int main(int argc, char *argv[]) { fd_set rfds, wfds; struct connstruct *tp, *to; struct serverstruct *sp; int rnum, wnum, active; int i = 1; time_t currtime; char *httpAddress = NULL; int httpPort = CONFIG_HTTP_PORT; char *httpsAddress = NULL; int httpsPort = CONFIG_HTTP_HTTPS_PORT; uint32_t options = CONFIG_HTTP_DEFAULT_SSL_OPTIONS; char *portStr; char *private_key = NULL; char *cert = NULL; #ifdef WIN32 WORD wVersionRequested = MAKEWORD(2, 2); WSADATA wsaData; WSAStartup(wVersionRequested,&wsaData); #else signal(SIGPIPE, SIG_IGN); #if defined(CONFIG_HTTP_HAS_CGI) signal(SIGCHLD, reaper); #endif #ifdef CONFIG_HTTP_VERBOSE signal(SIGQUIT, die); #endif #endif #ifdef CONFIG_HTTP_VERBOSE signal(SIGTERM, die); signal(SIGINT, sigint_cleanup); #endif tdate_init(); /* get some command-line parameters */ while (argv[i] != NULL) { if (strcmp(argv[i], "-p") == 0 && argv[i+1] != NULL) { if ((portStr = strchr(argv[i+1], ':')) != NULL) { httpAddress = argv[i+1]; *portStr = 0; httpPort = atoi(portStr + 1); } else httpPort = atoi(argv[i+1]); i += 2; continue; } if (strcmp(argv[i], "-s") == 0 && argv[i+1] != NULL) { if ((portStr = strchr(argv[i+1], ':')) != NULL) { httpsAddress = argv[i+1]; *portStr = 0; httpsPort = atoi(portStr + 1); } else httpsPort = atoi(argv[i+1]); i += 2; continue; } if (strcmp(argv[i], "-w") == 0 && argv[i+1] != NULL) { webroot = argv[i+1]; i += 2; continue; } if (strcmp(argv[i], "-cert") == 0 && argv[i+1] != NULL) { cert = argv[i+1]; i += 2; continue; } if (strcmp(argv[i], "-key") == 0 && argv[i+1] != NULL) { private_key = argv[i+1]; i += 2; continue; } printf("%s:\n" " [-p [address:]httpport]\n" " [-s [address:]httpsport]\n" " [-key private_key]\n" " [-cert cert]\n" " [-w webroot]\n", argv[0]); exit(1); } for (i = 0; i < INITIAL_CONNECTION_SLOTS; i++) { tp = freeconns; freeconns = (struct connstruct *)calloc(1, sizeof(struct connstruct)); freeconns->next = tp; } if ((active = openlistener(httpAddress, httpPort)) == -1) { #ifdef CONFIG_HTTP_VERBOSE fprintf(stderr, "ERR: Couldn't bind to port %d\n", httpPort); #endif exit(1); } addtoservers(active); if ((active = openlistener(httpsAddress, httpsPort)) == -1) { #ifdef CONFIG_HTTP_VERBOSE fprintf(stderr, "ERR: Couldn't bind to port %d\n", httpsPort); #endif exit(1); } addtoservers(active); if (cert != NULL && private_key != NULL) options |= SSL_NO_DEFAULT_KEY; servers->ssl_ctx = ssl_ctx_new(options, CONFIG_HTTP_SESSION_CACHE_SIZE); servers->is_ssl = 1; if (cert != NULL && private_key != NULL) { printf("YEAH\n"); if (ssl_obj_load(servers->ssl_ctx, SSL_OBJ_RSA_KEY, private_key, NULL)) { #ifdef CONFIG_HTTP_VERBOSE fprintf(stderr, "ERR: Couldn't load private key %s\n", private_key); #endif exit(1); } if (ssl_obj_load(servers->ssl_ctx, SSL_OBJ_X509_CERT, cert, NULL)) { #ifdef CONFIG_HTTP_VERBOSE fprintf(stderr, "ERR: Couldn't load cert %s\n", cert); #endif exit(1); } } #if defined(CONFIG_HTTP_HAS_CGI) addcgiext(CONFIG_HTTP_CGI_EXTENSIONS); #endif #if defined(CONFIG_HTTP_VERBOSE) #if defined(CONFIG_HTTP_HAS_CGI) printf("addcgiext %s\n", CONFIG_HTTP_CGI_EXTENSIONS); #endif printf("%s: listening on ports %d (http) and %d (https)\n", server_version, httpPort, httpsPort); TTY_FLUSH(); #endif ax_chdir(); #ifdef CONFIG_HTTP_ENABLE_DIFFERENT_USER { struct passwd *pd = getpwnam(CONFIG_HTTP_USER); if (pd != NULL) { int res = setuid(pd->pw_uid); res |= setgid(pd->pw_gid); #if defined(CONFIG_HTTP_VERBOSE) if (res == 0) { printf("change to '%s' successful\n", CONFIG_HTTP_USER); TTY_FLUSH(); } #endif } } #endif #ifndef WIN32 #ifdef CONFIG_HTTP_IS_DAEMON if (fork() > 0) /* parent will die */ exit(0); setsid(); #endif #endif /* main loop */ while (1) { struct timeval tv = { 10, 0 }; FD_ZERO(&rfds); FD_ZERO(&wfds); rnum = wnum = -1; sp = servers; while (sp != NULL) /* read each server port */ { FD_SET(sp->sd, &rfds); if (sp->sd > rnum) rnum = sp->sd; sp = sp->next; } /* Add the established sockets */ tp = usedconns; currtime = time(NULL); while (tp != NULL) { if (currtime > tp->timeout) /* timed out? Kill it. */ { to = tp; tp = tp->next; removeconnection(to); continue; } if (tp->state == STATE_WANT_TO_READ_HEAD) { FD_SET(tp->networkdesc, &rfds); if (tp->networkdesc > rnum) rnum = tp->networkdesc; } if (tp->state == STATE_WANT_TO_SEND_HEAD) { FD_SET(tp->networkdesc, &wfds); if (tp->networkdesc > wnum) wnum = tp->networkdesc; } if (tp->state == STATE_WANT_TO_READ_FILE) { FD_SET(tp->filedesc, &rfds); if (tp->filedesc > rnum) rnum = tp->filedesc; } if (tp->state == STATE_WANT_TO_SEND_FILE) { FD_SET(tp->networkdesc, &wfds); if (tp->networkdesc > wnum) wnum = tp->networkdesc; } #if defined(CONFIG_HTTP_DIRECTORIES) if (tp->state == STATE_DOING_DIR) { FD_SET(tp->networkdesc, &wfds); if (tp->networkdesc > wnum) wnum = tp->networkdesc; } #endif tp = tp->next; } active = select(wnum > rnum ? wnum+1 : rnum+1, rnum != -1 ? &rfds : NULL, wnum != -1 ? &wfds : NULL, NULL, usedconns ? &tv : NULL); /* timeout? */ if (active == 0) continue; /* New connection? */ sp = servers; while (active > 0 && sp != NULL) { if (FD_ISSET(sp->sd, &rfds)) { handlenewconnection(sp->sd, sp->is_ssl); active--; } sp = sp->next; } /* Handle the established sockets */ tp = usedconns; while (active > 0 && tp != NULL) { to = tp; tp = tp->next; if (to->state == STATE_WANT_TO_READ_HEAD && FD_ISSET(to->networkdesc, &rfds)) { active--; #if defined(CONFIG_HTTP_HAS_CGI) if (to->post_state) read_post_data(to); else #endif procreadhead(to); } if (to->state == STATE_WANT_TO_SEND_HEAD && FD_ISSET(to->networkdesc, &wfds)) { active--; procsendhead(to); } if (to->state == STATE_WANT_TO_READ_FILE && FD_ISSET(to->filedesc, &rfds)) { active--; procreadfile(to); } if (to->state == STATE_WANT_TO_SEND_FILE && FD_ISSET(to->networkdesc, &wfds)) { active--; procsendfile(to); } #if defined(CONFIG_HTTP_DIRECTORIES) if (to->state == STATE_DOING_DIR && FD_ISSET(to->networkdesc, &wfds)) { active--; procdodir(to); } #endif } } return 0; }
void listener(char *server_port, char *interface_name) { socklen_t len; int listening_fd, errcode; struct sockaddr server; struct sockaddr_in *iptr; char text_buf[TEXT_SIZE]; char local_node[HOSTMAX]; char *host_name; struct thread_params *params; pthread_t agent_id; no_sigpipe(); /* establish a server "listening post" */ listening_fd = openlistener(server_port, interface_name, &server); /* get the hostname of server*/ if (interface_name == NULL) { if (gethostname(local_node, HOSTMAX) < 0) { perror("Server gethostname"); exit(1); } host_name = local_node; } else { host_name = interface_name; } if (listening_fd < 0) exit(EXIT_FAILURE); /* we are now successfully established as a server */ /* infinite loop -- server serves forever, must be killed by ^C */ for (;;) { iptr = (struct sockaddr_in *) &server; if (inet_ntop(iptr->sin_family, &iptr->sin_addr, text_buf, TEXT_SIZE) == NULL) { perror("inet_ntop server"); break; } fprintf(stderr, "%s listening at IP address %s port %d\n", host_name, text_buf, ntohs(iptr->sin_port)); /* accept a client connection (block until one arrives) */ params = malloc(sizeof(struct thread_params)); if (params == NULL) { perror("listener malloc"); break; } len = sizeof(params->client); if ((params->client_fd = accept(listening_fd, ¶ms->client, &len)) < 0) { perror("rplcsd accept"); break; } iptr = (struct sockaddr_in *) (¶ms->client); if (inet_ntop(iptr->sin_family, &iptr->sin_addr, text_buf, TEXT_SIZE) == NULL) { perror("inet_ntop client"); free(params); continue; } fprintf(stderr, "connected to client at IP address %s " "port %d\n", text_buf, ntohs(iptr->sin_port)); /* we are now successfully connected to a remote client */ errcode = pthread_create(&agent_id, NULL, server_agent, params); if (errcode != 0) { fprintf(stderr, "pthread_create server agent: %s\n", strerror(errcode)); break; } } /* infinite loop */ if (close(listening_fd) < 0) { perror("rplcsd server close"); } pthread_exit(NULL); } /* listener */