GNU libmicrohttpd  0.9.29
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
applicationlayer.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 
25 #include "platform.h"
26 #include "applicationlayer.h"
27 #include "alstructures.h"
28 #include "structures.h"
29 #include "internal.h"
30 #include "daemon.h"
31 #include "session.h"
32 
33 
34 void
36  struct SPDY_Response *response,
37  struct SPDY_Request *request,
38  enum SPDY_RESPONSE_RESULT status,
39  bool streamopened)
40 {
41  (void)cls;
42  (void)status;
43  (void)streamopened;
44 
45  SPDY_destroy_request(request);
46  SPDY_destroy_response(response);
47 }
48 
49 
58 static int
60  struct SPDYF_Stream * stream)
61 {
62  (void)cls;
63  unsigned int i;
64  char *method = NULL;
65  char *path = NULL;
66  char *version = NULL;
67  char *host = NULL;
68  char *scheme = NULL;
69  struct SPDY_Request * request = NULL;
70  struct SPDY_NameValue * headers = NULL;
71  struct SPDY_NameValue * iterator = stream->headers;
72  struct SPDY_Daemon *daemon;
73 
74  daemon = stream->session->daemon;
75 
76  //if the user doesn't care, ignore it
77  if(NULL == daemon->new_request_cb)
78  return SPDY_YES;
79 
80  if(NULL == (headers=SPDY_name_value_create()))
81  goto free_and_fail;
82 
83  if(NULL==(request = malloc(sizeof(struct SPDY_Request))))
84  goto free_and_fail;
85 
86  memset(request, 0, sizeof(struct SPDY_Request));
87  request->stream = stream;
88 
89  /* extract the mandatory fields from stream->headers' structure
90  * to pass them to the client */
91  while(iterator != NULL)
92  {
93  if(strcmp(":method",iterator->name) == 0)
94  {
95  if(1 != iterator->num_values)
96  break;
97  method = iterator->value[0];
98  }
99  else if(strcmp(":path",iterator->name) == 0)
100  {
101  if(1 != iterator->num_values)
102  break;
103  path = iterator->value[0];
104  }
105  else if(strcmp(":version",iterator->name) == 0)
106  {
107  if(1 != iterator->num_values)
108  break;
109  version = iterator->value[0];
110  }
111  else if(strcmp(":host",iterator->name) == 0)
112  {
113  //TODO can it have more values?
114  if(1 != iterator->num_values)
115  break;
116  host = iterator->value[0];
117  }
118  else if(strcmp(":scheme",iterator->name) == 0)
119  {
120  if(1 != iterator->num_values)
121  break;
122  scheme = iterator->value[0];
123  }
124  else
125  for(i=0; i<iterator->num_values; ++i)
126  if (SPDY_YES != SPDY_name_value_add(headers,iterator->name,iterator->value[i]))
127  {
128  SPDY_destroy_request(request);
129  goto free_and_fail;
130  }
131 
132  iterator = iterator->next;
133  }
134 
135  request->method=method;
136  request->path=path;
137  request->version=version;
138  request->host=host;
139  request->scheme=scheme;
140  request->headers=headers;
141 
142  //check request validity, all these fields are mandatory for a request
143  if(NULL == method || strlen(method) == 0
144  || NULL == path || strlen(path) == 0
145  || NULL == version || strlen(version) == 0
146  || NULL == host || strlen(host) == 0
147  || NULL == scheme || strlen(scheme) == 0
148  )
149  {
150  //TODO HTTP 400 Bad Request must be answered
151 
152  SPDYF_DEBUG("Bad request");
153 
154  SPDY_destroy_request(request);
155 
156  return SPDY_YES;
157  }
158 
159  //call client's callback function to notify
160  daemon->new_request_cb(daemon->cls,
161  request,
162  stream->priority,
163  method,
164  path,
165  version,
166  host,
167  scheme,
168  headers,
169  !stream->is_in_closed);
170 
171  stream->cls = request;
172 
173  return SPDY_YES;
174 
175  //for GOTO
176  free_and_fail:
177 
178  SPDY_name_value_destroy(headers);
179  return SPDY_NO;
180 }
181 
182 
186 static int
188  struct SPDYF_Stream *stream,
189  const void * buf,
190  size_t size,
191  bool more)
192 {
193  return stream->session->daemon->received_data_cb(cls, stream->cls, buf, size, more);
194 }
195 
196 
197 
211 static void
213  struct SPDYF_Response_Queue *response_queue,
214  enum SPDY_RESPONSE_RESULT status)
215 {
216  int streamopened;
217  struct SPDY_Request *request = (struct SPDY_Request *)cls;
218 
219  SPDYF_ASSERT( ( (NULL == response_queue->data_frame) &&
220  (NULL != response_queue->control_frame) ) ||
221  ( (NULL != response_queue->data_frame) &&
222  (NULL == response_queue->control_frame) ),
223  "response queue must have either control frame or data frame");
224 
225  streamopened = !response_queue->stream->is_out_closed;
226 
227  response_queue->rrcb(response_queue->rrcb_cls, response_queue->response, request, status, streamopened);
228 }
229 
230 
231 int
232 (SPDY_init) (enum SPDY_IO_SUBSYSTEM io_subsystem, ...)
233 {
235  "Buffer size is less than max supported frame size!");
237  "Max supported frame size must be bigger than the minimal value!");
239  "SPDY_init must be called only once per program or after SPDY_deinit");
240 
241  if(SPDY_IO_SUBSYSTEM_OPENSSL & io_subsystem)
242  {
245  }
246  else if(SPDY_IO_SUBSYSTEM_RAW & io_subsystem)
247  {
250  }
251 
253  "SPDY_init could not find even one IO subsystem");
254 
255  return SPDY_YES;
256 }
257 
258 
259 void
261 {
263  "SPDY_init has not been called!");
264 
267  else if(SPDY_IO_SUBSYSTEM_RAW & spdyf_io_initialized)
269 
270  spdyf_io_initialized = SPDY_IO_SUBSYSTEM_NONE;
271 }
272 
273 
274 void
275 SPDY_run (struct SPDY_Daemon *daemon)
276 {
277  if(NULL == daemon)
278  {
279  SPDYF_DEBUG("daemon is NULL");
280  return;
281  }
282 
283  SPDYF_run(daemon);
284 }
285 
286 
287 int
288 SPDY_get_timeout (struct SPDY_Daemon *daemon,
289  unsigned long long *timeout)
290 {
291  if(NULL == daemon)
292  {
293  SPDYF_DEBUG("daemon is NULL");
294  return SPDY_INPUT_ERROR;
295  }
296 
297  return SPDYF_get_timeout(daemon,timeout);
298 }
299 
300 
301 int
302 SPDY_get_fdset (struct SPDY_Daemon *daemon,
303  fd_set *read_fd_set,
304  fd_set *write_fd_set,
305  fd_set *except_fd_set)
306 {
307  if(NULL == daemon
308  || NULL == read_fd_set
309  || NULL == write_fd_set
310  || NULL == except_fd_set)
311  {
312  SPDYF_DEBUG("a parameter is NULL");
313  return SPDY_INPUT_ERROR;
314  }
315 
316  return SPDYF_get_fdset(daemon,
317  read_fd_set,
318  write_fd_set,
319  except_fd_set,
320  false);
321 }
322 
323 
324 struct SPDY_Daemon *
326  const char *certfile,
327  const char *keyfile,
331  SPDY_NewDataCallback npdcb,
332  void * cls,
333  ...)
334 {
335  struct SPDY_Daemon *daemon;
336  va_list valist;
337 
339  {
340  SPDYF_DEBUG("library not initialized");
341  return NULL;
342  }
343  /*
344  * for now make this checks in framing layer
345  if(NULL == certfile)
346  {
347  SPDYF_DEBUG("certfile is NULL");
348  return NULL;
349  }
350  if(NULL == keyfile)
351  {
352  SPDYF_DEBUG("keyfile is NULL");
353  return NULL;
354  }
355  */
356 
357  va_start(valist, cls);
358  daemon = SPDYF_start_daemon_va ( port,
359  certfile,
360  keyfile,
361  nscb,
362  sccb,
363  nrcb,
364  npdcb,
367  cls,
368  NULL,
369  valist
370  );
371  va_end(valist);
372 
373  return daemon;
374 }
375 
376 
377 void
379 {
380  if(NULL == daemon)
381  {
382  SPDYF_DEBUG("daemon is NULL");
383  return;
384  }
385 
386  SPDYF_stop_daemon(daemon);
387 }
388 
389 
390 struct SPDY_Response *
392  const char * statustext,
393  const char * version,
394  struct SPDY_NameValue * headers,
395  const void * data,
396  size_t size)
397 {
398  struct SPDY_Response *response = NULL;
399  struct SPDY_NameValue ** all_headers = NULL; //TODO maybe array in stack is enough
400  char *fullstatus = NULL;
401  int ret;
402  int num_hdr_containers = 1;
403 
404  if(NULL == version)
405  {
406  SPDYF_DEBUG("version is NULL");
407  return NULL;
408  }
409 
410  if(NULL == (response = malloc(sizeof(struct SPDY_Response))))
411  goto free_and_fail;
412  memset(response, 0, sizeof(struct SPDY_Response));
413 
414  if(NULL != headers && !SPDYF_name_value_is_empty(headers))
415  num_hdr_containers = 2;
416 
417  if(NULL == (all_headers = malloc(num_hdr_containers * sizeof(struct SPDY_NameValue *))))
418  goto free_and_fail;
419  memset(all_headers, 0, num_hdr_containers * sizeof(struct SPDY_NameValue *));
420 
421  if(2 == num_hdr_containers)
422  all_headers[1] = headers;
423 
424  if(NULL == (all_headers[0] = SPDY_name_value_create()))
425  goto free_and_fail;
426 
427  if(NULL == statustext)
428  ret = asprintf(&fullstatus, "%i", status);
429  else
430  ret = asprintf(&fullstatus, "%i %s", status, statustext);
431  if(-1 == ret)
432  goto free_and_fail;
433 
434  if(SPDY_YES != SPDY_name_value_add(all_headers[0], ":status", fullstatus))
435  goto free_and_fail;
436 
437  free(fullstatus);
438  fullstatus = NULL;
439 
440  if(SPDY_YES != SPDY_name_value_add(all_headers[0], ":version", version))
441  goto free_and_fail;
442 
443  if(0 >= (response->headers_size = SPDYF_name_value_to_stream(all_headers,
444  num_hdr_containers,
445  &(response->headers))))
446  goto free_and_fail;
447 
448  SPDY_name_value_destroy(all_headers[0]);
449  free(all_headers);
450  all_headers = NULL;
451 
452  if(size > 0)
453  {
454  //copy the data to the response object
455  if(NULL == (response->data = malloc(size)))
456  {
457  free(response->headers);
458  goto free_and_fail;
459  }
460  memcpy(response->data, data, size);
461  response->data_size = size;
462  }
463 
464  return response;
465 
466  //for GOTO
467  free_and_fail:
468 
469  free(fullstatus);
470  if(NULL != all_headers)
471  SPDY_name_value_destroy(all_headers[0]);
472  free(all_headers);
473  free(response);
474 
475  return NULL;
476 }
477 
478 
479 struct SPDY_Response *
481  const char * statustext,
482  const char * version,
483  struct SPDY_NameValue * headers,
485  void *rcb_cls,
486  uint32_t block_size)
487 {
488  struct SPDY_Response *response;
489 
490  if(NULL == rcb)
491  {
492  SPDYF_DEBUG("rcb is NULL");
493  return NULL;
494  }
495  if(block_size > SPDY_MAX_SUPPORTED_FRAME_SIZE)
496  {
497  SPDYF_DEBUG("block_size is wrong");
498  return NULL;
499  }
500 
501  if(0 == block_size)
502  block_size = SPDY_MAX_SUPPORTED_FRAME_SIZE;
503 
504  response = SPDY_build_response(status,
505  statustext,
506  version,
507  headers,
508  NULL,
509  0);
510 
511  if(NULL == response)
512  {
513  return NULL;
514  }
515 
516  response->rcb = rcb;
517  response->rcb_cls = rcb_cls;
518  response->rcb_block_size = block_size;
519 
520  return response;
521 }
522 
523 
524 int
526  struct SPDY_Response *response,
527  bool closestream,
528  bool consider_priority,
530  void * rrcb_cls)
531 {
532  struct SPDYF_Response_Queue *headers_to_queue;
533  struct SPDYF_Response_Queue *body_to_queue;
535  void *frqcb_cls = NULL;
536  int int_consider_priority = consider_priority ? SPDY_YES : SPDY_NO;
537 
538  if(NULL == request)
539  {
540  SPDYF_DEBUG("request is NULL");
541  return SPDY_INPUT_ERROR;
542  }
543  if(NULL == response)
544  {
545  SPDYF_DEBUG("request is NULL");
546  return SPDY_INPUT_ERROR;
547  }
548 
549  if(request->stream->is_out_closed
551  return SPDY_NO;
552 
553  if(NULL != rrcb)
554  {
555  frqcb_cls = request;
557  }
558 
559  if(response->data_size > 0)
560  {
561  //SYN_REPLY and DATA will be queued
562 
563  if(NULL == (headers_to_queue = SPDYF_response_queue_create(false,
564  response->headers,
565  response->headers_size,
566  response,
567  request->stream,
568  false,
569  NULL,
570  NULL,
571  NULL,
572  NULL)))
573  {
574  return SPDY_NO;
575  }
576 
577  if(NULL == (body_to_queue = SPDYF_response_queue_create(true,
578  response->data,
579  response->data_size,
580  response,
581  request->stream,
582  closestream,
583  frqcb,
584  frqcb_cls,
585  rrcb,
586  rrcb_cls)))
587  {
588  SPDYF_response_queue_destroy(headers_to_queue);
589  return SPDY_NO;
590  }
591 
592  SPDYF_queue_response (headers_to_queue,
593  request->stream->session,
594  int_consider_priority);
595 
596  SPDYF_queue_response (body_to_queue,
597  request->stream->session,
598  int_consider_priority);
599  }
600  else if(NULL == response->rcb)
601  {
602  //no "body" will be queued, e.g. HTTP 404 without body
603 
604  if(NULL == (headers_to_queue = SPDYF_response_queue_create(false,
605  response->headers,
606  response->headers_size,
607  response,
608  request->stream,
609  closestream,
610  frqcb,
611  frqcb_cls,
612  rrcb,
613  rrcb_cls)))
614  {
615  return SPDY_NO;
616  }
617 
618  SPDYF_queue_response (headers_to_queue,
619  request->stream->session,
620  int_consider_priority);
621  }
622  else
623  {
624  //response with callbacks
625 
626  if(NULL == (headers_to_queue = SPDYF_response_queue_create(false,
627  response->headers,
628  response->headers_size,
629  response,
630  request->stream,
631  false,
632  NULL,
633  NULL,
634  NULL,
635  NULL)))
636  {
637  return SPDY_NO;
638  }
639 
640  if(NULL == (body_to_queue = SPDYF_response_queue_create(true,
641  response->data,
642  response->data_size,
643  response,
644  request->stream,
645  closestream,
646  frqcb,
647  frqcb_cls,
648  rrcb,
649  rrcb_cls)))
650  {
651  SPDYF_response_queue_destroy(headers_to_queue);
652  return SPDY_NO;
653  }
654 
655  SPDYF_queue_response (headers_to_queue,
656  request->stream->session,
657  int_consider_priority);
658 
659  SPDYF_queue_response (body_to_queue,
660  request->stream->session,
661  int_consider_priority);
662  }
663 
664  return SPDY_YES;
665 }
666 
667 
668 socklen_t
670  struct sockaddr ** addr)
671 {
672  if(NULL == session)
673  {
674  SPDYF_DEBUG("session is NULL");
675  return 0;
676  }
677 
678  *addr = session->addr;
679 
680  return session->addr_len;
681 }
682 
683 
684 struct SPDY_Session *
686 {
687  if(NULL == request)
688  {
689  SPDYF_DEBUG("request is NULL");
690  return NULL;
691  }
692 
693  return request->stream->session;
694 }
695 
696 
697 void *
699 {
700  if(NULL == session)
701  {
702  SPDYF_DEBUG("session is NULL");
703  return NULL;
704  }
705 
706  return session->user_cls;
707 }
708 
709 
710 void
712  void * cls)
713 {
714  if(NULL == session)
715  {
716  SPDYF_DEBUG("session is NULL");
717  return;
718  }
719 
720  session->user_cls = cls;
721 }
722 
723 
724 void *
726 {
727  if(NULL == request)
728  {
729  SPDYF_DEBUG("request is NULL");
730  return NULL;
731  }
732 
733  return request->user_cls;
734 }
735 
736 
737 void
739  void * cls)
740 {
741  if(NULL == request)
742  {
743  SPDYF_DEBUG("request is NULL");
744  return;
745  }
746 
747  request->user_cls = cls;
748 }