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