00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00025 #include "platform.h"
00026 #include "structures.h"
00027 #include "internal.h"
00028 #include "session.h"
00029 #include "io.h"
00030
00031
00041 static void
00042 spdyf_panic_std (void *cls,
00043 const char *file,
00044 unsigned int line,
00045 const char *reason)
00046 {
00047 (void)cls;
00048 fprintf (stdout, "Fatal error in libmicrospdy %s:%u: %s\n",
00049 file, line, reason);
00050
00051 abort ();
00052 }
00053
00054
00058 SPDY_PanicCallback spdyf_panic = &spdyf_panic_std;
00059
00060
00064 void *spdyf_panic_cls;
00065
00066
00073 static void
00074 spdyf_cleanup_sessions (struct SPDY_Daemon *daemon)
00075 {
00076 struct SPDY_Session *session;
00077
00078 while (NULL != (session = daemon->cleanup_head))
00079 {
00080 DLL_remove (daemon->cleanup_head,
00081 daemon->cleanup_tail,
00082 session);
00083
00084 SPDYF_session_destroy(session);
00085 }
00086 }
00087
00088
00094 static void
00095 spdyf_close_all_sessions (struct SPDY_Daemon *daemon)
00096 {
00097 struct SPDY_Session *session;
00098
00099 while (NULL != (session = daemon->sessions_head))
00100 {
00101
00102 SPDYF_prepare_goaway(session, SPDY_GOAWAY_STATUS_OK, true);
00103
00104 SPDYF_session_write(session,true);
00105 SPDYF_session_close(session);
00106 }
00107
00108 spdyf_cleanup_sessions(daemon);
00109 }
00110
00111
00119 static int
00120 spdyf_parse_options_va (struct SPDY_Daemon *daemon,
00121 va_list valist)
00122 {
00123 enum SPDY_DAEMON_OPTION opt;
00124
00125 while (SPDY_DAEMON_OPTION_END != (opt = (enum SPDY_DAEMON_OPTION) va_arg (valist, int)))
00126 {
00127 if(opt & daemon->options)
00128 {
00129 SPDYF_DEBUG("Daemon option %i used twice",opt);
00130 return SPDY_NO;
00131 }
00132 daemon->options |= opt;
00133
00134 switch (opt)
00135 {
00136 case SPDY_DAEMON_OPTION_SESSION_TIMEOUT:
00137 daemon->session_timeout = va_arg (valist, unsigned int) * 1000;
00138 break;
00139 case SPDY_DAEMON_OPTION_SOCK_ADDR:
00140 daemon->address = va_arg (valist, struct sockaddr *);
00141 break;
00142 case SPDY_DAEMON_OPTION_FLAGS:
00143 daemon->flags = va_arg (valist, enum SPDY_DAEMON_FLAG);
00144 break;
00145 case SPDY_DAEMON_OPTION_IO_SUBSYSTEM:
00146 daemon->io_subsystem = va_arg (valist, enum SPDY_IO_SUBSYSTEM);
00147 break;
00148 case SPDY_DAEMON_OPTION_MAX_NUM_FRAMES:
00149 daemon->max_num_frames = va_arg (valist, uint32_t);
00150 break;
00151 default:
00152 SPDYF_DEBUG("Wrong option for the daemon %i",opt);
00153 return SPDY_NO;
00154 }
00155 }
00156 return SPDY_YES;
00157 }
00158
00159
00160 void
00161 SPDY_set_panic_func (SPDY_PanicCallback cb,
00162 void *cls)
00163 {
00164 spdyf_panic = cb;
00165 spdyf_panic_cls = cls;
00166 }
00167
00168
00169 struct SPDY_Daemon *
00170 SPDYF_start_daemon_va (uint16_t port,
00171 const char *certfile,
00172 const char *keyfile,
00173 SPDY_NewSessionCallback nscb,
00174 SPDY_SessionClosedCallback sccb,
00175 SPDY_NewRequestCallback nrcb,
00176 SPDY_NewDataCallback npdcb,
00177 SPDYF_NewStreamCallback fnscb,
00178 SPDYF_NewDataCallback fndcb,
00179 void * cls,
00180 void * fcls,
00181 va_list valist)
00182 {
00183 struct SPDY_Daemon *daemon = NULL;
00184 int afamily;
00185 int option_on = 1;
00186 int ret;
00187 struct sockaddr_in* servaddr4 = NULL;
00188 #if HAVE_INET6
00189 struct sockaddr_in6* servaddr6 = NULL;
00190 #endif
00191 socklen_t addrlen;
00192
00193 if (NULL == (daemon = malloc (sizeof (struct SPDY_Daemon))))
00194 {
00195 SPDYF_DEBUG("malloc");
00196 return NULL;
00197 }
00198 memset (daemon, 0, sizeof (struct SPDY_Daemon));
00199 daemon->socket_fd = -1;
00200 daemon->port = port;
00201
00202 if(SPDY_YES != spdyf_parse_options_va (daemon, valist))
00203 {
00204 SPDYF_DEBUG("parse");
00205 goto free_and_fail;
00206 }
00207
00208 if(0 == daemon->max_num_frames)
00209 daemon->max_num_frames = SPDYF_NUM_SENT_FRAMES_AT_ONCE;
00210
00211 if(!port && NULL == daemon->address)
00212 {
00213 SPDYF_DEBUG("Port is 0");
00214 goto free_and_fail;
00215 }
00216 if(0 == daemon->io_subsystem)
00217 daemon->io_subsystem = SPDY_IO_SUBSYSTEM_OPENSSL;
00218
00219 if(SPDY_YES != SPDYF_io_set_daemon(daemon, daemon->io_subsystem))
00220 goto free_and_fail;
00221
00222 if(SPDY_IO_SUBSYSTEM_RAW != daemon->io_subsystem)
00223 {
00224 if (NULL == certfile
00225 || NULL == (daemon->certfile = strdup (certfile)))
00226 {
00227 SPDYF_DEBUG("strdup (certfile)");
00228 goto free_and_fail;
00229 }
00230 if (NULL == keyfile
00231 || NULL == (daemon->keyfile = strdup (keyfile)))
00232 {
00233 SPDYF_DEBUG("strdup (keyfile)");
00234 goto free_and_fail;
00235 }
00236 }
00237
00238 daemon->new_session_cb = nscb;
00239 daemon->session_closed_cb = sccb;
00240 daemon->new_request_cb = nrcb;
00241 daemon->received_data_cb = npdcb;
00242 daemon->cls = cls;
00243 daemon->fcls = fcls;
00244 daemon->fnew_stream_cb = fnscb;
00245 daemon->freceived_data_cb = fndcb;
00246
00247 #if HAVE_INET6
00248
00249 if((daemon->flags & SPDY_DAEMON_FLAG_ONLY_IPV6)
00250 && NULL != daemon->address && AF_INET6 != daemon->address->sa_family)
00251 {
00252 SPDYF_DEBUG("SPDY_DAEMON_FLAG_ONLY_IPV6 set but IPv4 address provided");
00253 goto free_and_fail;
00254 }
00255
00256 addrlen = sizeof (struct sockaddr_in6);
00257
00258 if(NULL == daemon->address)
00259 {
00260 if (NULL == (servaddr6 = malloc (addrlen)))
00261 {
00262 SPDYF_DEBUG("malloc");
00263 goto free_and_fail;
00264 }
00265 memset (servaddr6, 0, addrlen);
00266 servaddr6->sin6_family = AF_INET6;
00267 servaddr6->sin6_addr = in6addr_any;
00268 servaddr6->sin6_port = htons (port);
00269 daemon->address = (struct sockaddr *) servaddr6;
00270 }
00271
00272 if(AF_INET6 == daemon->address->sa_family)
00273 {
00274 afamily = PF_INET6;
00275 }
00276 else
00277 {
00278 afamily = PF_INET;
00279 }
00280 #else
00281
00282 if(daemon->flags & SPDY_DAEMON_FLAG_ONLY_IPV6)
00283 {
00284 SPDYF_DEBUG("SPDY_DAEMON_FLAG_ONLY_IPV6 set but no support");
00285 goto free_and_fail;
00286 }
00287
00288 addrlen = sizeof (struct sockaddr_in);
00289
00290 if(NULL == daemon->address)
00291 {
00292 if (NULL == (servaddr4 = malloc (addrlen)))
00293 {
00294 SPDYF_DEBUG("malloc");
00295 goto free_and_fail;
00296 }
00297 memset (servaddr4, 0, addrlen);
00298 servaddr4->sin_family = AF_INET;
00299 servaddr4->sin_addr = INADDR_ANY;
00300 servaddr4->sin_port = htons (port);
00301 daemon->address = (struct sockaddr *) servaddr4;
00302 }
00303
00304 afamily = PF_INET;
00305 #endif
00306
00307 daemon->socket_fd = socket (afamily, SOCK_STREAM, 0);
00308 if (-1 == daemon->socket_fd)
00309 {
00310 SPDYF_DEBUG("sock");
00311 goto free_and_fail;
00312 }
00313
00314
00315 ret = setsockopt(daemon->socket_fd, SOL_SOCKET, SO_REUSEADDR, &option_on, sizeof(option_on));
00316 if(ret)
00317 {
00318 SPDYF_DEBUG("WARNING: SO_REUSEADDR was not set for the server");
00319 }
00320
00321 #if HAVE_INET6
00322 if(daemon->flags & SPDY_DAEMON_FLAG_ONLY_IPV6)
00323 {
00324 ret = setsockopt(daemon->socket_fd, IPPROTO_IPV6, IPV6_V6ONLY, &option_on, sizeof(option_on));
00325 if(ret)
00326 {
00327 SPDYF_DEBUG("setsockopt with IPPROTO_IPV6 failed");
00328 goto free_and_fail;
00329 }
00330 }
00331 #endif
00332
00333 if (-1 == bind (daemon->socket_fd, daemon->address, addrlen))
00334 {
00335 SPDYF_DEBUG("bind %i",errno);
00336 goto free_and_fail;
00337 }
00338
00339 if (listen (daemon->socket_fd, 20) < 0)
00340 {
00341 SPDYF_DEBUG("listen %i",errno);
00342 goto free_and_fail;
00343 }
00344
00345 if(SPDY_YES != daemon->fio_init(daemon))
00346 {
00347 SPDYF_DEBUG("tls");
00348 goto free_and_fail;
00349 }
00350
00351 return daemon;
00352
00353
00354 free_and_fail:
00355 if(daemon->socket_fd > 0)
00356 (void)close (daemon->socket_fd);
00357
00358 free(servaddr4);
00359 #if HAVE_INET6
00360 free(servaddr6);
00361 #endif
00362 if(NULL != daemon->certfile)
00363 free(daemon->certfile);
00364 if(NULL != daemon->keyfile)
00365 free(daemon->keyfile);
00366 free (daemon);
00367
00368 return NULL;
00369 }
00370
00371
00372 void
00373 SPDYF_stop_daemon (struct SPDY_Daemon *daemon)
00374 {
00375 daemon->fio_deinit(daemon);
00376
00377 shutdown (daemon->socket_fd, SHUT_RDWR);
00378 spdyf_close_all_sessions (daemon);
00379 (void)close (daemon->socket_fd);
00380
00381 if(!(SPDY_DAEMON_OPTION_SOCK_ADDR & daemon->options))
00382 free(daemon->address);
00383
00384 free(daemon->certfile);
00385 free(daemon->keyfile);
00386
00387 free(daemon);
00388 }
00389
00390
00391 int
00392 SPDYF_get_timeout (struct SPDY_Daemon *daemon,
00393 unsigned long long *timeout)
00394 {
00395 unsigned long long earliest_deadline = 0;
00396 unsigned long long now;
00397 struct SPDY_Session *pos;
00398 bool have_timeout;
00399
00400 if(0 == daemon->session_timeout)
00401 return SPDY_NO;
00402
00403 now = SPDYF_monotonic_time();
00404 have_timeout = false;
00405 for (pos = daemon->sessions_head; NULL != pos; pos = pos->next)
00406 {
00407 if ( (! have_timeout) ||
00408 (earliest_deadline > pos->last_activity + daemon->session_timeout) )
00409 earliest_deadline = pos->last_activity + daemon->session_timeout;
00410
00411 have_timeout = true;
00412
00413 if (SPDY_YES == pos->fio_is_pending(pos))
00414 {
00415 earliest_deadline = 0;
00416 break;
00417 }
00418 }
00419
00420 if (!have_timeout)
00421 return SPDY_NO;
00422 if (earliest_deadline <= now)
00423 *timeout = 0;
00424 else
00425 *timeout = earliest_deadline - now;
00426
00427 return SPDY_YES;
00428 }
00429
00430
00431 int
00432 SPDYF_get_fdset (struct SPDY_Daemon *daemon,
00433 fd_set *read_fd_set,
00434 fd_set *write_fd_set,
00435 fd_set *except_fd_set,
00436 bool all)
00437 {
00438 (void)except_fd_set;
00439 struct SPDY_Session *pos;
00440 int fd;
00441 int max_fd = -1;
00442
00443 fd = daemon->socket_fd;
00444 if (-1 != fd)
00445 {
00446 FD_SET (fd, read_fd_set);
00447
00448 max_fd = fd;
00449 }
00450
00451 for (pos = daemon->sessions_head; NULL != pos; pos = pos->next)
00452 {
00453 fd = pos->socket_fd;
00454 FD_SET(fd, read_fd_set);
00455 if (all
00456 || (NULL != pos->response_queue_head)
00457 || (NULL != pos->write_buffer)
00458 || (SPDY_SESSION_STATUS_CLOSING == pos->status)
00459 || (daemon->session_timeout
00460 && (pos->last_activity + daemon->session_timeout < SPDYF_monotonic_time()))
00461 || (SPDY_YES == pos->fio_is_pending(pos))
00462 || ((pos->read_buffer_offset - pos->read_buffer_beginning) > 0)
00463 )
00464 FD_SET(fd, write_fd_set);
00465 if(fd > max_fd)
00466 max_fd = fd;
00467 }
00468
00469 return max_fd;
00470 }
00471
00472
00473 void
00474 SPDYF_run (struct SPDY_Daemon *daemon)
00475 {
00476 struct SPDY_Session *pos;
00477 struct SPDY_Session *next;
00478 int num_ready;
00479 fd_set rs;
00480 fd_set ws;
00481 fd_set es;
00482 int max;
00483 struct timeval timeout;
00484 int ds;
00485
00486 timeout.tv_sec = 0;
00487 timeout.tv_usec = 0;
00488 FD_ZERO (&rs);
00489 FD_ZERO (&ws);
00490 FD_ZERO (&es);
00491
00492 max = SPDYF_get_fdset(daemon,&rs,&ws,&es, true);
00493
00494 num_ready = select (max + 1, &rs, &ws, &es, &timeout);
00495
00496 if(num_ready < 1)
00497 return;
00498
00499 if ( (-1 != (ds = daemon->socket_fd)) &&
00500 (FD_ISSET (ds, &rs)) ){
00501 SPDYF_session_accept(daemon);
00502 }
00503
00504 next = daemon->sessions_head;
00505 while (NULL != (pos = next))
00506 {
00507 next = pos->next;
00508 ds = pos->socket_fd;
00509 if (ds != -1)
00510 {
00511
00512 if (FD_ISSET (ds, &rs) || pos->fio_is_pending(pos)){
00513 SPDYF_session_read(pos);
00514 }
00515
00516
00517 if(SPDY_NO == SPDYF_session_idle(pos))
00518 {
00519
00520
00521 }
00522
00523
00524
00525
00526 if (FD_ISSET (ds, &ws)){
00527 if(SPDY_NO == SPDYF_session_write(pos, false))
00528 {
00529
00530
00531 }
00532 }
00533
00534
00535
00536
00537
00538
00539
00540 }
00541 }
00542
00543 spdyf_cleanup_sessions(daemon);
00544 }