#include #include #include #include #include #include #include "misc.h" #include "socket.h" #include "webserver.h" typedef std::vector string_array; int def_timeout = 5; struct responseRoute { std::string method; std::string path; std::string content_type; response_callback rc; }; std::vector responses; //for use of multi-thread typedef std::lock_guard guarded_mutex; int working_thread = 0, max_send_failure = 10; bool SERVER_EXIT_FLAG = false; std::mutex working_mutex, server_exit_flag_mutex; static inline void working_acc() { guarded_mutex guard(working_mutex); working_thread++; } static inline void working_dec() { guarded_mutex guard(working_mutex); working_thread--; } static inline int safe_read_working() { int retVal; guarded_mutex guard(working_mutex); retVal = working_thread; return retVal; } static inline bool safe_read_server_exit_flag() { bool retVal; guarded_mutex guard(server_exit_flag_mutex); retVal = SERVER_EXIT_FLAG; return retVal; } static inline void safe_set_server_exit_flag() { guarded_mutex guard(server_exit_flag_mutex); SERVER_EXIT_FLAG = true; } int sendall(SOCKET sock, std::string data) { unsigned int total = 0, bytesleft = data.size(); int sent = 0; const char* datastr = data.data(); while(total < bytesleft) { sent = send(sock, datastr + total, bytesleft, 0); if(sent < 0) { std::cerr< 2) { wrong_req(client_sock); goto end; } else if(vArray.size() > 1) { uri = vArray[0]; args = vArray[1]; } else uri = arguments; if(strcmp(command, "POST") == 0) { if(request.find("\r\n\r\n") != request.npos) postdata = request.substr(request.find("\r\n\r\n") + 4); } else if(strcmp(command, "OPTIONS") == 0) { serve_options(client_sock); goto end; } for(std::vector::iterator iter = responses.begin(); iter != responses.end(); ++iter) { if(iter->method.compare(command) == 0 && iter->path == uri) { response_callback &rc = iter->rc; serve_content(client_sock, iter->content_type, rc(args, postdata)); goto end; } } file_not_found(uri, client_sock); end: std::cerr<<"worker stop"<listen_address, request; int port = args->port, max_conn = args->max_conn, max_workers = args->max_workers, numbytes, worker_index = 0; socklen_t sock_size = sizeof(struct sockaddr_in); char buf[BUFSIZ]; struct sockaddr_in user_socket, server_addr; SOCKET acc_socket; int server_socket, fail_counter = 0; server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); std::thread workers[max_workers]; if (server_socket == -1) { //log socket error std::cerr<<"socket build error!"< max_send_failure) break; continue; } else { break; } } request = ""; while(true) //receive the complete request { numbytes = recv(acc_socket, buf, BUFSIZ - 1, 0); if(numbytes > 0) //received request.append(buf); if(numbytes < 0) { if(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) { continue; } else { break; } } if(numbytes == 0) break; } //handle_req(buf, acc_socket); while(safe_read_working() >= max_workers) { sleep(10); if(safe_read_server_exit_flag()) break; } while(workers[worker_index].get_id() != std::thread::id()) { worker_index++; } workers[worker_index] = std::thread(handle_req, request, acc_socket); workers[worker_index].detach(); worker_index++; if(worker_index > max_workers) worker_index = 0; } return 0; }