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