+ /* master file descriptor list */
+ fd_set used_fds, read_fds;
+
+ /* working structs */
+ struct http_request *req;
+ struct path_info *pin;
+ struct client *cl;
+
+ /* maximum file descriptor number */
+ int new_fd, cur_fd = 0;
+
+ /* clear the master and temp sets */
+ FD_ZERO(&used_fds);
+ FD_ZERO(&read_fds);
+
+ /* backup server descriptor set */
+ used_fds = serv_fds;
+
+ /* loop */
+ while(run)
+ {
+ /* create a working copy of the used fd set */
+ read_fds = used_fds;
+
+ /* sleep until socket activity */
+ if( select(max_fd + 1, &read_fds, NULL, NULL, NULL) == -1 )
+ {
+ perror("select()");
+ exit(1);
+ }
+
+ /* run through the existing connections looking for data to be read */
+ for( cur_fd = 0; cur_fd <= max_fd; cur_fd++ )
+ {
+ /* is a socket managed by us */
+ if( FD_ISSET(cur_fd, &read_fds) )
+ {
+ /* is one of our listen sockets */
+ if( FD_ISSET(cur_fd, &serv_fds) )
+ {
+ /* handle new connections */
+ if( (new_fd = accept(cur_fd, NULL, 0)) != -1 )
+ {
+ /* add to global client list */
+ if( (cl = uh_client_add(new_fd, uh_listener_lookup(cur_fd))) != NULL )
+ {
+#ifdef HAVE_TLS
+ /* setup client tls context */
+ if( conf->tls )
+ conf->tls_accept(cl);
+#endif
+
+ /* add client socket to global fdset */
+ FD_SET(new_fd, &used_fds);
+ fd_cloexec(new_fd);
+ max_fd = max(max_fd, new_fd);
+ }
+
+ /* insufficient resources */
+ else
+ {
+ fprintf(stderr,
+ "uh_client_add(): Cannot allocate memory\n");
+
+ close(new_fd);
+ }
+ }
+ }
+
+ /* is a client socket */
+ else
+ {
+ if( ! (cl = uh_client_lookup(cur_fd)) )
+ {
+ /* this should not happen! */
+ fprintf(stderr,
+ "uh_client_lookup(): No entry for fd %i!\n",
+ cur_fd);
+
+ goto cleanup;
+ }
+
+ /* parse message header */
+ if( (req = uh_http_header_recv(cl)) != NULL )
+ {
+ /* RFC1918 filtering required? */
+ if( conf->rfc1918_filter &&
+ sa_rfc1918(&cl->peeraddr) &&
+ !sa_rfc1918(&cl->servaddr) )
+ {
+ uh_http_sendhf(cl, 403, "Forbidden",
+ "Rejected request from RFC1918 IP "
+ "to public server address");
+ }
+ else
+#ifdef HAVE_LUA
+ /* Lua request? */
+ if( conf->lua_state &&
+ uh_path_match(conf->lua_prefix, req->url) )
+ {
+ conf->lua_request(cl, req, conf->lua_state);
+ }
+ else
+#endif
+ /* dispatch request */
+ if( (pin = uh_path_lookup(cl, req->url)) != NULL )
+ {
+ /* auth ok? */
+ if( !pin->redirected && uh_auth_check(cl, req, pin) )
+ uh_dispatch_request(cl, req, pin);
+ }
+
+ /* 404 */
+ else
+ {
+ /* Try to invoke an error handler */
+ pin = uh_path_lookup(cl, conf->error_handler);
+
+ if( pin && uh_auth_check(cl, req, pin) )
+ {
+ req->redirect_status = 404;
+ uh_dispatch_request(cl, req, pin);
+ }
+ else
+ {
+ uh_http_sendhf(cl, 404, "Not Found",
+ "No such file or directory");
+ }
+ }
+ }
+
+#ifdef HAVE_TLS
+ /* free client tls context */
+ if( conf->tls )
+ conf->tls_close(cl);
+#endif
+
+ cleanup:
+
+ /* close client socket */
+ close(cur_fd);
+ FD_CLR(cur_fd, &used_fds);
+
+ /* remove from global client list */
+ uh_client_remove(cur_fd);
+ }
+ }
+ }
+ }
+