GNU libmicrohttpd  0.9.29
session.c
Go to the documentation of this file.
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 
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 
43 static void
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 
55  "the function is called wrong");
56 
57  frame = (struct SPDYF_Control_Frame *)session->frame_handler_cls;
58 
59  //handle subheaders
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");
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
87  return;
88  }
89  else
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 !=
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 */
124 
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,
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);
168  free(frame);
169 }
170 
171 
180 static void
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 
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
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  {
236  break;
238  break;
240  break;
241  }
242 
243  //SPDYF_DEBUG("goaway received: status %i", status);
244  }
245 
247  free(frame);
248 }
249 
250 
259 static void
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 
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
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 
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 
331 static void
333 {
334  int ret;
335  struct SPDYF_Data_Frame * frame;
336  struct SPDYF_Stream * stream;
337 
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
350  {
351  if(frame->length > SPDY_MAX_SUPPORTED_FRAME_SIZE)
352  {
354  return;
355  }
356  else
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;
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,
407  {
409  }
410  //else: do it later
411  }
412 
413  //SPDYF_DEBUG("data received: id %i", frame->stream_id);
414 
416  free(frame);
417  }
418 }
419 
420 
421 int
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 
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 */
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 */
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
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
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,
641  {
642  return SPDY_NO;
643  }
644 
645  //else no memory
646  //for now close session
647  //TODO what?
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
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
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
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
831 {
832  struct SPDYF_Control_Frame *frame;
833 
836  "the function is called wrong");
837 
838 
839  frame = (struct SPDYF_Control_Frame *)session->frame_handler_cls;
840 
841  //handle subheaders
843  {
844  if(frame->length > SPDY_MAX_SUPPORTED_FRAME_SIZE)
845  {
847  return;
848  }
849  else
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;
860  free(frame);
861  }
862 }
863 
864 
865 int
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  {
887 
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 
895 
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 
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  {
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;
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
960  //try to flush the queue when write is called
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
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
1043  != session->response_queue_head->control_frame->type)
1044  {
1047  SPDYF_session_write(session,true);
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;
1092  return SPDY_YES;
1093 
1094  case SPDY_IO_ERROR_ERROR:
1095  //any kind of error in the TLS subsystem
1096  //forbid more writing
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)
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
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  {
1168  //best effort for sending GOAWAY
1170  SPDYF_session_write(session,true);
1171  }
1172 
1173  switch(session->status)
1174  {
1175  //expect new frame to arrive
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 
1204  //assign different frame handler according to frame type
1205  switch(control_frame->type){
1208  break;
1211  break;
1214  break;
1215  default:
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 
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);
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
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 
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
1302 
1303  //actually the read buffer can be bigger than the
1304  //max supported size
1305  session->status = session->read_ignore_bytes
1308 
1309  free(session->frame_handler_cls);
1310  }
1311  }
1312  }
1313 
1315  {
1316  break;
1317  }
1318 
1319  //ignoring data in read buffer
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;
1335  }
1336  break;
1337 
1338  //expect frame body (name/value pairs)
1340  if(NULL!=session->frame_handler)
1341  session->frame_handler(session);
1342  break;
1343 
1345 
1346  return SPDY_NO;
1347 
1348  //because of error the session needs to be closed
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
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
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
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;
1451 
1452  //init zlib context for the whole session
1454  {
1455  session->fio_close_session(session);
1456  goto free_and_fail;
1457  }
1459  {
1460  session->fio_close_session(session);
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)MHD_socket_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
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
1576 {
1577  struct SPDYF_Stream *stream;
1578  struct SPDYF_Response_Queue *response_queue;
1579 
1580  (void)MHD_socket_close_ (session->socket_fd);
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
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;
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
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;
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
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;
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 }
struct SPDYF_Response_Queue * SPDYF_response_queue_create(bool is_data, void *data, size_t data_size, struct SPDY_Response *response, struct SPDYF_Stream *stream, bool closestream, SPDYF_ResponseQueueResultCallback frqcb, void *frqcb_cls, SPDY_ResponseResultCallback rrcb, void *rrcb_cls)
Definition: structures.c:290
int SPDYF_zlib_deflate(z_stream *strm, const void *src, size_t src_size, size_t *data_used, void **dest, size_t *dest_size)
Definition: compression.c:250
size_t read_buffer_size
Definition: structures.h:742
SPDY_NewSessionCallback new_session_cb
Definition: structures.h:909
#define SPDYF_CONTROL_FRAME_NTOH(frame)
Definition: structures.h:1117
#define SPDYF_DATA_FRAME_NTOH(frame)
Definition: structures.h:1150
static void spdyf_handler_read_goaway(struct SPDY_Session *session)
Definition: session.c:181
static void spdyf_handler_read_data(struct SPDY_Session *session)
Definition: session.c:332
void SPDYF_zlib_deflate_end(z_stream *strm)
Definition: compression.c:244
struct SPDYF_Response_Queue * response_queue_tail
Definition: structures.h:665
struct SPDYF_Stream * streams_head
Definition: structures.h:644
z_stream zlib_recv_stream
Definition: structures.h:610
zlib handling functions
void * data
Definition: microhttpd.h:2035
int SPDYF_zlib_inflate(z_stream *strm, const void *src, size_t src_size, void **dest, size_t *dest_size)
Definition: compression.c:350
SPDYF_IORecv fio_recv
Definition: structures.h:706
#define NULL
Definition: reason_phrase.c:30
void * read_buffer
Definition: structures.h:670
void SPDYF_stream_destroy(struct SPDYF_Stream *stream)
Definition: stream.c:117
struct SPDY_Daemon * daemon
Definition: structures.h:633
int SPDYF_handler_write_goaway(struct SPDY_Session *session)
Definition: session.c:517
#define SPDY_YES
Definition: microspdy.h:93
unsigned long long session_timeout
Definition: structures.h:961
uint32_t current_stream_id
Definition: structures.h:816
void * cls
Definition: structures.h:935
#define DLL_remove(head, tail, element)
Definition: internal.h:1343
SPDY_RST_STREAM_STATUS
Definition: structures.h:219
int SPDYF_session_read(struct SPDY_Session *session)
Definition: session.c:866
void * fcls
Definition: structures.h:945
struct SPDYF_Response_Queue * response_queue_head
Definition: structures.h:660
#define SPDYF_INITIAL_WINDOW_SIZE
Definition: internal.h:42
SPDYF_IOCloseSession fio_close_session
Definition: structures.h:701
SPDYF_IONewSession fio_new_session
Definition: structures.h:696
int SPDYF_prepare_goaway(struct SPDY_Session *session, enum SPDY_GOAWAY_STATUS status, bool in_front)
Definition: session.c:1617
uint32_t last_replied_to_stream_id
Definition: structures.h:809
struct SPDYF_Control_Frame * control_frame
Definition: structures.h:430
TCP connection/SPDY session handling.
size_t write_buffer_beginning
Definition: structures.h:770
int SPDYF_handler_write_data(struct SPDY_Session *session)
Definition: session.c:570
void SPDYF_response_queue_destroy(struct SPDYF_Response_Queue *response_queue)
Definition: structures.c:435
#define MHD_socket_close_(fd)
socklen_t addr_len
Definition: structures.h:788
static void spdyf_handler_read_syn_stream(struct SPDY_Session *session)
Definition: session.c:44
int SPDYF_prepare_window_update(struct SPDY_Session *session, struct SPDYF_Stream *stream, int32_t delta_window_size)
Definition: session.c:1721
void(* frame_handler)(struct SPDY_Session *session)
Definition: structures.h:680
bool is_out_closed
Definition: structures.h:590
internal functions and macros for the framing layer
void * write_buffer
Definition: structures.h:675
SPDY_SessionClosedCallback session_closed_cb
Definition: structures.h:914
platform-specific includes for libmicrohttpd
uint32_t max_num_frames
Definition: structures.h:976
unsigned long long last_activity
Definition: structures.h:776
void SPDYF_queue_response(struct SPDYF_Response_Queue *response_to_queue, struct SPDY_Session *session, int consider_priority)
Definition: session.c:1494
internal and public structures – most of the structs used by the library are defined here ...
Signatures for IO functions.
struct SPDYF_Response_Queue * prev
Definition: structures.h:414
uint32_t max_num_frames
Definition: structures.h:825
_MHD_EXTERN int SPDYF_name_value_from_stream(void *stream, size_t size, struct SPDY_NameValue **container)
Definition: structures.c:554
enum SPDY_IO_SUBSYSTEM io_subsystem
Definition: structures.h:991
SPDY streams handling.
int SPDYF_prepare_rst_stream(struct SPDY_Session *session, struct SPDYF_Stream *stream, enum SPDY_RST_STREAM_STATUS status)
Definition: session.c:1665
bool is_goaway_received
Definition: structures.h:853
SPDYF_ResponseQueueResultCallback frqcb
Definition: structures.h:452
#define SPDY_MAX_SUPPORTED_FRAME_SIZE
Definition: microspdy.h:117
SPDY_ResponseCallback rcb
Definition: structures.h:1022
#define SPDY_NO
Definition: microspdy.h:98
#define SPDYF_CONTROL_FRAME_HTON(frame)
Definition: structures.h:1100
void SPDYF_session_close(struct SPDY_Session *session)
Definition: session.c:1360
struct SPDY_Session * cleanup_head
Definition: structures.h:876
unsigned long long SPDYF_monotonic_time(void)
Definition: internal.c:30
int SPDYF_session_write(struct SPDY_Session *session, bool only_one_frame)
Definition: session.c:981
SPDY_GOAWAY_STATUS
Definition: structures.h:295
bool read_closed
Definition: structures.h:840
void * rcb_cls
Definition: structures.h:1027
bool is_in_closed
Definition: structures.h:583
#define SPDY_VERSION
Definition: microspdy.h:110
#define SPDYF_BUFFER_SIZE
Definition: internal.h:36
struct SPDYF_Stream * next
Definition: structures.h:524
size_t read_ignore_bytes
Definition: structures.h:734
void SPDYF_session_destroy(struct SPDY_Session *session)
Definition: session.c:1575
int SPDYF_io_set_session(struct SPDY_Session *session, enum SPDY_IO_SUBSYSTEM io_subsystem)
Definition: io.c:58
bool is_goaway_sent
Definition: structures.h:846
struct SPDY_Session * sessions_head
Definition: structures.h:866
#define SPDYF_DEBUG(fmt,...)
Definition: internal.h:155
SPDYF_IOAfterWrite fio_after_write
Definition: structures.h:726
void SPDYF_stream_set_flags_on_write(struct SPDYF_Response_Queue *response_queue)
Definition: stream.c:126
struct sockaddr * addr
Definition: structures.h:638
uint32_t rcb_block_size
Definition: structures.h:1044
size_t write_buffer_size
Definition: structures.h:759
struct SPDYF_Data_Frame * data_frame
Definition: structures.h:436
SPDYF_NewStreamCallback fnew_stream_cb
Definition: structures.h:940
size_t read_buffer_beginning
Definition: structures.h:753
enum SPDY_SESSION_STATUS status
Definition: structures.h:831
#define SPDYF_ASSERT(expr, msg)
Definition: internal.h:80
struct SPDY_Session * cleanup_tail
Definition: structures.h:881
size_t write_buffer_offset
Definition: structures.h:765
void SPDYF_handler_ignore_frame(struct SPDY_Session *session)
Definition: session.c:830
int SPDYF_session_accept(struct SPDY_Daemon *daemon)
Definition: session.c:1389
int SPDYF_handler_write_window_update(struct SPDY_Session *session)
Definition: session.c:787
struct SPDYF_Stream * SPDYF_stream_find(uint32_t stream_id, struct SPDY_Session *session)
Definition: stream.c:159
static void spdyf_handler_read_rst_stream(struct SPDY_Session *session)
Definition: session.c:260
uint32_t window_size
Definition: structures.h:559
uint8_t priority
Definition: structures.h:564
#define HTON31(n)
Definition: internal.h:142
struct SPDY_NameValue * headers
Definition: structures.h:539
int(* process_response_handler)(struct SPDY_Session *session)
Definition: structures.h:446
SPDYF_IOSend fio_send
Definition: structures.h:711
SPDY_ResponseResultCallback rrcb
Definition: structures.h:462
#define DLL_insert(head, tail, element)
Definition: internal.h:1322
uint32_t stream_id
Definition: structures.h:549
struct SPDY_Session * sessions_tail
Definition: structures.h:871
struct SPDYF_Stream * streams_tail
Definition: structures.h:649
#define SPDYF_DATA_FRAME_HTON(frame)
Definition: structures.h:1134
void * frame_handler_cls
Definition: structures.h:685
int SPDYF_zlib_deflate_init(z_stream *strm)
Definition: compression.c:215
size_t read_buffer_offset
Definition: structures.h:748
struct SPDYF_Response_Queue * next
Definition: structures.h:409
#define NTOH31(n)
Definition: internal.h:126
int SPDYF_handler_write_syn_reply(struct SPDY_Session *session)
Definition: session.c:422
struct SPDYF_Stream * stream
Definition: structures.h:419
int SPDYF_session_idle(struct SPDY_Session *session)
Definition: session.c:1155
SPDYF_NewDataCallback freceived_data_cb
Definition: structures.h:930
int SPDYF_handler_write_rst_stream(struct SPDY_Session *session)
Definition: session.c:742
z_stream zlib_send_stream
Definition: structures.h:618
SPDYF_IOBeforeWrite fio_before_write
Definition: structures.h:721
struct SPDY_Response * response
Definition: structures.h:424
SPDY_NewDataCallback received_data_cb
Definition: structures.h:925
int SPDYF_stream_new(struct SPDY_Session *session)
Definition: stream.c:32
void SPDYF_zlib_inflate_end(z_stream *strm)
Definition: compression.c:343
int SPDYF_zlib_inflate_init(z_stream *strm)
Definition: compression.c:320