#include "worker.hfa" #include #include #include #include #include #include "options.hfa" #include "protocol.hfa" #include "filecache.hfa" //============================================================================================= // Worker Thread //============================================================================================= void ?{}( Worker & this ) { ((thread&)this){ "Server Worker Thread", *options.clopts.instance }; this.pipe[0] = -1; this.pipe[1] = -1; this.done = false; } extern "C" { extern int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags); } void main( Worker & this ) { park(); /* paranoid */ assert( this.pipe[0] != -1 ); /* paranoid */ assert( this.pipe[1] != -1 ); CONNECTION: for() { if( options.log ) printf("=== Accepting connection ===\n"); int fd = cfa_accept4( this.[sockfd, addr, addrlen, flags], 0, -1`s, &this.cancel, 0p ); // int fd = accept4( this.[sockfd, addr, addrlen, flags] ); if(fd < 0) { if( errno == ECONNABORTED ) break; if( errno == EINVAL && this.done ) break; abort( "accept error: (%d) %s\n", (int)errno, strerror(errno) ); } if( options.log ) printf("=== New connection %d, waiting for requests ===\n", fd); REQUEST: for() { bool closed; HttpCode code; const char * file; size_t name_size; // Read the http request size_t len = options.socket.buflen; char buffer[len]; if( options.log ) printf("=== Reading request ===\n"); [code, closed, file, name_size] = http_read(fd, buffer, len, &this.cancel); // if we are done, break out of the loop if( closed ) { if( options.log ) printf("=== Connection closed ===\n"); close(fd); continue CONNECTION; } // If this wasn't a request retrun 400 if( code != OK200 ) { printf("=== Invalid Request : %d ===\n", code_val(code)); answer_error(fd, code); continue REQUEST; } if(0 == strncmp(file, "plaintext", min(name_size, sizeof("plaintext") ))) { if( options.log ) printf("=== Request for /plaintext ===\n"); char text[] = "Hello, World!\n"; // Send the header answer_plain(fd, text, sizeof(text)); if( options.log ) printf("=== Answer sent ===\n"); continue REQUEST; } if(0 == strncmp(file, "ping", min(name_size, sizeof("ping") ))) { if( options.log ) printf("=== Request for /ping ===\n"); // Send the header answer_empty(fd); if( options.log ) printf("=== Answer sent ===\n"); continue REQUEST; } if( options.log ) printf("=== Request for file %.*s ===\n", (int)name_size, file); // Get the fd from the file cache int ans_fd; size_t count; [ans_fd, count] = get_file( file, name_size ); // If we can't find the file, return 404 if( ans_fd < 0 ) { printf("=== File Not Found ===\n"); answer_error(fd, E404); continue REQUEST; } // Send the header answer_header(fd, count); // Send the desired file sendfile( this.pipe, fd, ans_fd, count); if( options.log ) printf("=== Answer sent ===\n"); } } }