1/*
2    This file is part of libmicrospdy
3    Copyright Copyright (C) 2012 Andrey Uzunov
4
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation, either version 3 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17*/
18
19/**
20 * @file session.c
21 * @brief  TCP connection/SPDY session handling. So far most of the
22 * 			functions for handling SPDY framing layer are here.
23 * @author Andrey Uzunov
24 */
25
26#include "platform.h"
27#include "structures.h"
28#include "internal.h"
29#include "session.h"
30#include "compression.h"
31#include "stream.h"
32#include "io.h"
33
34
35/**
36 * Handler for reading the full SYN_STREAM frame after we know that
37 * the frame is such.
38 * The function waits for the full frame and then changes status
39 * of the session. New stream is created.
40 *
41 * @param session SPDY_Session whose read buffer is used.
42 */
43static void
44spdyf_handler_read_syn_stream (struct SPDY_Session *session)
45{
46  size_t name_value_strm_size = 0;
47  unsigned int compressed_data_size;
48  int ret;
49  void *name_value_strm = NULL;
50  struct SPDYF_Control_Frame *frame;
51  struct SPDY_NameValue *headers;
52
53  SPDYF_ASSERT(SPDY_SESSION_STATUS_WAIT_FOR_SUBHEADER == session->status
54               || SPDY_SESSION_STATUS_WAIT_FOR_BODY == session->status,
55               "the function is called wrong");
56
57  frame = (struct SPDYF_Control_Frame *)session->frame_handler_cls;
58
59  //handle subheaders
60  if(SPDY_SESSION_STATUS_WAIT_FOR_SUBHEADER == session->status)
61    {
62      if(0 == frame->length)
63        {
64          //protocol error: incomplete frame
65          //we just ignore it since there is no stream id for which to
66          //send RST_STREAM
67          //TODO maybe GOAWAY and closing session is appropriate
68          SPDYF_DEBUG("zero long SYN_STREAM received");
69          session->status = SPDY_SESSION_STATUS_WAIT_FOR_HEADER;
70          free(frame);
71          return;
72        }
73
74      if(SPDY_YES != SPDYF_stream_new(session))
75        {
76          /* waiting for some more fields to create new stream
77             or something went wrong, SPDYF_stream_new has handled the
78             situation */
79          return;
80        }
81
82      session->current_stream_id = session->streams_head->stream_id;
83      if(frame->length > SPDY_MAX_SUPPORTED_FRAME_SIZE)
84        {
85          //TODO no need to create stream if this happens
86          session->status = SPDY_SESSION_STATUS_IGNORE_BYTES;
87          return;
88        }
89      else
90        session->status = SPDY_SESSION_STATUS_WAIT_FOR_BODY;
91    }
92
93  //handle body
94
95  //start reading the compressed name/value pairs (http headers)
96  compressed_data_size = frame->length //everything after length field
97    - 10;//4B stream id, 4B assoc strem id, 2B priority, unused and slot
98
99  if(session->read_buffer_offset - session->read_buffer_beginning < compressed_data_size)
100    {
101      // the full frame is not yet here, try later
102      return;
103    }
104
105  if ( (compressed_data_size > 0) &&
106       (SPDY_YES !=
107        SPDYF_zlib_inflate(&session->zlib_recv_stream,
108                           session->read_buffer + session->read_buffer_beginning,
109                           compressed_data_size,
110                           &name_value_strm,
111                           &name_value_strm_size)) )
112    {
113      /* something went wrong on inflating,
114       * the state of the stream for decompression is unknown
115       * and we may not be able to read anything more received on
116       * this session,
117       * so it is better to close the session */
118      free(name_value_strm);
119      free(frame);
120
121      /* mark the session for closing and close it, when
122       * everything on the output queue is already written */
123      session->status = SPDY_SESSION_STATUS_FLUSHING;
124
125      SPDYF_prepare_goaway(session, SPDY_GOAWAY_STATUS_INTERNAL_ERROR, false);
126
127      return;
128    }
129
130  if(0 == name_value_strm_size || 0 == compressed_data_size)
131    {
132      //Protocol error: send RST_STREAM
133      if(SPDY_YES != SPDYF_prepare_rst_stream(session, session->streams_head,
134                                              SPDY_RST_STREAM_STATUS_PROTOCOL_ERROR))
135        {
136          //no memory, try later to send RST
137          free(name_value_strm);
138          return;
139        }
140    }
141  else
142    {
143      ret = SPDYF_name_value_from_stream(name_value_strm, name_value_strm_size, &headers);
144      if(SPDY_NO == ret)
145        {
146          //memory error, try later
147          free(name_value_strm);
148          return;
149        }
150
151      session->streams_head->headers = headers;
152      //inform the application layer for the new stream received
153      if(SPDY_YES != session->daemon->fnew_stream_cb(session->daemon->fcls, session->streams_head))
154        {
155          //memory error, try later
156          free(name_value_strm);
157          return;
158        }
159
160      session->read_buffer_beginning += compressed_data_size;
161    }
162
163  //SPDYF_DEBUG("syn_stream received: id %i", session->current_stream_id);
164
165  //change state to wait for new frame
166  free(name_value_strm);
167  session->status = SPDY_SESSION_STATUS_WAIT_FOR_HEADER;
168  free(frame);
169}
170
171
172/**
173 * Handler for reading the GOAWAY frame after we know that
174 * the frame is such.
175 * The function waits for the full frame and then changes status
176 * of the session.
177 *
178 * @param session SPDY_Session whose read buffer is used.
179 */
180static void
181spdyf_handler_read_goaway (struct SPDY_Session *session)
182{
183	struct SPDYF_Control_Frame *frame;
184	uint32_t last_good_stream_id;
185	uint32_t status_int;
186	enum SPDY_GOAWAY_STATUS status;
187
188	SPDYF_ASSERT(SPDY_SESSION_STATUS_WAIT_FOR_SUBHEADER == session->status,
189		"the function is called wrong");
190
191	frame = (struct SPDYF_Control_Frame *)session->frame_handler_cls;
192
193	if(frame->length > SPDY_MAX_SUPPORTED_FRAME_SIZE)
194	{
195		//this is a protocol error/attack
196		session->status = SPDY_SESSION_STATUS_IGNORE_BYTES;
197		return;
198	}
199
200	if(0 != frame->flags || 8 != frame->length)
201	{
202		//this is a protocol error
203		SPDYF_DEBUG("wrong GOAWAY received");
204		//anyway, it will be handled
205	}
206
207	if((session->read_buffer_offset - session->read_buffer_beginning) < frame->length)
208	{
209		//not all fields are received
210		//try later
211		return;
212	}
213
214	//mark that the session is almost closed
215	session->is_goaway_received = true;
216
217	if(8 == frame->length)
218	{
219		memcpy(&last_good_stream_id, session->read_buffer + session->read_buffer_beginning, 4);
220		last_good_stream_id = NTOH31(last_good_stream_id);
221		session->read_buffer_beginning += 4;
222
223		memcpy(&status_int, session->read_buffer + session->read_buffer_beginning, 4);
224		status = ntohl(status_int);
225		session->read_buffer_beginning += 4;
226
227		//TODO do something with last_good
228
229		//SPDYF_DEBUG("Received GOAWAY; status=%i; lastgood=%i",status,last_good_stream_id);
230
231		//do something according to the status
232		//TODO
233		switch(status)
234		{
235			case SPDY_GOAWAY_STATUS_OK:
236				break;
237			case SPDY_GOAWAY_STATUS_PROTOCOL_ERROR:
238				break;
239			case SPDY_GOAWAY_STATUS_INTERNAL_ERROR:
240				break;
241		}
242
243    //SPDYF_DEBUG("goaway received: status %i", status);
244	}
245
246	session->status = SPDY_SESSION_STATUS_WAIT_FOR_HEADER;
247	free(frame);
248}
249
250
251/**
252 * Handler for reading RST_STREAM frames. After receiving the frame
253 * the stream moves into closed state and status
254 * of the session is changed. Frames, belonging to this stream, which
255 * are still at the output queue, will be ignored later.
256 *
257 * @param session SPDY_Session whose read buffer is used.
258 */
259static void
260spdyf_handler_read_rst_stream (struct SPDY_Session *session)
261{
262	struct SPDYF_Control_Frame *frame;
263	uint32_t stream_id;
264	int32_t status_int;
265	//enum SPDY_RST_STREAM_STATUS status; //for debug
266	struct SPDYF_Stream *stream;
267
268	SPDYF_ASSERT(SPDY_SESSION_STATUS_WAIT_FOR_SUBHEADER == session->status,
269		"the function is called wrong");
270
271	frame = (struct SPDYF_Control_Frame *)session->frame_handler_cls;
272
273	if(0 != frame->flags || 8 != frame->length)
274	{
275		//this is a protocol error
276		SPDYF_DEBUG("wrong RST_STREAM received");
277		//ignore as a large frame
278		session->status = SPDY_SESSION_STATUS_IGNORE_BYTES;
279		return;
280	}
281
282	if((session->read_buffer_offset - session->read_buffer_beginning) < frame->length)
283	{
284		//not all fields are received
285		//try later
286		return;
287	}
288
289    memcpy(&stream_id, session->read_buffer + session->read_buffer_beginning, 4);
290	stream_id = NTOH31(stream_id);
291	session->read_buffer_beginning += 4;
292
293    memcpy(&status_int, session->read_buffer + session->read_buffer_beginning, 4);
294	//status = ntohl(status_int); //for debug
295	session->read_buffer_beginning += 4;
296
297	session->status = SPDY_SESSION_STATUS_WAIT_FOR_HEADER;
298	free(frame);
299
300	//mark the stream as closed
301	stream = session->streams_head;
302	while(NULL != stream)
303	{
304		if(stream_id == stream->stream_id)
305		{
306			stream->is_in_closed = true;
307			stream->is_out_closed = true;
308			break;
309		}
310		stream = stream->next;
311	}
312
313	//SPDYF_DEBUG("Received RST_STREAM; status=%i; id=%i",status,stream_id);
314
315	//do something according to the status
316	//TODO
317	/*switch(status)
318	{
319		case SPDY_RST_STREAM_STATUS_PROTOCOL_ERROR:
320			break;
321	}*/
322}
323
324
325/**
326 * Handler for reading DATA frames. In requests they are used for POST
327 * arguments.
328 *
329 * @param session SPDY_Session whose read buffer is used.
330 */
331static void
332spdyf_handler_read_data (struct SPDY_Session *session)
333{
334  int ret;
335  struct SPDYF_Data_Frame * frame;
336  struct SPDYF_Stream * stream;
337
338	SPDYF_ASSERT(SPDY_SESSION_STATUS_WAIT_FOR_SUBHEADER == session->status
339		|| SPDY_SESSION_STATUS_WAIT_FOR_BODY == session->status,
340		"the function is called wrong");
341
342  //SPDYF_DEBUG("DATA frame received (POST?). Ignoring");
343
344  //SPDYF_SIGINT("");
345
346	frame = (struct SPDYF_Data_Frame *)session->frame_handler_cls;
347
348	//handle subheaders
349	if(SPDY_SESSION_STATUS_WAIT_FOR_SUBHEADER == session->status)
350	{
351		if(frame->length > SPDY_MAX_SUPPORTED_FRAME_SIZE)
352		{
353			session->status = SPDY_SESSION_STATUS_IGNORE_BYTES;
354			return;
355		}
356		else
357			session->status = SPDY_SESSION_STATUS_WAIT_FOR_BODY;
358	}
359
360	//handle body
361
362	if(session->read_buffer_offset - session->read_buffer_beginning
363		>= frame->length)
364	{
365    stream = SPDYF_stream_find(frame->stream_id, session);
366
367    if(NULL == stream || stream->is_in_closed || NULL == session->daemon->received_data_cb)
368    {
369      if(NULL == session->daemon->received_data_cb)
370      SPDYF_DEBUG("No callback for DATA frame set; Ignoring DATA frame!");
371
372      //TODO send error?
373
374      //TODO for now ignore frame
375      session->read_buffer_beginning += frame->length;
376      session->status = SPDY_SESSION_STATUS_WAIT_FOR_HEADER;
377      free(frame);
378      return;
379    }
380
381    ret = session->daemon->freceived_data_cb(session->daemon->cls,
382                                      stream,
383                                      session->read_buffer + session->read_buffer_beginning,
384                                      frame->length,
385                                      0 == (SPDY_DATA_FLAG_FIN & frame->flags));
386
387    session->read_buffer_beginning += frame->length;
388
389    stream->window_size -= frame->length;
390
391    //TODO close in and send rst maybe
392    SPDYF_ASSERT(SPDY_YES == ret, "Cancel POST data is not yet implemented");
393
394    if(SPDY_DATA_FLAG_FIN & frame->flags)
395    {
396      stream->is_in_closed = true;
397    }
398    else if(stream->window_size < SPDYF_INITIAL_WINDOW_SIZE / 2)
399    {
400      //very simple implementation of flow control
401      //when the window's size is under the half of the initial value,
402      //increase it again up to the initial value
403
404      //prepare WINDOW_UPDATE
405      if(SPDY_YES == SPDYF_prepare_window_update(session, stream,
406            SPDYF_INITIAL_WINDOW_SIZE - stream->window_size))
407      {
408        stream->window_size = SPDYF_INITIAL_WINDOW_SIZE;
409      }
410      //else: do it later
411    }
412
413    //SPDYF_DEBUG("data received: id %i", frame->stream_id);
414
415    session->status = SPDY_SESSION_STATUS_WAIT_FOR_HEADER;
416    free(frame);
417	}
418}
419
420
421int
422SPDYF_handler_write_syn_reply (struct SPDY_Session *session)
423{
424	struct SPDYF_Response_Queue *response_queue = session->response_queue_head;
425	struct SPDYF_Stream *stream = response_queue->stream;
426	struct SPDYF_Control_Frame control_frame;
427	void *compressed_headers = NULL;
428	size_t compressed_headers_size=0;
429	size_t used_data=0;
430	size_t total_size;
431	uint32_t stream_id_nbo;
432
433	SPDYF_ASSERT(NULL == session->write_buffer, "the function is called not in the correct moment");
434
435	memcpy(&control_frame, response_queue->control_frame, sizeof(control_frame));
436
437	if(SPDY_YES != SPDYF_zlib_deflate(&session->zlib_send_stream,
438		response_queue->data,
439		response_queue->data_size,
440		&used_data,
441		&compressed_headers,
442		&compressed_headers_size))
443	{
444		/* something went wrong on compressing,
445		* the state of the stream for compression is unknown
446		* and we may not be able to send anything more on
447		* this session,
448		* so it is better to close the session right now */
449		session->status = SPDY_SESSION_STATUS_CLOSING;
450
451		free(compressed_headers);
452
453		return SPDY_NO;
454	}
455
456	//TODO do we need this used_Data
457	SPDYF_ASSERT(used_data == response_queue->data_size, "not everything was used by zlib");
458
459	total_size = sizeof(struct SPDYF_Control_Frame) //SPDY header
460		+ 4 // stream id as "subheader"
461		+ compressed_headers_size;
462
463	if(NULL == (session->write_buffer = malloc(total_size)))
464	{
465		/* no memory
466		 * since we do not save the compressed data anywhere and
467		 * the sending zlib stream is already in new state, we must
468		 * close the session */
469		session->status = SPDY_SESSION_STATUS_CLOSING;
470
471		free(compressed_headers);
472
473		return SPDY_NO;
474	}
475	session->write_buffer_beginning = 0;
476	session->write_buffer_offset = 0;
477	session->write_buffer_size = total_size;
478
479	control_frame.length = compressed_headers_size + 4; // compressed data + stream_id
480	SPDYF_CONTROL_FRAME_HTON(&control_frame);
481
482	//put frame headers to write buffer
483	memcpy(session->write_buffer + session->write_buffer_offset,&control_frame,sizeof(struct SPDYF_Control_Frame));
484	session->write_buffer_offset +=  sizeof(struct SPDYF_Control_Frame);
485
486	//put stream id to write buffer
487	stream_id_nbo = HTON31(stream->stream_id);
488	memcpy(session->write_buffer + session->write_buffer_offset, &stream_id_nbo, 4);
489	session->write_buffer_offset += 4;
490
491	//put compressed name/value pairs to write buffer
492	memcpy(session->write_buffer + session->write_buffer_offset, compressed_headers, compressed_headers_size);
493	session->write_buffer_offset +=  compressed_headers_size;
494
495	SPDYF_ASSERT(0 == session->write_buffer_beginning, "bug1");
496	SPDYF_ASSERT(session->write_buffer_offset == session->write_buffer_size, "bug2");
497
498	//DEBUG CODE, break compression state to see what happens
499/*	SPDYF_zlib_deflate(&session->zlib_send_stream,
500		"1234567890",
501		10,
502		&used_data,
503		&compressed_headers,
504		&compressed_headers_size);
505*/
506	free(compressed_headers);
507
508	session->last_replied_to_stream_id = stream->stream_id;
509
510  //SPDYF_DEBUG("syn_reply sent: id %i", stream->stream_id);
511
512	return SPDY_YES;
513}
514
515
516int
517SPDYF_handler_write_goaway (struct SPDY_Session *session)
518{
519	struct SPDYF_Response_Queue *response_queue = session->response_queue_head;
520	struct SPDYF_Control_Frame control_frame;
521	size_t total_size;
522	int last_good_stream_id;
523
524	SPDYF_ASSERT(NULL == session->write_buffer, "the function is called not in the correct moment");
525
526	memcpy(&control_frame, response_queue->control_frame, sizeof(control_frame));
527
528	session->is_goaway_sent = true;
529
530	total_size = sizeof(struct SPDYF_Control_Frame) //SPDY header
531		+ 4 // last good stream id as "subheader"
532		+ 4; // status code as "subheader"
533
534	if(NULL == (session->write_buffer = malloc(total_size)))
535	{
536		return SPDY_NO;
537	}
538	session->write_buffer_beginning = 0;
539	session->write_buffer_offset = 0;
540	session->write_buffer_size = total_size;
541
542	control_frame.length = 8; // always for GOAWAY
543	SPDYF_CONTROL_FRAME_HTON(&control_frame);
544
545	//put frame headers to write buffer
546	memcpy(session->write_buffer + session->write_buffer_offset,&control_frame,sizeof(struct SPDYF_Control_Frame));
547	session->write_buffer_offset +=  sizeof(struct SPDYF_Control_Frame);
548
549	//put last good stream id to write buffer
550	last_good_stream_id = HTON31(session->last_replied_to_stream_id);
551	memcpy(session->write_buffer + session->write_buffer_offset, &last_good_stream_id, 4);
552	session->write_buffer_offset +=  4;
553
554	//put "data" to write buffer. This is the status
555	memcpy(session->write_buffer + session->write_buffer_offset, response_queue->data, 4);
556	session->write_buffer_offset +=  4;
557	//data is not freed by the destroy function so:
558	//free(response_queue->data);
559
560  //SPDYF_DEBUG("goaway sent: status %i", NTOH31(*(uint32_t*)(response_queue->data)));
561
562	SPDYF_ASSERT(0 == session->write_buffer_beginning, "bug1");
563	SPDYF_ASSERT(session->write_buffer_offset == session->write_buffer_size, "bug2");
564
565	return SPDY_YES;
566}
567
568
569int
570SPDYF_handler_write_data (struct SPDY_Session *session)
571{
572	struct SPDYF_Response_Queue *response_queue = session->response_queue_head;
573	struct SPDYF_Response_Queue *new_response_queue;
574	size_t total_size;
575	struct SPDYF_Data_Frame data_frame;
576	ssize_t ret;
577	bool more;
578
579	SPDYF_ASSERT(NULL == session->write_buffer, "the function is called not in the correct moment");
580
581	memcpy(&data_frame, response_queue->data_frame, sizeof(data_frame));
582
583	if(NULL == response_queue->response->rcb)
584	{
585		//standard response with data into the struct
586		SPDYF_ASSERT(NULL != response_queue->data, "no data for the response");
587
588		total_size = sizeof(struct SPDYF_Data_Frame) //SPDY header
589			+ response_queue->data_size;
590
591		if(NULL == (session->write_buffer = malloc(total_size)))
592		{
593			return SPDY_NO;
594		}
595		session->write_buffer_beginning = 0;
596		session->write_buffer_offset = 0;
597		session->write_buffer_size = total_size;
598
599		data_frame.length = response_queue->data_size;
600		SPDYF_DATA_FRAME_HTON(&data_frame);
601
602		//put SPDY headers to the writing buffer
603		memcpy(session->write_buffer + session->write_buffer_offset,&data_frame,sizeof(struct SPDYF_Data_Frame));
604		session->write_buffer_offset +=  sizeof(struct SPDYF_Data_Frame);
605
606		//put data to the writing buffer
607		memcpy(session->write_buffer + session->write_buffer_offset, response_queue->data, response_queue->data_size);
608		session->write_buffer_offset +=  response_queue->data_size;
609	}
610	else
611	{
612		/* response with callbacks. The lib will produce more than 1
613		 * data frames
614		 */
615
616		total_size = sizeof(struct SPDYF_Data_Frame) //SPDY header
617			+ SPDY_MAX_SUPPORTED_FRAME_SIZE; //max possible size
618
619		if(NULL == (session->write_buffer = malloc(total_size)))
620		{
621			return SPDY_NO;
622		}
623		session->write_buffer_beginning = 0;
624		session->write_buffer_offset = 0;
625		session->write_buffer_size = total_size;
626
627		ret = response_queue->response->rcb(response_queue->response->rcb_cls,
628			session->write_buffer + sizeof(struct SPDYF_Data_Frame),
629			response_queue->response->rcb_block_size,
630			&more);
631
632		if(ret < 0 || ret > response_queue->response->rcb_block_size)
633		{
634			free(session->write_buffer);
635      session->write_buffer = NULL;
636
637      //send RST_STREAM
638      if(SPDY_YES == (ret = SPDYF_prepare_rst_stream(session,
639        response_queue->stream,
640        SPDY_RST_STREAM_STATUS_INTERNAL_ERROR)))
641      {
642        return SPDY_NO;
643      }
644
645      //else no memory
646			//for now close session
647			//TODO what?
648			session->status = SPDY_SESSION_STATUS_CLOSING;
649
650			return SPDY_NO;
651		}
652		if(0 == ret && more)
653		{
654			//the app couldn't write anything to buf but later will
655			free(session->write_buffer);
656			session->write_buffer = NULL;
657			session->write_buffer_size = 0;
658
659			if(NULL != response_queue->next)
660			{
661				//put the frame at the end of the queue
662				//otherwise - head of line blocking
663				session->response_queue_head = response_queue->next;
664				session->response_queue_head->prev = NULL;
665				session->response_queue_tail->next = response_queue;
666				response_queue->prev = session->response_queue_tail;
667				response_queue->next = NULL;
668				session->response_queue_tail = response_queue;
669			}
670
671			return SPDY_YES;
672		}
673
674		if(more)
675		{
676			//create another response queue object to call the user cb again
677			if(NULL == (new_response_queue = SPDYF_response_queue_create(true,
678							NULL,
679							0,
680							response_queue->response,
681							response_queue->stream,
682							false,
683							response_queue->frqcb,
684							response_queue->frqcb_cls,
685							response_queue->rrcb,
686							response_queue->rrcb_cls)))
687			{
688				//TODO send RST_STREAM
689				//for now close session
690				session->status = SPDY_SESSION_STATUS_CLOSING;
691
692				free(session->write_buffer);
693        session->write_buffer = NULL;
694				return SPDY_NO;
695			}
696
697			//put it at second position on the queue
698			new_response_queue->prev = response_queue;
699			new_response_queue->next = response_queue->next;
700			if(NULL == response_queue->next)
701			{
702				session->response_queue_tail = new_response_queue;
703			}
704			else
705			{
706				response_queue->next->prev = new_response_queue;
707			}
708			response_queue->next = new_response_queue;
709
710			response_queue->frqcb = NULL;
711			response_queue->frqcb_cls = NULL;
712			response_queue->rrcb = NULL;
713			response_queue->rrcb_cls = NULL;
714		}
715		else
716		{
717			data_frame.flags |= SPDY_DATA_FLAG_FIN;
718		}
719
720		data_frame.length = ret;
721		SPDYF_DATA_FRAME_HTON(&data_frame);
722
723		//put SPDY headers to the writing buffer
724		memcpy(session->write_buffer + session->write_buffer_offset,
725			&data_frame,
726			sizeof(struct SPDYF_Data_Frame));
727		session->write_buffer_offset +=  sizeof(struct SPDYF_Data_Frame);
728		session->write_buffer_offset +=  ret;
729		session->write_buffer_size = session->write_buffer_offset;
730	}
731
732  //SPDYF_DEBUG("data sent: id %i", NTOH31(data_frame.stream_id));
733
734	SPDYF_ASSERT(0 == session->write_buffer_beginning, "bug1");
735	SPDYF_ASSERT(session->write_buffer_offset == session->write_buffer_size, "bug2");
736
737	return SPDY_YES;
738}
739
740
741int
742SPDYF_handler_write_rst_stream (struct SPDY_Session *session)
743{
744	struct SPDYF_Response_Queue *response_queue = session->response_queue_head;
745	struct SPDYF_Control_Frame control_frame;
746	size_t total_size;
747
748	SPDYF_ASSERT(NULL == session->write_buffer, "the function is called not in the correct moment");
749
750	memcpy(&control_frame, response_queue->control_frame, sizeof(control_frame));
751
752	total_size = sizeof(struct SPDYF_Control_Frame) //SPDY header
753		+ 4 // stream id as "subheader"
754		+ 4; // status code as "subheader"
755
756	if(NULL == (session->write_buffer = malloc(total_size)))
757	{
758		return SPDY_NO;
759	}
760	session->write_buffer_beginning = 0;
761	session->write_buffer_offset = 0;
762	session->write_buffer_size = total_size;
763
764	control_frame.length = 8; // always for RST_STREAM
765	SPDYF_CONTROL_FRAME_HTON(&control_frame);
766
767	//put frame headers to write buffer
768	memcpy(session->write_buffer + session->write_buffer_offset,&control_frame,sizeof(struct SPDYF_Control_Frame));
769	session->write_buffer_offset +=  sizeof(struct SPDYF_Control_Frame);
770
771	//put stream id to write buffer. This is the status
772	memcpy(session->write_buffer + session->write_buffer_offset, response_queue->data, 8);
773	session->write_buffer_offset +=  8;
774	//data is not freed by the destroy function so:
775	//free(response_queue->data);
776
777  //SPDYF_DEBUG("rst_stream sent: id %i", NTOH31((((uint64_t)response_queue->data) & 0xFFFF0000) >> 32));
778
779	SPDYF_ASSERT(0 == session->write_buffer_beginning, "bug1");
780	SPDYF_ASSERT(session->write_buffer_offset == session->write_buffer_size, "bug2");
781
782	return SPDY_YES;
783}
784
785
786int
787SPDYF_handler_write_window_update (struct SPDY_Session *session)
788{
789	struct SPDYF_Response_Queue *response_queue = session->response_queue_head;
790	struct SPDYF_Control_Frame control_frame;
791	size_t total_size;
792
793	SPDYF_ASSERT(NULL == session->write_buffer, "the function is called not in the correct moment");
794
795	memcpy(&control_frame, response_queue->control_frame, sizeof(control_frame));
796
797	total_size = sizeof(struct SPDYF_Control_Frame) //SPDY header
798		+ 4 // stream id as "subheader"
799		+ 4; // delta-window-size as "subheader"
800
801	if(NULL == (session->write_buffer = malloc(total_size)))
802	{
803		return SPDY_NO;
804	}
805	session->write_buffer_beginning = 0;
806	session->write_buffer_offset = 0;
807	session->write_buffer_size = total_size;
808
809	control_frame.length = 8; // always for WINDOW_UPDATE
810	SPDYF_CONTROL_FRAME_HTON(&control_frame);
811
812	//put frame headers to write buffer
813	memcpy(session->write_buffer + session->write_buffer_offset,&control_frame,sizeof(struct SPDYF_Control_Frame));
814	session->write_buffer_offset +=  sizeof(struct SPDYF_Control_Frame);
815
816	//put stream id and delta-window-size to write buffer
817	memcpy(session->write_buffer + session->write_buffer_offset, response_queue->data, 8);
818	session->write_buffer_offset +=  8;
819
820  //SPDYF_DEBUG("window_update sent: id %i", NTOH31((((uint64_t)response_queue->data) & 0xFFFF0000) >> 32));
821
822	SPDYF_ASSERT(0 == session->write_buffer_beginning, "bug1");
823	SPDYF_ASSERT(session->write_buffer_offset == session->write_buffer_size, "bug2");
824
825	return SPDY_YES;
826}
827
828
829void
830SPDYF_handler_ignore_frame (struct SPDY_Session *session)
831{
832	struct SPDYF_Control_Frame *frame;
833
834	SPDYF_ASSERT(SPDY_SESSION_STATUS_WAIT_FOR_SUBHEADER == session->status
835		|| SPDY_SESSION_STATUS_WAIT_FOR_BODY == session->status,
836		"the function is called wrong");
837
838
839	frame = (struct SPDYF_Control_Frame *)session->frame_handler_cls;
840
841	//handle subheaders
842	if(SPDY_SESSION_STATUS_WAIT_FOR_SUBHEADER == session->status)
843	{
844		if(frame->length > SPDY_MAX_SUPPORTED_FRAME_SIZE)
845		{
846			session->status = SPDY_SESSION_STATUS_IGNORE_BYTES;
847			return;
848		}
849		else
850			session->status = SPDY_SESSION_STATUS_WAIT_FOR_BODY;
851	}
852
853	//handle body
854
855	if(session->read_buffer_offset - session->read_buffer_beginning
856		>= frame->length)
857	{
858		session->read_buffer_beginning += frame->length;
859		session->status = SPDY_SESSION_STATUS_WAIT_FOR_HEADER;
860		free(frame);
861	}
862}
863
864
865int
866SPDYF_session_read (struct SPDY_Session *session)
867{
868	int bytes_read;
869	bool reallocate;
870	size_t actual_buf_size;
871
872	if(SPDY_SESSION_STATUS_CLOSING == session->status
873		|| SPDY_SESSION_STATUS_FLUSHING == session->status)
874		return SPDY_NO;
875
876	//if the read buffer is full to the end, we need to reallocate space
877	if (session->read_buffer_size == session->read_buffer_offset)
878	{
879		//but only if the state of the session requires it
880		//i.e. no further proceeding is possible without reallocation
881		reallocate = false;
882		actual_buf_size = session->read_buffer_offset
883			- session->read_buffer_beginning;
884		switch(session->status)
885		{
886			case SPDY_SESSION_STATUS_WAIT_FOR_HEADER:
887
888			case SPDY_SESSION_STATUS_IGNORE_BYTES:
889				//we need space for a whole control frame header
890				if(actual_buf_size < sizeof(struct SPDYF_Control_Frame))
891					reallocate = true;
892				break;
893
894			case SPDY_SESSION_STATUS_WAIT_FOR_SUBHEADER:
895
896			case SPDY_SESSION_STATUS_WAIT_FOR_BODY:
897				//we need as many bytes as set in length field of the
898				//header
899				SPDYF_ASSERT(NULL != session->frame_handler_cls,
900					"no frame for session");
901				if(session->frame_handler != &spdyf_handler_read_data)
902				{
903					if(actual_buf_size
904						< ((struct SPDYF_Control_Frame *)session->frame_handler_cls)->length)
905						reallocate = true;
906				}
907				else
908				{
909					if(actual_buf_size
910						< ((struct SPDYF_Data_Frame *)session->frame_handler_cls)->length)
911						reallocate = true;
912				}
913				break;
914
915			case SPDY_SESSION_STATUS_CLOSING:
916			case SPDY_SESSION_STATUS_FLUSHING:
917				//nothing needed
918				break;
919		}
920
921		if(reallocate)
922		{
923			//reuse the space in the buffer that was already read by the lib
924			memmove(session->read_buffer,
925				session->read_buffer + session->read_buffer_beginning,
926				session->read_buffer_offset - session->read_buffer_beginning);
927
928			session->read_buffer_offset -= session->read_buffer_beginning;
929			session->read_buffer_beginning = 0;
930		}
931		else
932		{
933			//will read next time
934			//TODO optimize it, memmove more often?
935			return SPDY_NO;
936		}
937	}
938
939	session->last_activity = SPDYF_monotonic_time();
940
941	//actual read from the TLS socket
942	bytes_read = session->fio_recv(session,
943					session->read_buffer + session->read_buffer_offset,
944					session->read_buffer_size - session->read_buffer_offset);
945
946	switch(bytes_read)
947	{
948		case SPDY_IO_ERROR_CLOSED:
949			//The TLS connection was closed by the other party, clean
950			//or not
951			shutdown (session->socket_fd, SHUT_RD);
952			session->read_closed = true;
953			session->status = SPDY_SESSION_STATUS_CLOSING;
954			return SPDY_YES;
955
956		case SPDY_IO_ERROR_ERROR:
957			//any kind of error in the TLS subsystem
958			//try to prepare GOAWAY frame
959			SPDYF_prepare_goaway(session, SPDY_GOAWAY_STATUS_INTERNAL_ERROR, false);
960			//try to flush the queue when write is called
961			session->status = SPDY_SESSION_STATUS_FLUSHING;
962			return SPDY_YES;
963
964		case SPDY_IO_ERROR_AGAIN:
965			//read or write should be called again; leave it for the
966			//next time
967			return SPDY_NO;
968
969		//default:
970			//something was really read from the TLS subsystem
971			//just continue
972	}
973
974	session->read_buffer_offset += bytes_read;
975
976	return SPDY_YES;
977}
978
979
980int
981SPDYF_session_write (struct SPDY_Session *session,
982                     bool only_one_frame)
983{
984	unsigned int i;
985	int bytes_written;
986	struct SPDYF_Response_Queue *queue_head;
987	struct SPDYF_Response_Queue *response_queue;
988
989	if(SPDY_SESSION_STATUS_CLOSING == session->status)
990		return SPDY_NO;
991
992  if(SPDY_NO == session->fio_before_write(session))
993    return SPDY_NO;
994
995	for(i=0;
996		only_one_frame
997		? i < 1
998		: i < session->max_num_frames;
999		++i)
1000	{
1001		//if the buffer is not null, part of the last frame is still
1002		//pending to be sent
1003		if(NULL == session->write_buffer)
1004		{
1005			//discard frames on closed streams
1006			response_queue = session->response_queue_head;
1007
1008			while(NULL != response_queue)
1009			{
1010				//if stream is closed, remove not yet sent frames
1011				//associated with it
1012				//GOAWAY frames are not associated to streams
1013				//and still need to be sent
1014				if(NULL == response_queue->stream
1015					|| !response_queue->stream->is_out_closed)
1016					break;
1017
1018				DLL_remove(session->response_queue_head,session->response_queue_tail,response_queue);
1019
1020				if(NULL != response_queue->frqcb)
1021				{
1022					response_queue->frqcb(response_queue->frqcb_cls, response_queue, SPDY_RESPONSE_RESULT_STREAM_CLOSED);
1023				}
1024
1025				SPDYF_response_queue_destroy(response_queue);
1026				response_queue = session->response_queue_head;
1027			}
1028
1029			if(NULL == session->response_queue_head)
1030				break;//nothing on the queue
1031
1032			//get next data from queue and put it to the write buffer
1033			// to send it
1034			if(SPDY_NO == session->response_queue_head->process_response_handler(session))
1035			{
1036				//error occured and the handler changed or not the
1037				//session's status appropriately
1038				if(SPDY_SESSION_STATUS_CLOSING == session->status)
1039				{
1040					//try to send GOAWAY first if the current frame is different
1041					if(session->response_queue_head->is_data
1042						|| SPDY_CONTROL_FRAME_TYPES_GOAWAY
1043							!= session->response_queue_head->control_frame->type)
1044					{
1045						session->status = SPDY_SESSION_STATUS_FLUSHING;
1046						SPDYF_prepare_goaway(session, SPDY_GOAWAY_STATUS_INTERNAL_ERROR, true);
1047						SPDYF_session_write(session,true);
1048						session->status = SPDY_SESSION_STATUS_CLOSING;
1049					}
1050					return SPDY_YES;
1051				}
1052
1053				//just return from the loop to return from this function
1054        ++i;
1055				break;
1056			}
1057
1058			//check if something was prepared for writing
1059			//on respones with callbacks it is possible that their is no
1060			//data available
1061			if(0 == session->write_buffer_size)//nothing to write
1062      {
1063				if(response_queue != session->response_queue_head)
1064				{
1065					//the handler modified the queue
1066					continue;
1067				}
1068				else
1069				{
1070					//no need to try the same frame again
1071          ++i;
1072					break;
1073				}
1074      }
1075		}
1076
1077		session->last_activity = SPDYF_monotonic_time();
1078
1079		//actual write to the IO
1080		bytes_written = session->fio_send(session,
1081			session->write_buffer + session->write_buffer_beginning,
1082			session->write_buffer_offset - session->write_buffer_beginning);
1083
1084		switch(bytes_written)
1085		{
1086			case SPDY_IO_ERROR_CLOSED:
1087				//The TLS connection was closed by the other party, clean
1088				//or not
1089				shutdown (session->socket_fd, SHUT_RD);
1090				session->read_closed = true;
1091				session->status = SPDY_SESSION_STATUS_CLOSING;
1092				return SPDY_YES;
1093
1094			case SPDY_IO_ERROR_ERROR:
1095				//any kind of error in the TLS subsystem
1096				//forbid more writing
1097				session->status = SPDY_SESSION_STATUS_CLOSING;
1098				return SPDY_YES;
1099
1100			case SPDY_IO_ERROR_AGAIN:
1101				//read or write should be called again; leave it for the
1102				//next time; return from the function as we do not now
1103				//whether reading or writing is needed
1104				return i>0 ? SPDY_YES : SPDY_NO;
1105
1106			//default:
1107				//something was really read from the TLS subsystem
1108				//just continue
1109		}
1110
1111		session->write_buffer_beginning += bytes_written;
1112
1113		//check if the full buffer was written
1114		if(session->write_buffer_beginning == session->write_buffer_size)
1115		{
1116			//that response is handled, remove it from queue
1117      free(session->write_buffer);
1118			session->write_buffer = NULL;
1119			session->write_buffer_size = 0;
1120			queue_head = session->response_queue_head;
1121			if(NULL == queue_head->next)
1122			{
1123				session->response_queue_head = NULL;
1124				session->response_queue_tail = NULL;
1125			}
1126			else
1127			{
1128				session->response_queue_head = queue_head->next;
1129				session->response_queue_head->prev = NULL;
1130			}
1131
1132			//set stream to closed if the frame's fin flag is set
1133			SPDYF_stream_set_flags_on_write(queue_head);
1134
1135			if(NULL != queue_head->frqcb)
1136			{
1137				//application layer callback to notify sending of the response
1138				queue_head->frqcb(queue_head->frqcb_cls, queue_head, SPDY_RESPONSE_RESULT_SUCCESS);
1139			}
1140
1141			SPDYF_response_queue_destroy(queue_head);
1142		}
1143	}
1144
1145	if(SPDY_SESSION_STATUS_FLUSHING == session->status
1146		&& NULL == session->response_queue_head)
1147		session->status = SPDY_SESSION_STATUS_CLOSING;
1148
1149	//return i>0 ? SPDY_YES : SPDY_NO;
1150	return session->fio_after_write(session, i>0 ? SPDY_YES : SPDY_NO);
1151}
1152
1153
1154int
1155SPDYF_session_idle (struct SPDY_Session *session)
1156{
1157	size_t read_buffer_beginning;
1158	size_t frame_length;
1159	struct SPDYF_Control_Frame* control_frame;
1160	struct SPDYF_Data_Frame *data_frame;
1161
1162	//prepare session for closing if timeout is used and already passed
1163	if(SPDY_SESSION_STATUS_CLOSING != session->status
1164		&& session->daemon->session_timeout
1165		&& (session->last_activity + session->daemon->session_timeout < SPDYF_monotonic_time()))
1166	{
1167		session->status = SPDY_SESSION_STATUS_CLOSING;
1168		//best effort for sending GOAWAY
1169		SPDYF_prepare_goaway(session, SPDY_GOAWAY_STATUS_OK, true);
1170		SPDYF_session_write(session,true);
1171	}
1172
1173	switch(session->status)
1174	{
1175		//expect new frame to arrive
1176		case SPDY_SESSION_STATUS_WAIT_FOR_HEADER:
1177			session->current_stream_id = 0;
1178			//check if the whole frame header is already here
1179			//both frame types have the same length
1180			if(session->read_buffer_offset - session->read_buffer_beginning
1181				< sizeof(struct SPDYF_Control_Frame))
1182				return SPDY_NO;
1183
1184			/* check the first bit to see if it is data or control frame
1185			 * and also if the version is supported */
1186			if(0x80 == *(uint8_t *)(session->read_buffer + session->read_buffer_beginning)
1187				&& SPDY_VERSION == *((uint8_t *)session->read_buffer + session->read_buffer_beginning + 1))
1188			{
1189				//control frame
1190				if(NULL == (control_frame = malloc(sizeof(struct SPDYF_Control_Frame))))
1191				{
1192					SPDYF_DEBUG("No memory");
1193					return SPDY_NO;
1194				}
1195
1196				//get frame headers
1197				memcpy(control_frame,
1198					session->read_buffer + session->read_buffer_beginning,
1199					sizeof(struct SPDYF_Control_Frame));
1200				session->read_buffer_beginning += sizeof(struct SPDYF_Control_Frame);
1201				SPDYF_CONTROL_FRAME_NTOH(control_frame);
1202
1203				session->status = SPDY_SESSION_STATUS_WAIT_FOR_SUBHEADER;
1204				//assign different frame handler according to frame type
1205				switch(control_frame->type){
1206					case SPDY_CONTROL_FRAME_TYPES_SYN_STREAM:
1207						session->frame_handler = &spdyf_handler_read_syn_stream;
1208						break;
1209					case SPDY_CONTROL_FRAME_TYPES_GOAWAY:
1210						session->frame_handler = &spdyf_handler_read_goaway;
1211						break;
1212					case SPDY_CONTROL_FRAME_TYPES_RST_STREAM:
1213						session->frame_handler = &spdyf_handler_read_rst_stream;
1214						break;
1215					default:
1216						session->frame_handler = &SPDYF_handler_ignore_frame;
1217				}
1218				session->frame_handler_cls = control_frame;
1219				//DO NOT break the outer case
1220			}
1221			else if(0 == *(uint8_t *)(session->read_buffer + session->read_buffer_beginning))
1222			{
1223				//needed for POST
1224				//data frame
1225				if(NULL == (data_frame = malloc(sizeof(struct SPDYF_Data_Frame))))
1226				{
1227					SPDYF_DEBUG("No memory");
1228					return SPDY_NO;
1229				}
1230
1231				//get frame headers
1232				memcpy(data_frame,
1233					session->read_buffer + session->read_buffer_beginning,
1234					sizeof(struct SPDYF_Data_Frame));
1235				session->read_buffer_beginning += sizeof(struct SPDYF_Data_Frame);
1236				SPDYF_DATA_FRAME_NTOH(data_frame);
1237
1238				session->status = SPDY_SESSION_STATUS_WAIT_FOR_BODY;
1239				session->frame_handler = &spdyf_handler_read_data;
1240				session->frame_handler_cls = data_frame;
1241				//DO NOT brake the outer case
1242			}
1243			else
1244			{
1245				SPDYF_DEBUG("another protocol or version received!");
1246
1247				/* According to the draft the lib should send here
1248				 * RST_STREAM with status UNSUPPORTED_VERSION. I don't
1249				 * see any sense of keeping the session open since
1250				 * we don't know how many bytes is the bogus "frame".
1251				 * And the latter normally will be HTTP request.
1252				 *
1253				 */
1254
1255				//shutdown(session->socket_fd, SHUT_RD);
1256				session->status = SPDY_SESSION_STATUS_FLUSHING;
1257				SPDYF_prepare_goaway(session, SPDY_GOAWAY_STATUS_PROTOCOL_ERROR,false);
1258				//SPDYF_session_write(session,false);
1259				/* close connection since the client expects another
1260				protocol from us */
1261				//SPDYF_session_close(session);
1262				return SPDY_YES;
1263			}
1264
1265		//expect specific header fields after the standard header
1266		case SPDY_SESSION_STATUS_WAIT_FOR_SUBHEADER:
1267			if(NULL!=session->frame_handler)
1268			{
1269				read_buffer_beginning = session->read_buffer_beginning;
1270				//if everything is ok, the "body" will also be processed
1271				//by the handler
1272				session->frame_handler(session);
1273
1274				if(SPDY_SESSION_STATUS_IGNORE_BYTES == session->status)
1275				{
1276					//check for larger than max supported frame
1277					if(session->frame_handler != &spdyf_handler_read_data)
1278					{
1279						frame_length = ((struct SPDYF_Control_Frame *)session->frame_handler_cls)->length;
1280					}
1281					else
1282					{
1283						frame_length = ((struct SPDYF_Data_Frame *)session->frame_handler_cls)->length;
1284					}
1285
1286					//if(SPDY_MAX_SUPPORTED_FRAME_SIZE < frame_length)
1287					{
1288						SPDYF_DEBUG("received frame with unsupported size: %zu", frame_length);
1289						//the data being received must be ignored and
1290						//RST_STREAM sent
1291
1292						//ignore bytes that will arive later
1293						session->read_ignore_bytes = frame_length
1294							+ read_buffer_beginning
1295							- session->read_buffer_offset;
1296						//ignore what is already in read buffer
1297						session->read_buffer_beginning = session->read_buffer_offset;
1298
1299						SPDYF_prepare_rst_stream(session,
1300							session->current_stream_id > 0 ? session->streams_head : NULL, //may be 0 here which is not good
1301							SPDY_RST_STREAM_STATUS_FRAME_TOO_LARGE);
1302
1303						//actually the read buffer can be bigger than the
1304						//max supported size
1305						session->status = session->read_ignore_bytes
1306							? SPDY_SESSION_STATUS_IGNORE_BYTES
1307							: SPDY_SESSION_STATUS_WAIT_FOR_HEADER;
1308
1309						free(session->frame_handler_cls);
1310					}
1311				}
1312			}
1313
1314			if(SPDY_SESSION_STATUS_IGNORE_BYTES != session->status)
1315			{
1316				break;
1317			}
1318
1319		//ignoring data in read buffer
1320		case SPDY_SESSION_STATUS_IGNORE_BYTES:
1321			SPDYF_ASSERT(session->read_ignore_bytes > 0,
1322				"Session is in wrong state");
1323			if(session->read_ignore_bytes
1324				> session->read_buffer_offset - session->read_buffer_beginning)
1325			{
1326				session->read_ignore_bytes -=
1327					session->read_buffer_offset - session->read_buffer_beginning;
1328				session->read_buffer_beginning = session->read_buffer_offset;
1329			}
1330			else
1331			{
1332				session->read_buffer_beginning += session->read_ignore_bytes;
1333				session->read_ignore_bytes = 0;
1334				session->status = SPDY_SESSION_STATUS_WAIT_FOR_HEADER;
1335			}
1336			break;
1337
1338		//expect frame body (name/value pairs)
1339		case SPDY_SESSION_STATUS_WAIT_FOR_BODY:
1340			if(NULL!=session->frame_handler)
1341				session->frame_handler(session);
1342			break;
1343
1344		case SPDY_SESSION_STATUS_FLUSHING:
1345
1346			return SPDY_NO;
1347
1348		//because of error the session needs to be closed
1349		case SPDY_SESSION_STATUS_CLOSING:
1350			//error should be already sent to the client
1351			SPDYF_session_close(session);
1352			return SPDY_YES;
1353	}
1354
1355	return SPDY_YES;
1356}
1357
1358
1359void
1360SPDYF_session_close (struct SPDY_Session *session)
1361{
1362	struct SPDY_Daemon *daemon = session->daemon;
1363	int by_client = session->read_closed ? SPDY_YES : SPDY_NO;
1364
1365	//shutdown the tls and deinit the tls context
1366	session->fio_close_session(session);
1367	shutdown (session->socket_fd,
1368		session->read_closed ? SHUT_WR : SHUT_RDWR);
1369	session->read_closed = true;
1370
1371	//remove session from the list
1372	DLL_remove (daemon->sessions_head,
1373		daemon->sessions_tail,
1374		session);
1375	//add the session for the list for cleaning up
1376	DLL_insert (daemon->cleanup_head,
1377		daemon->cleanup_tail,
1378		session);
1379
1380	//call callback for closed session
1381	if(NULL != daemon->session_closed_cb)
1382	{
1383		daemon->session_closed_cb(daemon->cls, session, by_client);
1384	}
1385}
1386
1387
1388int
1389SPDYF_session_accept(struct SPDY_Daemon *daemon)
1390{
1391	int new_socket_fd;
1392  int ret;
1393	struct SPDY_Session *session = NULL;
1394	socklen_t addr_len;
1395	struct sockaddr *addr;
1396
1397#if HAVE_INET6
1398	struct sockaddr_in6 addr6;
1399
1400	addr = (struct sockaddr *)&addr6;
1401	addr_len = sizeof(addr6);
1402#else
1403	struct sockaddr_in addr4;
1404
1405	addr = (struct sockaddr *)&addr4;
1406	addr_len = sizeof(addr6);
1407#endif
1408
1409  new_socket_fd = accept (daemon->socket_fd, addr, &addr_len);
1410
1411  if(new_socket_fd < 1)
1412		return SPDY_NO;
1413
1414	if (NULL == (session = malloc (sizeof (struct SPDY_Session))))
1415  {
1416		goto free_and_fail;
1417	}
1418	memset (session, 0, sizeof (struct SPDY_Session));
1419
1420	session->daemon = daemon;
1421	session->socket_fd = new_socket_fd;
1422  session->max_num_frames = daemon->max_num_frames;
1423
1424  ret = SPDYF_io_set_session(session, daemon->io_subsystem);
1425  SPDYF_ASSERT(SPDY_YES == ret, "Somehow daemon->io_subsystem iswrong here");
1426
1427	//init TLS context, handshake will be done
1428	if(SPDY_YES != session->fio_new_session(session))
1429	{
1430		goto free_and_fail;
1431	}
1432
1433	//read buffer
1434	session->read_buffer_size = SPDYF_BUFFER_SIZE;
1435	if (NULL == (session->read_buffer = malloc (session->read_buffer_size)))
1436    {
1437		session->fio_close_session(session);
1438		goto free_and_fail;
1439	}
1440
1441	//address of the client
1442	if (NULL == (session->addr = malloc (addr_len)))
1443    {
1444		session->fio_close_session(session);
1445		goto free_and_fail;
1446	}
1447	memcpy (session->addr, addr, addr_len);
1448
1449	session->addr_len = addr_len;
1450	session->status = SPDY_SESSION_STATUS_WAIT_FOR_HEADER;
1451
1452	//init zlib context for the whole session
1453	if(SPDY_YES != SPDYF_zlib_deflate_init(&session->zlib_send_stream))
1454    {
1455		session->fio_close_session(session);
1456		goto free_and_fail;
1457	}
1458	if(SPDY_YES != SPDYF_zlib_inflate_init(&session->zlib_recv_stream))
1459    {
1460		session->fio_close_session(session);
1461		SPDYF_zlib_deflate_end(&session->zlib_send_stream);
1462		goto free_and_fail;
1463	}
1464
1465	//add it to daemon's list
1466	DLL_insert(daemon->sessions_head,daemon->sessions_tail,session);
1467
1468	session->last_activity = SPDYF_monotonic_time();
1469
1470	if(NULL != daemon->new_session_cb)
1471		daemon->new_session_cb(daemon->cls, session);
1472
1473	return SPDY_YES;
1474
1475	//for GOTO
1476	free_and_fail:
1477	/* something failed, so shutdown, close and free memory */
1478	shutdown (new_socket_fd, SHUT_RDWR);
1479	(void)close (new_socket_fd);
1480
1481	if(NULL != session)
1482	{
1483		if(NULL != session->addr)
1484			free (session->addr);
1485		if(NULL != session->read_buffer)
1486			free (session->read_buffer);
1487		free (session);
1488	}
1489	return SPDY_NO;
1490}
1491
1492
1493void
1494SPDYF_queue_response (struct SPDYF_Response_Queue *response_to_queue,
1495						struct SPDY_Session *session,
1496						int consider_priority)
1497{
1498	struct SPDYF_Response_Queue *pos;
1499	struct SPDYF_Response_Queue *last;
1500	uint8_t priority;
1501
1502	SPDYF_ASSERT(SPDY_YES != consider_priority || NULL != response_to_queue->stream,
1503		"called with consider_priority but no stream provided");
1504
1505	last = response_to_queue;
1506	while(NULL != last->next)
1507	{
1508		last = last->next;
1509	}
1510
1511	if(SPDY_NO == consider_priority)
1512	{
1513		//put it at the end of the queue
1514		response_to_queue->prev = session->response_queue_tail;
1515		if (NULL == session->response_queue_head)
1516			session->response_queue_head = response_to_queue;
1517		else
1518			session->response_queue_tail->next = response_to_queue;
1519		session->response_queue_tail = last;
1520		return;
1521	}
1522	else if(-1 == consider_priority)
1523	{
1524		//put it at the head of the queue
1525		last->next = session->response_queue_head;
1526		if (NULL == session->response_queue_tail)
1527			session->response_queue_tail = last;
1528		else
1529			session->response_queue_head->prev = response_to_queue;
1530		session->response_queue_head = response_to_queue;
1531		return;
1532	}
1533
1534	if(NULL == session->response_queue_tail)
1535	{
1536		session->response_queue_head = response_to_queue;
1537		session->response_queue_tail = last;
1538		return;
1539	}
1540
1541	//search for the right position to put it
1542	pos = session->response_queue_tail;
1543	priority = response_to_queue->stream->priority;
1544	while(NULL != pos
1545		&& pos->stream->priority > priority)
1546	{
1547		pos = pos->prev;
1548	}
1549
1550	if(NULL == pos)
1551	{
1552		//put it on the head
1553		session->response_queue_head->prev = last;
1554		last->next = session->response_queue_head;
1555		session->response_queue_head = response_to_queue;
1556	}
1557	else if(NULL == pos->next)
1558	{
1559		//put it at the end
1560		response_to_queue->prev = pos;
1561		pos->next = response_to_queue;
1562		session->response_queue_tail = last;
1563	}
1564	else
1565	{
1566		response_to_queue->prev = pos;
1567		last->next = pos->next;
1568		pos->next = response_to_queue;
1569		last->next->prev = last;
1570	}
1571}
1572
1573
1574void
1575SPDYF_session_destroy(struct SPDY_Session *session)
1576{
1577	struct SPDYF_Stream *stream;
1578	struct SPDYF_Response_Queue *response_queue;
1579
1580	(void)close (session->socket_fd);
1581	SPDYF_zlib_deflate_end(&session->zlib_send_stream);
1582	SPDYF_zlib_inflate_end(&session->zlib_recv_stream);
1583
1584	//clean up unsent data in the output queue
1585	while (NULL != (response_queue = session->response_queue_head))
1586	{
1587		DLL_remove (session->response_queue_head,
1588			session->response_queue_tail,
1589			response_queue);
1590
1591		if(NULL != response_queue->frqcb)
1592		{
1593			response_queue->frqcb(response_queue->frqcb_cls, response_queue, SPDY_RESPONSE_RESULT_SESSION_CLOSED);
1594		}
1595
1596		SPDYF_response_queue_destroy(response_queue);
1597	}
1598
1599	//clean up the streams belonging to this session
1600	while (NULL != (stream = session->streams_head))
1601	{
1602		DLL_remove (session->streams_head,
1603			session->streams_tail,
1604			stream);
1605
1606		SPDYF_stream_destroy(stream);
1607	}
1608
1609	free(session->addr);
1610	free(session->read_buffer);
1611	free(session->write_buffer);
1612	free(session);
1613}
1614
1615
1616int
1617SPDYF_prepare_goaway (struct SPDY_Session *session,
1618					enum SPDY_GOAWAY_STATUS status,
1619					bool in_front)
1620{
1621	struct SPDYF_Response_Queue *response_to_queue;
1622	struct SPDYF_Control_Frame *control_frame;
1623	uint32_t *data;
1624
1625	if(NULL == (response_to_queue = malloc(sizeof(struct SPDYF_Response_Queue))))
1626	{
1627		return SPDY_NO;
1628	}
1629	memset(response_to_queue, 0, sizeof(struct SPDYF_Response_Queue));
1630
1631	if(NULL == (control_frame = malloc(sizeof(struct SPDYF_Control_Frame))))
1632	{
1633		free(response_to_queue);
1634		return SPDY_NO;
1635	}
1636	memset(control_frame, 0, sizeof(struct SPDYF_Control_Frame));
1637
1638	if(NULL == (data = malloc(4)))
1639	{
1640		free(control_frame);
1641		free(response_to_queue);
1642		return SPDY_NO;
1643	}
1644	*(data) = htonl(status);
1645
1646	control_frame->control_bit = 1;
1647	control_frame->version = SPDY_VERSION;
1648	control_frame->type = SPDY_CONTROL_FRAME_TYPES_GOAWAY;
1649	control_frame->flags = 0;
1650
1651	response_to_queue->control_frame = control_frame;
1652	response_to_queue->process_response_handler = &SPDYF_handler_write_goaway;
1653	response_to_queue->data = data;
1654	response_to_queue->data_size = 4;
1655
1656	SPDYF_queue_response (response_to_queue,
1657						session,
1658						in_front ? -1 : SPDY_NO);
1659
1660	return SPDY_YES;
1661}
1662
1663
1664int
1665SPDYF_prepare_rst_stream (struct SPDY_Session *session,
1666					struct SPDYF_Stream * stream,
1667					enum SPDY_RST_STREAM_STATUS status)
1668{
1669	struct SPDYF_Response_Queue *response_to_queue;
1670	struct SPDYF_Control_Frame *control_frame;
1671	uint32_t *data;
1672	uint32_t stream_id;
1673
1674  if(NULL == stream)
1675    stream_id = 0;
1676  else
1677    stream_id = stream->stream_id;
1678
1679	if(NULL == (response_to_queue = malloc(sizeof(struct SPDYF_Response_Queue))))
1680	{
1681		return SPDY_NO;
1682	}
1683	memset(response_to_queue, 0, sizeof(struct SPDYF_Response_Queue));
1684
1685	if(NULL == (control_frame = malloc(sizeof(struct SPDYF_Control_Frame))))
1686	{
1687		free(response_to_queue);
1688		return SPDY_NO;
1689	}
1690	memset(control_frame, 0, sizeof(struct SPDYF_Control_Frame));
1691
1692	if(NULL == (data = malloc(8)))
1693	{
1694		free(control_frame);
1695		free(response_to_queue);
1696		return SPDY_NO;
1697	}
1698	*(data) = HTON31(stream_id);
1699	*(data + 1) = htonl(status);
1700
1701	control_frame->control_bit = 1;
1702	control_frame->version = SPDY_VERSION;
1703	control_frame->type = SPDY_CONTROL_FRAME_TYPES_RST_STREAM;
1704	control_frame->flags = 0;
1705
1706	response_to_queue->control_frame = control_frame;
1707	response_to_queue->process_response_handler = &SPDYF_handler_write_rst_stream;
1708	response_to_queue->data = data;
1709	response_to_queue->data_size = 8;
1710	response_to_queue->stream = stream;
1711
1712	SPDYF_queue_response (response_to_queue,
1713						session,
1714						-1);
1715
1716	return SPDY_YES;
1717}
1718
1719
1720int
1721SPDYF_prepare_window_update (struct SPDY_Session *session,
1722					struct SPDYF_Stream * stream,
1723					int32_t delta_window_size)
1724{
1725	struct SPDYF_Response_Queue *response_to_queue;
1726	struct SPDYF_Control_Frame *control_frame;
1727	uint32_t *data;
1728
1729  SPDYF_ASSERT(NULL != stream, "stream cannot be NULL");
1730
1731	if(NULL == (response_to_queue = malloc(sizeof(struct SPDYF_Response_Queue))))
1732	{
1733		return SPDY_NO;
1734	}
1735	memset(response_to_queue, 0, sizeof(struct SPDYF_Response_Queue));
1736
1737	if(NULL == (control_frame = malloc(sizeof(struct SPDYF_Control_Frame))))
1738	{
1739		free(response_to_queue);
1740		return SPDY_NO;
1741	}
1742	memset(control_frame, 0, sizeof(struct SPDYF_Control_Frame));
1743
1744	if(NULL == (data = malloc(8)))
1745	{
1746		free(control_frame);
1747		free(response_to_queue);
1748		return SPDY_NO;
1749	}
1750	*(data) = HTON31(stream->stream_id);
1751	*(data + 1) = HTON31(delta_window_size);
1752
1753	control_frame->control_bit = 1;
1754	control_frame->version = SPDY_VERSION;
1755	control_frame->type = SPDY_CONTROL_FRAME_TYPES_WINDOW_UPDATE;
1756	control_frame->flags = 0;
1757
1758	response_to_queue->control_frame = control_frame;
1759	response_to_queue->process_response_handler = &SPDYF_handler_write_window_update;
1760	response_to_queue->data = data;
1761	response_to_queue->data_size = 8;
1762	response_to_queue->stream = stream;
1763
1764	SPDYF_queue_response (response_to_queue,
1765						session,
1766						-1);
1767
1768	return SPDY_YES;
1769}
1770