00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "klone_conf.h"
00012 #include <sys/types.h>
00013 #include <sys/stat.h>
00014 #ifdef HAVE_SYS_WAIT
00015 #include <sys/wait.h>
00016 #endif
00017 #include <u/libu.h>
00018 #include <stdlib.h>
00019 #include <unistd.h>
00020 #include <errno.h>
00021 #include <fcntl.h>
00022 #include <klone/server.h>
00023 #include <klone/backend.h>
00024 #include <klone/os.h>
00025 #include <klone/timer.h>
00026 #include <klone/context.h>
00027 #include <klone/ppc.h>
00028 #include <klone/ppc_cmd.h>
00029 #include <klone/addr.h>
00030 #include <klone/utils.h>
00031 #include <klone/klog.h>
00032 #include <klone/hook.h>
00033 #include <klone/hookprv.h>
00034 #include <klone/server_ppc_cmd.h>
00035 #include "server_s.h"
00036 #include "child.h"
00037
00038 #define SERVER_MAX_BACKENDS 8
00039
00040 enum watch_fd_e
00041 {
00042 WATCH_FD_READ = 1 << 1,
00043 WATCH_FD_WRITE = 1 << 2,
00044 WATCH_FD_EXCP = 1 << 3
00045 };
00046
00047 static void server_watch_fd(server_t *s, int fd, unsigned int mode);
00048 static void server_clear_fd(server_t *s, int fd, unsigned int mode);
00049 static void server_close_fd(server_t *s, int fd);
00050
00051 static int server_be_listen(backend_t *be)
00052 {
00053 enum { DEFAULT_BACKLOG = 1024 };
00054 int d = 0, backlog = 0, val = 1;
00055 u_config_t *subkey;
00056
00057 dbg_return_if (be == NULL, ~0);
00058 dbg_return_if (be->addr == NULL, ~0);
00059
00060 switch(be->addr->type)
00061 {
00062 case ADDR_IPV4:
00063 dbg_err_if((d = socket(AF_INET, SOCK_STREAM, 0)) < 0);
00064 #ifndef OS_WIN
00065
00066
00067
00068 dbg_err_if(setsockopt(d, SOL_SOCKET, SO_REUSEADDR, (void *)&val,
00069 sizeof(int)) < 0);
00070 #endif
00071 dbg_err_if(bind(d, (void*)&be->addr->sa.sin,
00072 sizeof(struct sockaddr_in)));
00073 break;
00074 case ADDR_IPV6:
00075 case ADDR_UNIX:
00076 default:
00077 crit_err_if("unupported addr type");
00078 }
00079
00080 if(!u_config_get_subkey(be->config, "backlog", &subkey))
00081 backlog = atoi(u_config_get_value(subkey));
00082
00083 if(!backlog)
00084 backlog = DEFAULT_BACKLOG;
00085
00086 dbg_err_if(listen(d, backlog));
00087
00088 be->ld = d;
00089
00090 return 0;
00091 err:
00092 warn_strerror(errno);
00093 if(d)
00094 close(d);
00095 return ~0;
00096 }
00097
00098
00099 #ifdef OS_UNIX
00100
00101 static int server_reap_child(server_t *s, pid_t pid)
00102 {
00103 child_t *child;
00104 backend_t *be;
00105
00106 dbg_err_if (s == NULL);
00107
00108
00109 dbg_err_if(children_get_by_pid(s->children, pid, &child));
00110
00111
00112 dbg_err_if(children_del(s->children, child));
00113 be = child->be;
00114
00115
00116 be->nchild--;
00117 if(be->nchild < be->start_child)
00118 be->fork_child = be->start_child - be->nchild;
00119
00120 U_FREE(child);
00121
00122 return 0;
00123 err:
00124 return ~0;
00125 }
00126
00127
00128 static int server_add_child(server_t *s, pid_t pid, backend_t *be)
00129 {
00130 child_t *child = NULL;
00131
00132 dbg_err_if (s == NULL);
00133 dbg_err_if (be == NULL);
00134
00135 dbg_err_if(child_create(pid, be, &child));
00136
00137 dbg_err_if(children_add(s->children, child));
00138
00139 be->nchild++;
00140
00141 return 0;
00142 err:
00143 return ~0;
00144 }
00145
00146
00147 static int server_signal_children(server_t *s, int sig)
00148 {
00149 child_t *child;
00150 ssize_t i;
00151
00152 dbg_return_if (s == NULL, ~0);
00153
00154 for(i = children_count(s->children) - 1; i >= 0; --i)
00155 {
00156 if(!children_getn(s->children, i, &child))
00157 dbg_err_if(kill(child->pid, sig) < 0);
00158 }
00159
00160 return 0;
00161 err:
00162 dbg_strerror(errno);
00163 return ~0;
00164 }
00165 #endif
00166
00167 static void server_term_children(server_t *s)
00168 {
00169 dbg_ifb(s == NULL) return;
00170 #ifdef OS_UNIX
00171 server_signal_children(s, SIGTERM);
00172 #endif
00173 return;
00174 }
00175
00176 static void server_kill_children(server_t *s)
00177 {
00178 dbg_ifb(s == NULL) return;
00179 #ifdef OS_UNIX
00180 server_signal_children(s, SIGKILL);
00181 #endif
00182 return;
00183 }
00184
00185 static void server_sigint(int sig)
00186 {
00187 u_unused_args(sig);
00188
00189 warn("SIGINT");
00190
00191 if(ctx && ctx->server)
00192 server_stop(ctx->server);
00193
00194 emb_term();
00195 }
00196
00197 static void server_sigterm(int sig)
00198 {
00199 u_unused_args(sig);
00200
00201
00202
00203
00204 if(ctx->pipc)
00205 _exit(0);
00206
00207 warn("SIGTERM");
00208
00209 if(ctx && ctx->server)
00210 server_stop(ctx->server);
00211 }
00212
00213 #ifdef OS_UNIX
00214 static void server_sigchld(int sig)
00215 {
00216 server_t *s = ctx->server;
00217
00218 u_unused_args(sig);
00219
00220 s->reap_children = 1;
00221 }
00222
00223 static void server_waitpid(server_t *s)
00224 {
00225 pid_t pid = -1;
00226 int status;
00227
00228 dbg_ifb(s == NULL) return;
00229
00230 u_sig_block(SIGCHLD);
00231
00232
00233 while((pid = waitpid(-1, &status, WNOHANG)) > 0)
00234 {
00235 if(WIFEXITED(status) && WEXITSTATUS(status) != EXIT_SUCCESS)
00236 warn("pid [%u], exit code [%d]", pid, WEXITSTATUS(status));
00237
00238 if(WIFSIGNALED(status))
00239 warn("pid [%u], signal [%d]", pid, WTERMSIG(status));
00240
00241
00242 server_reap_child(s, pid);
00243 }
00244
00245 s->reap_children = 0;
00246
00247 u_sig_unblock(SIGCHLD);
00248 }
00249 #endif
00250
00251 static void server_recalc_hfd(server_t *s)
00252 {
00253 register int i;
00254 fd_set *prdfds, *pwrfds, *pexfds;
00255
00256 dbg_ifb(s == NULL) return;
00257
00258 prdfds = &s->rdfds;
00259 pwrfds = &s->wrfds;
00260 pexfds = &s->exfds;
00261
00262
00263 for(i = s->hfd, s->hfd = 0; i > 0; --i)
00264 {
00265 if(FD_ISSET(i, prdfds) || FD_ISSET(i, pwrfds) || FD_ISSET(i, pexfds))
00266 {
00267 s->hfd = i;
00268 break;
00269 }
00270 }
00271 }
00272
00273 static void server_clear_fd(server_t *s, int fd, unsigned int mode)
00274 {
00275 dbg_ifb(s == NULL) return;
00276
00277 if(mode & WATCH_FD_READ)
00278 FD_CLR(fd, &s->rdfds);
00279
00280 if(mode & WATCH_FD_WRITE)
00281 FD_CLR(fd, &s->wrfds);
00282
00283 if(mode & WATCH_FD_EXCP)
00284 FD_CLR(fd, &s->exfds);
00285
00286 server_recalc_hfd(s);
00287 }
00288
00289 static void server_watch_fd(server_t *s, int fd, unsigned int mode)
00290 {
00291 dbg_ifb(s == NULL) return;
00292 dbg_ifb(fd < 0) return;
00293
00294 if(mode & WATCH_FD_READ)
00295 FD_SET(fd, &s->rdfds);
00296
00297 if(mode & WATCH_FD_WRITE)
00298 FD_SET(fd, &s->wrfds);
00299
00300 if(mode & WATCH_FD_EXCP)
00301 FD_SET(fd, &s->exfds);
00302
00303 s->hfd = MAX(s->hfd, fd);
00304 }
00305
00306 static void server_close_fd(server_t *s, int fd)
00307 {
00308 dbg_ifb(s == NULL) return;
00309 dbg_ifb(fd < 0) return;
00310
00311 server_clear_fd(s, fd, WATCH_FD_READ | WATCH_FD_WRITE | WATCH_FD_EXCP);
00312 close(fd);
00313 }
00314
00315 static int server_be_accept(server_t *s, backend_t *be, int *pfd)
00316 {
00317 struct sockaddr sa;
00318 int sa_len = sizeof(struct sockaddr);
00319 int ad;
00320
00321 u_unused_args(s);
00322
00323 dbg_return_if (be == NULL, ~0);
00324 dbg_return_if (pfd == NULL, ~0);
00325
00326 again:
00327 ad = accept(be->ld, &sa, &sa_len);
00328 if(ad == -1 && errno == EINTR)
00329 goto again;
00330 dbg_err_if(ad == -1);
00331
00332 *pfd = ad;
00333
00334 return 0;
00335 err:
00336 if(ad < 0)
00337 warn_strerror(errno);
00338 return ~0;
00339 }
00340
00341 static int server_backend_detach(server_t *s, backend_t *be)
00342 {
00343 s->nbackend--;
00344
00345 dbg_return_if (s == NULL, ~0);
00346 dbg_return_if (be == NULL, ~0);
00347
00348 addr_free(be->addr);
00349 be->server = NULL;
00350 be->addr = NULL;
00351 be->config = NULL;
00352
00353 close(be->ld);
00354 be->ld = -1;
00355
00356 backend_free(be);
00357
00358 return 0;
00359 }
00360
00361 #ifdef OS_UNIX
00362 static int server_chroot_to(server_t *s, const char *dir)
00363 {
00364 dbg_return_if (s == NULL, ~0);
00365 dbg_return_if (dir == NULL, ~0);
00366
00367 u_unused_args(s);
00368
00369 dbg_err_if(chroot((char*)dir));
00370
00371 dbg_err_if(chdir("/"));
00372
00373 info("chroot'd: %s", dir);
00374
00375 return 0;
00376 err:
00377 warn_strerror(errno);
00378 return ~0;
00379 }
00380
00381 static int server_foreach_cb(struct dirent *d, const char *path, void *arg)
00382 {
00383 int *pfound = (int*)arg;
00384
00385 u_unused_args(d, path);
00386
00387 *pfound = 1;
00388
00389 return ~0;
00390 }
00391
00392 static int server_chroot_blind(server_t *s)
00393 {
00394 enum { BLIND_DIR_MODE = 0100 };
00395 char dir[U_PATH_MAX];
00396 struct stat st;
00397 int fd_dir = -1, found;
00398 pid_t child;
00399 unsigned int mask;
00400
00401 dbg_err_if (s == NULL);
00402 dbg_err_if (s->chroot == NULL);
00403
00404 dbg_err_if(u_path_snprintf(dir, U_PATH_MAX, U_PATH_SEPARATOR,
00405 "%s/kloned_blind_chroot_%d.dir", s->chroot, getpid()));
00406
00407
00408 dbg_err_if(mkdir(dir, BLIND_DIR_MODE ));
00409
00410
00411 dbg_err_if((fd_dir = open(dir, O_RDONLY, 0)) < 0);
00412
00413 dbg_err_if((child = fork()) < 0);
00414
00415 if(child == 0)
00416 {
00417
00418
00419 sleep(1);
00420 dbg("[child] removing dir: %s\n", dir);
00421 rmdir(dir);
00422 _exit(0);
00423 }
00424
00425
00426
00427 dbg_err_if(server_chroot_to(s, dir));
00428
00429
00430
00431
00432 dbg_err_if(fstat(fd_dir, &st));
00433
00434
00435 dbg_err_if(st.st_gid || st.st_uid);
00436
00437
00438 dbg_err_if((st.st_mode & 07777) != BLIND_DIR_MODE);
00439
00440
00441 found = 0;
00442 mask = S_IFIFO | S_IFCHR | S_IFDIR | S_IFBLK | S_IFREG | S_IFLNK | S_IFSOCK;
00443 dbg_err_if(u_foreach_dir_item("/", mask, server_foreach_cb, &found));
00444
00445
00446 dbg_err_if(found);
00447
00448 close(fd_dir);
00449
00450 return 0;
00451 err:
00452 if(fd_dir >= 0)
00453 close(fd_dir);
00454 warn_strerror(errno);
00455 return ~0;
00456 }
00457
00458 static int server_chroot(server_t *s)
00459 {
00460 dbg_return_if (s == NULL, ~0);
00461
00462 if(s->blind_chroot)
00463 return server_chroot_blind(s);
00464 else
00465 return server_chroot_to(s, s->chroot);
00466 }
00467
00468 static int server_drop_privileges(server_t *s)
00469 {
00470 uid_t uid;
00471 gid_t gid;
00472
00473 dbg_return_if (s == NULL, ~0);
00474
00475 if(s->gid > 0)
00476 {
00477 gid = (gid_t)s->gid;
00478
00479
00480 dbg_err_if(setgroups(1, &gid));
00481
00482
00483 dbg_err_if(setgid(gid));
00484 dbg_err_if(setegid(gid));
00485
00486
00487 dbg_err_if(getgid() != gid || getegid() != gid);
00488 }
00489
00490 if(s->uid > 0)
00491 {
00492 uid = (uid_t)s->uid;
00493
00494
00495 dbg_err_if(setuid(uid));
00496 dbg_err_if(seteuid(uid));
00497
00498
00499 dbg_err_if(getuid() != uid || geteuid() != uid);
00500 }
00501
00502 return 0;
00503 err:
00504 warn_strerror(errno);
00505 return ~0;
00506 }
00507
00508 static int server_fork_child(server_t *s, backend_t *be)
00509 {
00510 backend_t *obe;
00511 pid_t child;
00512 int socks[2];
00513
00514 dbg_return_if (s == NULL, -1);
00515 dbg_return_if (be == NULL, -1);
00516
00517 dbg_return_if (children_count(s->children) == s->max_child, -1);
00518 dbg_return_if (be->nchild == be->max_child, -1);
00519
00520
00521 dbg_err_if(socketpair(AF_UNIX, SOCK_STREAM, 0, socks) < 0);
00522
00523 if((child = fork()) == 0)
00524 {
00525
00526
00527 s->klog_flush = 0;
00528
00529
00530 srand(rand() + getpid() + time(0));
00531
00532
00533 close(socks[0]);
00534
00535
00536 ctx->pipc = socks[1];
00537 ctx->backend = be;
00538
00539
00540 LIST_FOREACH(obe, &s->bes, np)
00541 {
00542 if(obe == be)
00543 continue;
00544 close(obe->ld);
00545 obe->ld = -1;
00546 }
00547
00548
00549 dbg_err_if(children_clear(s->children));
00550
00551 } else if(child > 0) {
00552
00553
00554
00555 server_add_child(s, child, be);
00556
00557
00558 close(socks[1]);
00559
00560
00561 server_watch_fd(s, socks[0], WATCH_FD_READ);
00562 } else {
00563 warn_err("fork error");
00564 }
00565
00566 return child;
00567 err:
00568 warn_strerror(errno);
00569 return -1;
00570 }
00571
00572 static int server_child_serve(server_t *s, backend_t *be, int ad)
00573 {
00574 pid_t child;
00575
00576 dbg_return_if (s == NULL, ~0);
00577 dbg_return_if (be == NULL, ~0);
00578
00579 dbg_err_if((child = server_fork_child(s, be)) < 0);
00580
00581 if(child == 0)
00582 {
00583
00584
00585 close(be->ld);
00586
00587 hook_call(child_init);
00588
00589
00590 dbg_if(backend_serve(be, ad));
00591
00592 hook_call(child_term);
00593
00594
00595 close(ad);
00596 server_stop(be->server);
00597 }
00598
00599
00600 return 0;
00601 err:
00602 warn_strerror(errno);
00603 return ~0;
00604 }
00605
00606 static int server_cb_spawn_child(talarm_t *al, void *arg)
00607 {
00608 server_t *s = (server_t*)arg;
00609
00610 u_unused_args(al);
00611
00612 dbg_err_if (s == NULL);
00613
00614
00615 dbg_err_if(ctx->backend == NULL || ctx->pipc == 0);
00616
00617
00618 dbg_err_if(server_ppc_cmd_fork_child(s, ctx->backend));
00619
00620
00621
00622 server_stop(s);
00623
00624 return 0;
00625 err:
00626 return ~0;
00627 }
00628 #endif
00629
00630 static int server_be_serve(server_t *s, backend_t *be, int ad)
00631 {
00632 talarm_t *al = NULL;
00633
00634 dbg_err_if (s == NULL);
00635 dbg_err_if (be == NULL);
00636
00637 switch(be->model)
00638 {
00639 #ifdef OS_UNIX
00640 case SERVER_MODEL_FORK:
00641
00642 dbg_err_if(server_child_serve(s, be, ad));
00643 break;
00644
00645 case SERVER_MODEL_PREFORK:
00646
00647
00648 dbg_err_if(timerm_add(1, server_cb_spawn_child, (void*)s, &al));
00649
00650
00651 dbg_if(backend_serve(be, ad));
00652
00653
00654 timerm_del(al);
00655 break;
00656 #endif
00657
00658 case SERVER_MODEL_ITERATIVE:
00659
00660 dbg_if(backend_serve(be, ad));
00661 break;
00662
00663 default:
00664 warn_err_if("server model not supported");
00665 }
00666
00667
00668 close(ad);
00669
00670 return 0;
00671 err:
00672 close(ad);
00673 return ~0;
00674 }
00675
00676 int server_stop(server_t *s)
00677 {
00678 dbg_err_if (s == NULL);
00679
00680 if(ctx->pipc)
00681 {
00682
00683 dbg_err_if(ctx->backend == NULL);
00684
00685
00686 close(ctx->backend->ld);
00687 }
00688
00689
00690 s->stop = 1;
00691
00692 return 0;
00693 err:
00694 return ~0;
00695 }
00696
00697 static int server_listen(server_t *s)
00698 {
00699 backend_t *be;
00700
00701 dbg_err_if (s == NULL);
00702
00703 LIST_FOREACH(be, &s->bes, np)
00704 {
00705
00706 dbg_err_if(server_be_listen(be));
00707
00708
00709 if(be->model != SERVER_MODEL_PREFORK)
00710 server_watch_fd(s, be->ld, WATCH_FD_READ);
00711 }
00712
00713 return 0;
00714 err:
00715 return ~0;
00716 }
00717
00718 int server_cgi(server_t *s)
00719 {
00720 backend_t *be;
00721
00722 dbg_err_if (s == NULL);
00723
00724
00725 LIST_FOREACH(be, &s->bes, np)
00726 {
00727 if(strcasecmp(be->proto, "http") == 0)
00728 {
00729 hook_call(server_init);
00730
00731 dbg_if(backend_serve(be, 0));
00732
00733 hook_call(server_term);
00734
00735 return 0;
00736 }
00737 }
00738
00739 err:
00740 return ~0;
00741 }
00742
00743 ppc_t* server_get_ppc(server_t *s)
00744 {
00745 dbg_return_if (s == NULL, NULL);
00746
00747 return s->ppc;
00748 }
00749
00750 static int server_process_ppc(server_t *s, int fd)
00751 {
00752 unsigned char cmd;
00753 char data[PPC_MAX_DATA_SIZE];
00754 ssize_t n;
00755
00756 dbg_err_if (s == NULL);
00757 dbg_err_if (fd < 0);
00758
00759
00760 n = ppc_read(s->ppc, fd, &cmd, data, PPC_MAX_DATA_SIZE);
00761 if(n > 0)
00762 {
00763
00764 dbg_err_if(ppc_dispatch(s->ppc, fd, cmd, data, n));
00765 } else if(n == 0) {
00766
00767
00768 server_close_fd(s, fd);
00769 } else {
00770
00771 server_close_fd(s, fd);
00772 }
00773
00774 return 0;
00775 err:
00776 return ~0;
00777 }
00778
00779 static int server_set_socket_opts(server_t *s, int sock)
00780 {
00781 int on = 1;
00782
00783 u_unused_args(s);
00784
00785 dbg_err_if (sock < 0);
00786
00787 #ifdef HAVE_TCP_NODELAY
00788
00789 warn_err_sif(setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
00790 (void*) &on, sizeof(int)) < 0);
00791 #endif
00792
00793 return 0;
00794 err:
00795 return ~0;
00796 }
00797
00798 static int server_dispatch(server_t *s, int fd)
00799 {
00800 backend_t *be;
00801 int ad = -1;
00802
00803 dbg_err_if (s == NULL);
00804
00805
00806 LIST_FOREACH(be, &s->bes, np)
00807 if(be->ld == fd)
00808 break;
00809
00810 if(be == NULL)
00811 return server_process_ppc(s, fd);
00812
00813
00814 dbg_err_if(server_be_accept(s, be, &ad));
00815
00816
00817 dbg_err_if(server_set_socket_opts(s, ad));
00818
00819
00820 dbg_err_if(server_be_serve(s, be, ad));
00821
00822 return 0;
00823 err:
00824 U_CLOSE(ad);
00825 return ~0;
00826 }
00827
00828 int server_cb_klog_flush(talarm_t *a, void *arg)
00829 {
00830 server_t *s = (server_t*)arg;
00831
00832 u_unused_args(a);
00833
00834 dbg_return_if (s == NULL, ~0);
00835
00836
00837 s->klog_flush++;
00838
00839 return 0;
00840 }
00841
00842 #ifdef OS_UNIX
00843 int server_spawn_child(server_t *s, backend_t *be)
00844 {
00845 size_t c;
00846 int rc;
00847
00848 dbg_err_if (s == NULL);
00849 dbg_err_if (be == NULL);
00850
00851 dbg_err_if((rc = server_fork_child(s, be)) < 0);
00852 if(rc > 0)
00853 return 0;
00854
00855
00856 hook_call(child_init);
00857
00858
00859
00860
00861 for(c = 0; !s->stop && c < be->max_rq_xchild; ++c)
00862 {
00863
00864 dbg_err_if(server_dispatch(s, be->ld));
00865 }
00866
00867
00868 hook_call(child_term);
00869
00870 server_stop(s);
00871
00872 return 0;
00873 err:
00874 return ~0;
00875 }
00876
00877
00878 static int server_spawn_children(server_t *s)
00879 {
00880 backend_t *be;
00881 register size_t i;
00882
00883 dbg_err_if (s == NULL);
00884
00885
00886 LIST_FOREACH (be, &s->bes, np)
00887 {
00888 if(be->model != SERVER_MODEL_PREFORK || be->fork_child == 0)
00889 continue;
00890
00891
00892 for(i = 0; i < be->fork_child; ++i)
00893 {
00894 dbg_err_if(server_spawn_child(s, be));
00895
00896 if(ctx->pipc)
00897 break;
00898 be->fork_child--;
00899 }
00900 }
00901
00902 return 0;
00903 err:
00904 return ~0;
00905 }
00906 #endif
00907
00908 int server_loop(server_t *s)
00909 {
00910 struct timeval tv;
00911 int rc, fd;
00912 fd_set rdfds, wrfds, exfds;
00913
00914 dbg_err_if (s == NULL);
00915 dbg_err_if (s->config == NULL);
00916
00917 dbg_err_if(server_listen(s));
00918
00919 #ifdef OS_UNIX
00920
00921 if(s->chroot)
00922 dbg_err_if(server_chroot(s));
00923
00924
00925 warn_err_sifm(server_drop_privileges(s), "unable to drop priviledges");
00926
00927
00928 if(!s->allow_root)
00929 warn_err_ifm(!getuid() || !geteuid() || !getgid() || !getegid(),
00930 "you must set the allow_root config option to run kloned as root");
00931 #endif
00932
00933
00934 hook_call(server_init);
00935
00936 for(; !s->stop; )
00937 {
00938 #ifdef OS_UNIX
00939
00940 dbg_if(server_spawn_children(s));
00941 #endif
00942
00943
00944 if(ctx->pipc)
00945 break;
00946
00947 memcpy(&rdfds, &s->rdfds, sizeof(fd_set));
00948 memcpy(&wrfds, &s->wrfds, sizeof(fd_set));
00949 memcpy(&exfds, &s->exfds, sizeof(fd_set));
00950
00951
00952 tv.tv_sec = 1; tv.tv_usec = 0;
00953
00954 again:
00955 rc = select(1 + s->hfd, &rdfds, &wrfds, &exfds, &tv);
00956 if(rc == -1 && errno == EINTR)
00957 goto again;
00958 dbg_err_if(rc == -1);
00959
00960 #ifdef OS_UNIX
00961 if(s->reap_children)
00962 server_waitpid(s);
00963 #endif
00964
00965
00966 if(s->klog_flush && ctx->pipc == 0)
00967 {
00968
00969 klog_flush(s->klog);
00970
00971
00972 s->klog_flush = 0;
00973
00974 U_FREE(s->al_klog_flush);
00975
00976
00977 dbg_err_if(timerm_add(SERVER_LOG_FLUSH_TIMEOUT,
00978 server_cb_klog_flush, s, &s->al_klog_flush));
00979 }
00980
00981
00982 for(fd = 0; rc && fd < 1 + s->hfd; ++fd)
00983 {
00984 if(FD_ISSET(fd, &rdfds))
00985 {
00986 --rc;
00987
00988 dbg_if(server_dispatch(s, fd));
00989 }
00990 }
00991
00992 }
00993
00994
00995 if(ctx->pipc)
00996 return 0;
00997
00998
00999 hook_call(server_term);
01000
01001
01002 server_term_children(s);
01003
01004 sleep(1);
01005
01006
01007 if(s->nchild)
01008 server_kill_children(s);
01009
01010 return 0;
01011 err:
01012 return ~0;
01013 }
01014
01015 int server_free(server_t *s)
01016 {
01017 backend_t *be;
01018
01019 dbg_err_if (s == NULL);
01020
01021
01022 u_log_set_hook(NULL, NULL, NULL, NULL);
01023
01024
01025 if(s->al_klog_flush)
01026 {
01027 timerm_del(s->al_klog_flush);
01028 s->al_klog_flush = NULL;
01029 }
01030
01031 if(s->klog)
01032 {
01033
01034
01035
01036
01037
01038
01039 if(ctx->pipc == 0)
01040 klog_close(s->klog);
01041 s->klog = NULL;
01042 }
01043
01044 while((be = LIST_FIRST(&s->bes)) != NULL)
01045 {
01046 LIST_REMOVE(be, np);
01047 server_backend_detach(s, be);
01048 }
01049
01050 dbg_if(ppc_free(s->ppc));
01051
01052 dbg_if(children_free(s->children));
01053
01054 #ifdef OS_WIN
01055 WSACleanup();
01056 #endif
01057
01058 U_FREE(s);
01059 return 0;
01060 err:
01061 return ~0;
01062 }
01063
01064 static int server_setup_backend(server_t *s, backend_t *be)
01065 {
01066 u_config_t *subkey;
01067
01068 dbg_return_if (s == NULL, ~0);
01069 dbg_return_if (be == NULL, ~0);
01070
01071
01072 s->nbackend++;
01073
01074
01075 warn_err_ifm(u_config_get_subkey(be->config, "addr", &subkey),
01076 "missing or bad '<servname>.addr' value");
01077
01078 dbg_err_if(addr_create(&be->addr));
01079
01080 if(strcasecmp(be->proto, "https") == 0)
01081 dbg_err_if(addr_set_ipv4_port(be->addr, 443));
01082 else
01083 dbg_err_if(addr_set_ipv4_port(be->addr, 80));
01084
01085 dbg_err_if(addr_set_from_config(be->addr, subkey));
01086
01087 return 0;
01088 err:
01089 if(be->addr)
01090 {
01091 addr_free(be->addr);
01092 be->addr = NULL;
01093 }
01094 return ~0;
01095 }
01096
01097 static int server_log_hook(void *arg, int level, const char *str)
01098 {
01099 server_t *s = (server_t*)arg;
01100 u_log_hook_t old = NULL;
01101 void *old_arg = NULL;
01102
01103 dbg_err_if (s == NULL);
01104 dbg_err_if (str == NULL);
01105
01106
01107 if(s->klog == NULL && (ctx->backend == NULL || ctx->backend->klog == NULL))
01108 return 0;
01109
01110
01111
01112 u_log_set_hook(NULL, NULL, &old, &old_arg);
01113
01114
01115 if(s->klog->type == KLOG_TYPE_SYSLOG || ctx->pipc == 0)
01116 {
01117 if(s->klog)
01118 dbg_err_if(klog(s->klog, syslog_to_klog(level), "%s", str));
01119 } else {
01120
01121 dbg_err_if(server_ppc_cmd_log_add(s, level, str));
01122 }
01123
01124
01125 u_log_set_hook(old, old_arg, NULL, NULL);
01126
01127 return 0;
01128 err:
01129 if(old)
01130 u_log_set_hook(old, old_arg, NULL, NULL);
01131 return ~0;
01132 }
01133
01134 int server_get_logger(server_t *s, klog_t **pkl)
01135 {
01136 klog_t *kl = NULL;
01137
01138 dbg_err_if (s == NULL);
01139 dbg_err_if (pkl == NULL);
01140
01141 if(ctx->backend)
01142 kl = ctx->backend->klog;
01143
01144 if(kl == NULL)
01145 kl = s->klog;
01146
01147 *pkl = kl;
01148
01149 return 0;
01150 err:
01151 return ~0;
01152 }
01153
01154 static int server_get_klog_line(server_t *s, klog_t *kl, size_t i, char *line)
01155 {
01156 backend_t *be = ctx->backend;
01157
01158 dbg_err_if(kl->type != KLOG_TYPE_MEM);
01159 dbg_err_if(be == NULL);
01160
01161
01162 if(be->model != SERVER_MODEL_PREFORK)
01163 {
01164 dbg_err_if(klog_getln(kl, i, line));
01165 return 0;
01166 }
01167
01168
01169 nop_err_if(server_ppc_cmd_log_get(s, i, line));
01170
01171 return 0;
01172 err:
01173 return ~0;
01174 }
01175
01176 int server_foreach_memlog_line(server_t *s,
01177 int (*cb)(const char*, void*), void *arg)
01178 {
01179 klog_t *kl = NULL;
01180 size_t i;
01181 char line[KLOG_LN_SZ];
01182
01183
01184 if(server_get_logger(s, &kl) || kl == NULL || kl->type != KLOG_TYPE_MEM)
01185 {
01186 cb("logging is not configured or is not a in-memory log", arg);
01187 return ~0;
01188 }
01189
01190
01191 for(i = 1; server_get_klog_line(s, kl, i, line) == 0; ++i)
01192 cb(line, arg);
01193
01194 return 0;
01195 err:
01196 cb("klog_getln error", arg);
01197 return ~0;
01198 }
01199
01200
01201 int server_get_backend_by_id(server_t *s, int id, backend_t **pbe)
01202 {
01203 backend_t *be;
01204
01205 dbg_err_if (s == NULL);
01206 dbg_err_if (pbe == NULL);
01207
01208 LIST_FOREACH(be, &s->bes, np)
01209 {
01210 if(be->id == id)
01211 {
01212 *pbe = be;
01213 return 0;
01214 }
01215 }
01216
01217 err:
01218 return ~0;
01219 }
01220
01221 int server_create(u_config_t *config, int foreground, server_t **ps)
01222 {
01223 server_t *s = NULL;
01224 u_config_t *bekey = NULL, *log_c = NULL;
01225 backend_t *be = NULL;
01226 const char *list, *type;
01227 char *n = NULL, *name = NULL;
01228 int i, id, iv;
01229
01230 dbg_return_if (ps == NULL, ~0);
01231 dbg_return_if (config == NULL, ~0);
01232
01233 #ifdef OS_WIN
01234 WORD ver;
01235 WSADATA wsadata;
01236
01237 ver = MAKEWORD(1,1);
01238 dbg_err_if(WSAStartup(ver, &wsadata));
01239 #endif
01240
01241 s = u_zalloc(sizeof(server_t));
01242 dbg_err_if(s == NULL);
01243
01244 *ps = s;
01245
01246 s->config = config;
01247 s->model = SERVER_MODEL_FORK;
01248
01249 dbg_err_if(children_create(&s->children));
01250
01251
01252 FD_ZERO(&s->rdfds);
01253 FD_ZERO(&s->wrfds);
01254 FD_ZERO(&s->exfds);
01255
01256
01257 LIST_INIT(&s->bes);
01258
01259 dbg_err_if(ppc_create(&s->ppc));
01260
01261
01262 if(!u_config_get_subkey(config, "log", &log_c))
01263 {
01264 dbg_if(klog_open_from_config(log_c, &s->klog));
01265 s->klog_flush = 1;
01266 }
01267
01268
01269 dbg_err_if(ppc_register(s->ppc, PPC_CMD_NOP, server_ppc_cb_nop, s));
01270 dbg_err_if(ppc_register(s->ppc, PPC_CMD_LOG_ADD, server_ppc_cb_log_add, s));
01271 dbg_err_if(ppc_register(s->ppc, PPC_CMD_LOG_GET, server_ppc_cb_log_get, s));
01272 #ifdef OS_UNIX
01273 dbg_err_if(ppc_register(s->ppc, PPC_CMD_FORK_CHILD,
01274 server_ppc_cb_fork_child, s));
01275 #endif
01276 dbg_err_if(ppc_register(s->ppc, PPC_CMD_ACCESS_LOG,
01277 server_ppc_cb_access_log, s));
01278
01279
01280 dbg_err_if(u_log_set_hook(server_log_hook, s, NULL, NULL));
01281
01282
01283 list = u_config_get_subkey_value(config, "server_list");
01284 warn_err_ifm(list == NULL, "bad or missing 'server_list' config param");
01285
01286
01287 s->chroot = u_config_get_subkey_value(config, "chroot");
01288 dbg_err_if(u_config_get_subkey_value_i(config, "uid", -1, &s->uid));
01289 dbg_err_if(u_config_get_subkey_value_i(config, "gid", -1, &s->gid));
01290 dbg_err_if(u_config_get_subkey_value_b(config, "allow_root", 0,
01291 &s->allow_root));
01292 dbg_err_if(u_config_get_subkey_value_b(config, "blind_chroot", 0,
01293 &s->blind_chroot));
01294
01295 warn_err_ifm(!s->uid || !s->gid,
01296 "you must set uid and gid config parameters");
01297
01298 dbg_err_if(u_config_get_subkey_value_i(config, "max_child",
01299 SERVER_MAX_CHILD, &iv));
01300 s->max_child = iv;
01301
01302 name = n = u_zalloc(strlen(list) + 1);
01303 dbg_err_if(name == NULL);
01304
01305
01306 for(i = strlen(list), id = 0;
01307 i > 0 && sscanf(list, "%[^ \t]", name);
01308 i -= 1 + strlen(name), list += 1 + strlen(name), name[0] = 0)
01309 {
01310 dbg("configuring backend: %s", name);
01311
01312
01313 warn_err_if(s->nbackend == SERVER_MAX_BACKENDS);
01314
01315
01316 warn_err_ifm(u_config_get_subkey(config, name, &bekey),
01317 "missing [%s] backend configuration", name);
01318
01319 type = u_config_get_subkey_value(bekey, "type");
01320 warn_err_ifm(type == NULL, "missing or bad '<servname>.type' value");
01321
01322
01323 warn_err_ifm(backend_create(type, bekey, &be),
01324 "backend \"%s\" startup error", type);
01325
01326 be->server = s;
01327 be->config = bekey;
01328 be->id = id++;
01329 if(be->model == SERVER_MODEL_UNSET)
01330 be->model = s->model;
01331
01332 if(foreground)
01333 be->model = SERVER_MODEL_ITERATIVE;
01334
01335
01336 if(!u_config_get_subkey(bekey, "log", &log_c))
01337 dbg_if(klog_open_from_config(log_c, &be->klog));
01338
01339 #ifdef OS_WIN
01340 if(be->model != SERVER_MODEL_ITERATIVE)
01341 warn_err("child-based server model is not "
01342 "yet supported on Windows");
01343 #endif
01344
01345 LIST_INSERT_HEAD(&s->bes, be, np);
01346
01347 dbg_err_if(server_setup_backend(s, be));
01348 }
01349
01350 U_FREE(n);
01351
01352
01353 dbg_err_if(u_signal(SIGINT, server_sigint));
01354 dbg_err_if(u_signal(SIGTERM, server_sigterm));
01355 #ifdef OS_UNIX
01356 dbg_err_if(u_signal(SIGPIPE, SIG_IGN));
01357 dbg_err_if(u_signal(SIGCHLD, server_sigchld));
01358 #endif
01359
01360 return 0;
01361 err:
01362 warn("server init error (config error?)");
01363 U_FREE(n);
01364 if(s)
01365 {
01366 server_free(s);
01367 *ps = NULL;
01368 }
01369 return ~0;
01370 }
01371