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