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  */
43 static void
spdyf_handler_read_syn_stream(struct SPDY_Session * session)44 spdyf_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  */
180 static void
spdyf_handler_read_goaway(struct SPDY_Session * session)181 spdyf_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  */
259 static void
spdyf_handler_read_rst_stream(struct SPDY_Session * session)260 spdyf_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  */
331 static void
spdyf_handler_read_data(struct SPDY_Session * session)332 spdyf_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 
421 int
SPDYF_handler_write_syn_reply(struct SPDY_Session * session)422 SPDYF_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 
516 int
SPDYF_handler_write_goaway(struct SPDY_Session * session)517 SPDYF_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 
569 int
SPDYF_handler_write_data(struct SPDY_Session * session)570 SPDYF_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 
741 int
SPDYF_handler_write_rst_stream(struct SPDY_Session * session)742 SPDYF_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 
786 int
SPDYF_handler_write_window_update(struct SPDY_Session * session)787 SPDYF_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 
829 void
SPDYF_handler_ignore_frame(struct SPDY_Session * session)830 SPDYF_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 
865 int
SPDYF_session_read(struct SPDY_Session * session)866 SPDYF_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 
980 int
SPDYF_session_write(struct SPDY_Session * session,bool only_one_frame)981 SPDYF_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 
1154 int
SPDYF_session_idle(struct SPDY_Session * session)1155 SPDYF_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 
1359 void
SPDYF_session_close(struct SPDY_Session * session)1360 SPDYF_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 
1388 int
SPDYF_session_accept(struct SPDY_Daemon * daemon)1389 SPDYF_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 
1493 void
SPDYF_queue_response(struct SPDYF_Response_Queue * response_to_queue,struct SPDY_Session * session,int consider_priority)1494 SPDYF_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 
1574 void
SPDYF_session_destroy(struct SPDY_Session * session)1575 SPDYF_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 
1616 int
SPDYF_prepare_goaway(struct SPDY_Session * session,enum SPDY_GOAWAY_STATUS status,bool in_front)1617 SPDYF_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 
1664 int
SPDYF_prepare_rst_stream(struct SPDY_Session * session,struct SPDYF_Stream * stream,enum SPDY_RST_STREAM_STATUS status)1665 SPDYF_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 
1720 int
SPDYF_prepare_window_update(struct SPDY_Session * session,struct SPDYF_Stream * stream,int32_t delta_window_size)1721 SPDYF_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