GNU libmicrohttpd  0.9.29
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
structures.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 //TODO not for here?
31 #include <ctype.h>
32 
33 
34 int
36 {
37  SPDYF_ASSERT(NULL != container, "NULL is not an empty container!");
38  return (NULL == container->name && NULL == container->value) ? SPDY_YES : SPDY_NO;
39 }
40 
41 struct SPDY_NameValue *
43 {
44  struct SPDY_NameValue *pair;
45 
46  if(NULL == (pair = malloc(sizeof(struct SPDY_NameValue))))
47  return NULL;
48 
49  memset (pair, 0, sizeof (struct SPDY_NameValue));
50 
51  return pair;
52 }
53 
54 
55 int
57  const char *name,
58  const char *value)
59 {
60  unsigned int i;
61  unsigned int len;
62  struct SPDY_NameValue *pair;
63  struct SPDY_NameValue *temp;
64  char **temp_value;
65  char *temp_string;
66 
67  if(NULL == container || NULL == name || 0 == (len = strlen(name)))
68  return SPDY_INPUT_ERROR;
69 
70  for(i=0; i<len; ++i)
71  {
72  if(isupper((int) name[i]))
73  return SPDY_INPUT_ERROR;
74  }
75 
76  if(SPDYF_name_value_is_empty(container))
77  {
78  //container is empty/just created
79  if (NULL == (container->name = strdup (name)))
80  {
81  return SPDY_NO;
82  }
83  if (NULL == (container->value = malloc(sizeof(char *))))
84  {
85  free(container->name);
86  return SPDY_NO;
87  }
88  if (NULL == (container->value[0] = strdup (value)))
89  {
90  free(container->value);
91  free(container->name);
92  return SPDY_NO;
93  }
94  container->num_values = 1;
95  return SPDY_YES;
96  }
97 
98  pair = container;
99  while(NULL != pair)
100  {
101  if(0 == strcmp(pair->name, name))
102  {
103  //the value will be added to this pair
104  break;
105  }
106  pair = pair->next;
107  }
108 
109  if(NULL == pair)
110  {
111  //the name doesn't exist in container, add new pair
112  if(NULL == (pair = malloc(sizeof(struct SPDY_NameValue))))
113  return SPDY_NO;
114 
115  memset(pair, 0, sizeof(struct SPDY_NameValue));
116 
117  if (NULL == (pair->name = strdup (name)))
118  {
119  free(pair);
120  return SPDY_NO;
121  }
122  if (NULL == (pair->value = malloc(sizeof(char *))))
123  {
124  free(pair->name);
125  free(pair);
126  return SPDY_NO;
127  }
128  if (NULL == (pair->value[0] = strdup (value)))
129  {
130  free(pair->value);
131  free(pair->name);
132  free(pair);
133  return SPDY_NO;
134  }
135  pair->num_values = 1;
136 
137  temp = container;
138  while(NULL != temp->next)
139  temp = temp->next;
140  temp->next = pair;
141  pair->prev = temp;
142 
143  return SPDY_YES;
144  }
145 
146  //check for duplication (case sensitive)
147  for(i=0; i<pair->num_values; ++i)
148  if(0 == strcmp(pair->value[i], value))
149  return SPDY_NO;
150 
151  if(strlen(pair->value[0]) > 0)
152  {
153  //the value will be appended to the others for this name
154  if (NULL == (temp_value = malloc((pair->num_values + 1) * sizeof(char *))))
155  {
156  return SPDY_NO;
157  }
158  memcpy(temp_value, pair->value, pair->num_values * sizeof(char *));
159  if (NULL == (temp_value[pair->num_values] = strdup (value)))
160  {
161  free(temp_value);
162  return SPDY_NO;
163  }
164  free(pair->value);
165  pair->value = temp_value;
166  ++pair->num_values;
167  return SPDY_YES;
168  }
169 
170  //just replace the empty value
171 
172  if (NULL == (temp_string = strdup (value)))
173  {
174  return SPDY_NO;
175  }
176  free(pair->value[0]);
177  pair->value[0] = temp_string;
178 
179  return SPDY_YES;
180 }
181 
182 
183 const char * const *
185  const char *name,
186  int *num_values)
187 {
188  struct SPDY_NameValue *temp = container;
189 
190  if(NULL == container || NULL == name || NULL == num_values)
191  return NULL;
192  if(SPDYF_name_value_is_empty(container))
193  return NULL;
194 
195  do
196  {
197  if(strcmp(name, temp->name) == 0)
198  {
199  *num_values = temp->num_values;
200  return (const char * const *)temp->value;
201  }
202 
203  temp = temp->next;
204  }
205  while(NULL != temp);
206 
207  return NULL;
208 }
209 
210 
211 void
213 {
214  unsigned int i;
215  struct SPDY_NameValue *temp = container;
216 
217  while(NULL != temp)
218  {
219  container = container->next;
220  free(temp->name);
221  for(i=0; i<temp->num_values; ++i)
222  free(temp->value[i]);
223  free(temp->value);
224  free(temp);
225  temp=container;
226  }
227 }
228 
229 
230 int
232  SPDY_NameValueIterator iterator,
233  void *iterator_cls)
234 {
235  int count;
236  int ret;
237  struct SPDY_NameValue *temp = container;
238 
239  if(NULL == container)
240  return SPDY_INPUT_ERROR;
241 
242  //check if container is an empty struct
243  if(SPDYF_name_value_is_empty(container))
244  return 0;
245 
246  count = 0;
247 
248  if(NULL == iterator)
249  {
250  do
251  {
252  ++count;
253  temp=temp->next;
254  }
255  while(NULL != temp);
256 
257  return count;
258  }
259 
260  //code duplication for avoiding if here
261  do
262  {
263  ++count;
264  ret = iterator(iterator_cls, temp->name, (const char * const *)temp->value, temp->num_values);
265  temp=temp->next;
266  }
267  while(NULL != temp && SPDY_YES == ret);
268 
269  return count;
270 }
271 
272 void
274 {
275  if(NULL == response)
276  return;
277  free(response->data);
278  free(response->headers);
279  free(response);
280 }
281 
282 
283 struct SPDYF_Response_Queue *
285  void *data,
286  size_t data_size,
287  struct SPDY_Response *response,
288  struct SPDYF_Stream *stream,
289  bool closestream,
291  void *frqcb_cls,
293  void *rrcb_cls)
294 {
295  struct SPDYF_Response_Queue *head = NULL;
296  struct SPDYF_Response_Queue *prev;
297  struct SPDYF_Response_Queue *response_to_queue;
298  struct SPDYF_Control_Frame *control_frame;
299  struct SPDYF_Data_Frame *data_frame;
300  unsigned int i;
301  bool is_last;
302 
303  SPDYF_ASSERT((! is_data)
304  || ((0 == data_size) && (NULL != response->rcb))
305  || ((0 < data_size) && (NULL == response->rcb)),
306  "either data or request->rcb must not be null");
307 
308  if (is_data && (data_size > SPDY_MAX_SUPPORTED_FRAME_SIZE))
309  {
310  //separate the data in more frames and add them to the queue
311 
312  prev=NULL;
313  for(i = 0; i < data_size; i += SPDY_MAX_SUPPORTED_FRAME_SIZE)
314  {
315  is_last = (i + SPDY_MAX_SUPPORTED_FRAME_SIZE) >= data_size;
316 
317  if(NULL == (response_to_queue = malloc(sizeof(struct SPDYF_Response_Queue))))
318  goto free_and_fail;
319 
320  memset(response_to_queue, 0, sizeof(struct SPDYF_Response_Queue));
321  if(0 == i)
322  head = response_to_queue;
323 
324  if(NULL == (data_frame = malloc(sizeof(struct SPDYF_Data_Frame))))
325  {
326  free(response_to_queue);
327  goto free_and_fail;
328  }
329  memset(data_frame, 0, sizeof(struct SPDYF_Data_Frame));
330  data_frame->control_bit = 0;
331  data_frame->stream_id = stream->stream_id;
332  if(is_last && closestream)
333  data_frame->flags |= SPDY_DATA_FLAG_FIN;
334 
335  response_to_queue->data_frame = data_frame;
337  response_to_queue->is_data = is_data;
338  response_to_queue->stream = stream;
339  if(is_last)
340  {
341  response_to_queue->frqcb = frqcb;
342  response_to_queue->frqcb_cls = frqcb_cls;
343  response_to_queue->rrcb = rrcb;
344  response_to_queue->rrcb_cls = rrcb_cls;
345  }
346  response_to_queue->data = data + i;
347  response_to_queue->data_size = is_last
348  ? (data_size - 1) % SPDY_MAX_SUPPORTED_FRAME_SIZE + 1
350  response_to_queue->response = response;
351 
352  response_to_queue->prev = prev;
353  if(NULL != prev)
354  prev->next = response_to_queue;
355  prev = response_to_queue;
356  }
357 
358  return head;
359 
360  //for GOTO
361  free_and_fail:
362  while(NULL != head)
363  {
364  response_to_queue = head;
365  head = head->next;
366  free(response_to_queue->data_frame);
367  free(response_to_queue);
368  }
369  return NULL;
370  }
371 
372  //create only one frame for data, data with callback or control frame
373 
374  if(NULL == (response_to_queue = malloc(sizeof(struct SPDYF_Response_Queue))))
375  {
376  return NULL;
377  }
378  memset(response_to_queue, 0, sizeof(struct SPDYF_Response_Queue));
379 
380  if(is_data)
381  {
382  if(NULL == (data_frame = malloc(sizeof(struct SPDYF_Data_Frame))))
383  {
384  free(response_to_queue);
385  return NULL;
386  }
387  memset(data_frame, 0, sizeof(struct SPDYF_Data_Frame));
388  data_frame->control_bit = 0;
389  data_frame->stream_id = stream->stream_id;
390  if(closestream && NULL == response->rcb)
391  data_frame->flags |= SPDY_DATA_FLAG_FIN;
392 
393  response_to_queue->data_frame = data_frame;
395  }
396  else
397  {
398  if(NULL == (control_frame = malloc(sizeof(struct SPDYF_Control_Frame))))
399  {
400  free(response_to_queue);
401  return NULL;
402  }
403  memset(control_frame, 0, sizeof(struct SPDYF_Control_Frame));
404  control_frame->control_bit = 1;
405  control_frame->version = SPDY_VERSION;
406  control_frame->type = SPDY_CONTROL_FRAME_TYPES_SYN_REPLY;
407  if(closestream)
408  control_frame->flags |= SPDY_SYN_REPLY_FLAG_FIN;
409 
410  response_to_queue->control_frame = control_frame;
412  }
413 
414  response_to_queue->is_data = is_data;
415  response_to_queue->stream = stream;
416  response_to_queue->frqcb = frqcb;
417  response_to_queue->frqcb_cls = frqcb_cls;
418  response_to_queue->rrcb = rrcb;
419  response_to_queue->rrcb_cls = rrcb_cls;
420  response_to_queue->data = data;
421  response_to_queue->data_size = data_size;
422  response_to_queue->response = response;
423 
424  return response_to_queue;
425 }
426 
427 
428 void
430 {
431  //data is not copied to the struct but only linked
432  //but this is not valid for GOAWAY and RST_STREAM
433  if(!response_queue->is_data
434  && (SPDY_CONTROL_FRAME_TYPES_RST_STREAM == response_queue->control_frame->type
435  || SPDY_CONTROL_FRAME_TYPES_GOAWAY == response_queue->control_frame->type))
436  {
437  free(response_queue->data);
438  }
439  if(response_queue->is_data)
440  free(response_queue->data_frame);
441  else
442  free(response_queue->control_frame);
443 
444  free(response_queue);
445 }
446 
447 
448 ssize_t
450  int num_containers,
451  void **stream)
452 {
453  size_t size;
454  int32_t num_pairs = 0;
455  int32_t value_size;
456  int32_t name_size;
457  int32_t temp;
458  unsigned int i;
459  unsigned int offset;
460  unsigned int value_offset;
461  struct SPDY_NameValue * iterator;
462  int j;
463 
464  size = 4; //for num pairs
465 
466  for(j=0; j<num_containers; ++j)
467  {
468  iterator = container[j];
469  while(iterator != NULL)
470  {
471  ++num_pairs;
472  size += 4 + strlen(iterator->name); //length + string
473 
474  SPDYF_ASSERT(iterator->num_values>0, "num_values is 0");
475 
476  size += 4; //value length
477 
478  for(i=0; i<iterator->num_values; ++i)
479  {
480  size += strlen(iterator->value[i]); // string
481  if(i/* || !strlen(iterator->value[i])*/) ++size; //NULL separator
482  }
483 
484  iterator = iterator->next;
485  }
486  }
487 
488  if(NULL == (*stream = malloc(size)))
489  {
490  return -1;
491  }
492 
493  //put num_pairs to the stream
494  num_pairs = htonl(num_pairs);
495  memcpy(*stream, &num_pairs, 4);
496  offset = 4;
497 
498  //put all other headers to the stream
499  for(j=0; j<num_containers; ++j)
500  {
501  iterator = container[j];
502  while(iterator != NULL)
503  {
504  name_size = strlen(iterator->name);
505  temp = htonl(name_size);
506  memcpy(*stream + offset, &temp, 4);
507  offset += 4;
508  strncpy(*stream + offset, iterator->name, name_size);
509  offset += name_size;
510 
511  value_offset = offset;
512  offset += 4;
513  for(i=0; i<iterator->num_values; ++i)
514  {
515  if(i /*|| !strlen(iterator->value[0])*/)
516  {
517  memset(*stream + offset, 0, 1);
518  ++offset;
519  //if(!i) continue;
520  }
521  strncpy(*stream + offset, iterator->value[i], strlen(iterator->value[i]));
522  offset += strlen(iterator->value[i]);
523  }
524  value_size = offset - value_offset - 4;
525  value_size = htonl(value_size);
526  memcpy(*stream + value_offset, &value_size, 4);
527 
528  iterator = iterator->next;
529  }
530  }
531 
532  SPDYF_ASSERT(offset == size,"offset is wrong");
533 
534  return size;
535 }
536 
537 
538 int
540  size_t size,
541  struct SPDY_NameValue ** container)
542 {
543  int32_t num_pairs;
544  int32_t value_size;
545  int32_t name_size;
546  int i;
547  unsigned int offset = 0;
548  unsigned int value_end_offset;
549  char *name;
550  char *value;
551 
552  if(NULL == (*container = SPDY_name_value_create ()))
553  {
554  return SPDY_NO;
555  }
556 
557  //get number of pairs
558  memcpy(&num_pairs, stream, 4);
559  offset = 4;
560  num_pairs = ntohl(num_pairs);
561 
562  if(num_pairs > 0)
563  {
564  for(i = 0; i < num_pairs; ++i)
565  {
566  //get name size
567  memcpy(&name_size, stream + offset, 4);
568  offset += 4;
569  name_size = ntohl(name_size);
570  //get name
571  if(NULL == (name = strndup(stream + offset, name_size)))
572  {
573  SPDY_name_value_destroy(*container);
574  return SPDY_NO;
575  }
576  offset+=name_size;
577 
578  //get value size
579  memcpy(&value_size, stream + offset, 4);
580  offset += 4;
581  value_size = ntohl(value_size);
582  value_end_offset = offset + value_size;
583  //get value
584  do
585  {
586  if(NULL == (value = strndup(stream + offset, value_size)))
587  {
588  free(name);
589  SPDY_name_value_destroy(*container);
590  return SPDY_NO;
591  }
592  offset += strlen(value);
593  if(offset < value_end_offset)
594  ++offset; //NULL separator
595 
596  //add name/value to the struct
597  if(SPDY_YES != SPDY_name_value_add(*container, name, value))
598  {
599  free(name);
600  free(value);
601  SPDY_name_value_destroy(*container);
602  return SPDY_NO;
603  }
604  free(value);
605  }
606  while(offset < value_end_offset);
607 
608  free(name);
609 
610  if(offset != value_end_offset)
611  {
612  SPDY_name_value_destroy(*container);
613  return SPDY_INPUT_ERROR;
614  }
615  }
616  }
617 
618  if(offset == size)
619  return SPDY_YES;
620 
621  SPDY_name_value_destroy(*container);
622  return SPDY_INPUT_ERROR;
623 }
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:284
int SPDY_name_value_iterate(struct SPDY_NameValue *container, SPDY_NameValueIterator iterator, void *iterator_cls)
Definition: structures.c:231
void SPDY_destroy_response(struct SPDY_Response *response)
Definition: structures.c:273
#define SPDY_YES
Definition: microspdy.h:90
int SPDYF_name_value_from_stream(void *stream, size_t size, struct SPDY_NameValue **container)
Definition: structures.c:539
struct SPDYF_Control_Frame * control_frame
Definition: structures.h:430
TCP connection/SPDY session handling.
struct SPDY_NameValue * SPDY_name_value_create()
Definition: structures.c:42
int SPDYF_handler_write_data(struct SPDY_Session *session)
Definition: session.c:568
void SPDYF_response_queue_destroy(struct SPDYF_Response_Queue *response_queue)
Definition: structures.c:429
int(* process_response_handler)(struct SPDY_Session *session)
Definition: structures.h:446
internal functions and macros for the framing layer
platform-specific includes for libmicrohttpd
#define SPDY_INPUT_ERROR
Definition: microspdy.h:102
internal and public structures – most of the structs used by the library are defined here ...
struct SPDYF_Response_Queue * prev
Definition: structures.h:414
int SPDYF_name_value_is_empty(struct SPDY_NameValue *container)
Definition: structures.c:35
SPDYF_ResponseQueueResultCallback frqcb
Definition: structures.h:452
#define SPDY_MAX_SUPPORTED_FRAME_SIZE
Definition: microspdy.h:114
SPDY_ResponseCallback rcb
Definition: structures.h:1022
#define SPDY_NO
Definition: microspdy.h:95
return NULL
Definition: tsearch.c:30
int SPDY_name_value_add(struct SPDY_NameValue *container, const char *name, const char *value)
Definition: structures.c:56
struct SPDY_NameValue * next
Definition: structures.h:491
int(* SPDY_NameValueIterator)(void *cls, const char *name, const char *const *value, int num_values)
Definition: microspdy.h:633
void * headers
Definition: structures.h:1009
unsigned int num_values
Definition: structures.h:512
void(* SPDY_ResponseResultCallback)(void *cls, struct SPDY_Response *response, struct SPDY_Request *request, enum SPDY_RESPONSE_RESULT status, bool streamopened)
Definition: microspdy.h:746
#define SPDY_VERSION
Definition: microspdy.h:107
void(* SPDYF_ResponseQueueResultCallback)(void *cls, struct SPDYF_Response_Queue *response_queue, enum SPDY_RESPONSE_RESULT status)
Definition: structures.h:370
char ** value
Definition: structures.h:507
struct SPDYF_Data_Frame * data_frame
Definition: structures.h:436
ssize_t SPDYF_name_value_to_stream(struct SPDY_NameValue *container[], int num_containers, void **stream)
Definition: structures.c:449
#define SPDYF_ASSERT(expr, msg)
Definition: internal.h:79
struct SPDY_NameValue * prev
Definition: structures.h:496
void SPDY_name_value_destroy(struct SPDY_NameValue *container)
Definition: structures.c:212
const char *const * SPDY_name_value_lookup(struct SPDY_NameValue *container, const char *name, int *num_values)
Definition: structures.c:184
SPDY_ResponseResultCallback rrcb
Definition: structures.h:462
uint32_t stream_id
Definition: structures.h:549
struct SPDYF_Response_Queue * next
Definition: structures.h:409
int SPDYF_handler_write_syn_reply(struct SPDY_Session *session)
Definition: session.c:420
struct SPDYF_Stream * stream
Definition: structures.h:419
struct SPDY_Response * response
Definition: structures.h:424