static int httpd_wait_cgi_child(pid_t target, int opts) { pid_t child; do { child = waitpid(target, NULL, opts); } while (child == -1 && errno == EINTR); if (child == -1) { int err = errno; httpd_error("waitpid() : %s", strerror(err)); return -err; } return child; }
static void httpd_client_process(struct client_info *cinfo) { struct http_req hreq; int err; char httpd_inbuf[BUFF_SZ]; char httpd_outbuf[BUFF_SZ]; if (0 > (err = httpd_build_request(cinfo, &hreq, httpd_inbuf, sizeof(httpd_inbuf)))) { httpd_error("can't build request: %s", strerror(-err)); } httpd_debug("method=%s uri_target=%s uri_query=%s", hreq.method, hreq.uri.target, hreq.uri.query); if (httpd_try_respond_file(cinfo, &hreq, httpd_outbuf, sizeof(httpd_outbuf))) { /* file sent, nothing to do */ } else { httpd_header(cinfo, 404, ""); } }
static void httpd_client_process(struct client_info *cinfo) { struct http_req hreq; pid_t cgi_child; int err; if ((err = httpd_build_request(cinfo, &hreq, httpd_g_inbuf, sizeof(httpd_g_inbuf)))) { httpd_error("can't build request: %s", strerror(-err)); } httpd_debug("method=%s uri_target=%s uri_query=%s", hreq.method, hreq.uri.target, hreq.uri.query); if ((cgi_child = httpd_try_respond_script(cinfo, &hreq))) { httpd_on_cgi_child(cinfo, cgi_child); } else if (USE_REAL_CMD && (cgi_child = httpd_try_respond_cmd(cinfo, &hreq))) { httpd_on_cgi_child(cinfo, cgi_child); } else if (httpd_try_respond_file(cinfo, &hreq, httpd_g_outbuf, sizeof(httpd_g_outbuf))) { /* file sent, nothing to do */ } else { httpd_header(cinfo, 404, ""); } }
int main(int argc, char **argv) { int host; int i; const char *basedir; #if USE_IP_VER == 4 struct sockaddr_in inaddr; const size_t inaddrlen = sizeof(inaddr); const int family = AF_INET; inaddr.sin_family = AF_INET; inaddr.sin_port= htons(80); inaddr.sin_addr.s_addr = htonl(INADDR_ANY); #elif USE_IP_VER == 6 struct sockaddr_in6 inaddr; const size_t inaddrlen = sizeof(inaddr); const int family = AF_INET6; inaddr.sin6_family = AF_INET6; inaddr.sin6_port= htons(80); memcpy(&inaddr.sin6_addr, &in6addr_any, sizeof(inaddr.sin6_addr)); #else #error Unknown USE_IP_VER #endif basedir = argc > 1 ? argv[1] : "/"; host = socket(family, SOCK_STREAM, IPPROTO_TCP); if (host == -1) { httpd_error("socket() failure: %s", strerror(errno)); return -errno; } if (-1 == bind(host, (struct sockaddr *) &inaddr, inaddrlen)) { httpd_error("bind() failure: %s", strerror(errno)); close(host); return -errno; } if (-1 == listen(host, 3)) { httpd_error("listen() failure: %s", strerror(errno)); close(host); return -errno; } for (i = 0; i < MAX_CLIENTS_COUNT; ++i) { client_is_free[i] = 1; } while (1) { struct client_info *ci; pthread_t thread; int index = clients_get_free_index(); if (index == -1) { httpd_error("There are no more memory for new connection!"); continue; } ci = &clients[index]; ci->ci_index=index; ci->ci_addrlen = inaddrlen; ci->ci_sock = accept(host, &ci->ci_addr, &ci->ci_addrlen); if (ci->ci_sock == -1) { httpd_error("accept() failure: %s", strerror(errno)); continue; } assert(ci->ci_addrlen == inaddrlen); ci->ci_basedir = basedir; pthread_create(&thread, NULL, do_httpd_client_thread, ci); pthread_detach(thread); } close(host); return 0; }
int main(int argc, char **argv) { int host; const char *basedir; #if USE_IP_VER == 4 struct sockaddr_in inaddr; const size_t inaddrlen = sizeof(inaddr); const int family = AF_INET; inaddr.sin_family = AF_INET; inaddr.sin_port= htons(80); inaddr.sin_addr.s_addr = htonl(INADDR_ANY); #elif USE_IP_VER == 6 struct sockaddr_in6 inaddr; const size_t inaddrlen = sizeof(inaddr); const int family = AF_INET6; inaddr.sin6_family = AF_INET6; inaddr.sin6_port= htons(80); memcpy(&inaddr.sin6_addr, &in6addr_any, sizeof(inaddr.sin6_addr)); #else #error Unknown USE_IP_VER #endif basedir = argc > 1 ? argv[1] : "/"; host = socket(family, SOCK_STREAM, IPPROTO_TCP); if (host == -1) { httpd_error("socket() failure: %s", strerror(errno)); return -errno; } if (-1 == bind(host, (struct sockaddr *) &inaddr, inaddrlen)) { httpd_error("bind() failure: %s", strerror(errno)); close(host); return -errno; } if (-1 == listen(host, 3)) { httpd_error("listen() failure: %s", strerror(errno)); close(host); return -errno; } while (1) { struct client_info ci; ci.ci_addrlen = inaddrlen; ci.ci_sock = accept(host, &ci.ci_addr, &ci.ci_addrlen); if (ci.ci_sock == -1) { if (errno != EINTR) { httpd_error("accept() failure: %s", strerror(errno)); usleep(100000); } continue; } assert(ci.ci_addrlen == inaddrlen); ci.ci_basedir = basedir; if (USE_PARALLEL_CGI) { while (0 < httpd_wait_cgi_child(-1, WNOHANG)) { /* wait another one */ } } httpd_client_process(&ci); close(ci.ci_sock); } close(host); return 0; }