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