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