extern "C" void delete_file (char *pathname, struct client client) { struct decafs_file_stat file_info; uint32_t num_chunks = 0, request_id = get_new_request_id(); // If the file doesn't exist if ((decafs_file_sstat (pathname, &file_info, client)) < 0) { // TODO halli check if this change is correct // old call //if (send_delete_result (client, 0, FILE_NOT_FOUND) < 0) { if (send_remove_result (client, FILE_NOT_FOUND) < 0) { printf ("\tDelete result could not reach client.\n"); } return; } if (get_exclusive_lock (client, file_info.file_id) < 0) { // TODO halli check if this change is correct // old call //if (send_delete_result (client, 0, FILE_IN_USE) < 0) { if (send_remove_result (client, FILE_IN_USE) < 0) { printf ("\tDelete result could not reach client.\n"); } return; } // Save the request id. active_delete_requests[request_id] = request_info (client, file_info.file_id); printf ("(request: %d) processing delete file %s\n", request_id, pathname); num_chunks = process_delete_file (request_id, file_info.file_id); assert (delete_request_exists (request_id)); active_delete_requests[request_id].chunks_expected = num_chunks; check_delete_complete(request_id); }
int proxenet_start() { sock_t control_socket, listening_socket; struct sigaction saction; control_socket = listening_socket = -1; /* create control socket */ control_socket = create_control_socket(); if (control_socket < 0) { xlog(LOG_CRITICAL, "Cannot create control socket: %s\n", strerror(errno)); return -1; } #ifdef DEBUG xlog(LOG_INFO, "Control socket: %d\n", control_socket); #endif /* create listening socket */ listening_socket = create_bind_socket(cfg->iface, cfg->port); if (listening_socket < 0) { xlog(LOG_CRITICAL, "Cannot create bind socket: %s\n", strerror(errno)); return -1; } #ifdef DEBUG xlog(LOG_INFO, "Bind socket: %d\n", listening_socket); #endif /* init everything */ initialize_sigmask(&saction); plugins_list = NULL; proxy_state = INACTIVE; active_threads_bitmask = 0; /* set up plugins */ if( proxenet_initialize_plugins_list() < 0 ) return -1; proxenet_initialize_plugins(); // call *MUST* succeed or abort() /* setting request counter */ request_id = 0; get_new_request_id(); /* prepare threads and start looping */ xloop(listening_socket, control_socket); /* clean context */ proxenet_remove_all_plugins(); close_socket(listening_socket); close_socket(control_socket); unlink(CONTROL_SOCK_PATH); return 0; }
extern "C" void node_up_handler_func (uint32_t node_number) { printf ("Handling node coming online...\n"); auto itW = writeRequests.begin(); while (itW!=writeRequests.end()) { if(itW->node_id == node_number) { uint32_t req_id = get_new_request_id(); replace_request_lookups.insert(std::pair<uint32_t, uint32_t>(req_id, req_id)); process_write_chunk (req_id, itW->fd, itW->file_id, itW->node_id, itW->stripe_id, itW->chunk_num, itW->offset, itW->buf, itW->count); printf("Write Request:\n file_id:%d \t node_id:%d\t stripe_id:%d\t chunk_num:%d\n", itW->file_id, itW->node_id, itW->stripe_id, itW->chunk_num); writeRequests.erase(itW); break; } itW++; } printf("finished restarting teh node :)\n"); }
extern "C" void write_file (int fd, const void *buf, size_t count, struct client client) { struct file_instance inst; struct decafs_file_stat stat; uint32_t stripe_id, num_chunks = 0, num_replica_chunks = 0; uint32_t chunks_written, replica_chunks_written; int file_offset, stripe_offset, bytes_written = 0, write_size = 0; uint32_t request_id = get_new_request_id(); uint32_t replica_request_id = get_new_request_id(); struct write_request request = {request_id, replica_request_id}; assert (fd > 0); inst = get_file_info((uint32_t)fd); printf ("\n(BARISTA) Write request (%d bytes) from file %d\n", (int)count, (int)inst.file_id); // If the client does not have permission to write, return an error if (has_exclusive_lock (client, inst.file_id) <= 0) { if (send_write_result (client, 0, FILE_NOT_OPEN_FOR_WRITE) < 0) { printf ("\tWrite result could not reach client.\n"); } return; } if (decafs_file_stat (inst.file_id, &stat, client) < 0) { if (send_write_result (client, 0, UNABLE_TO_STAT_FILE) < 0) { printf ("\tWrite result could not reach client.\n"); } return; } if ((file_offset = get_file_cursor (fd)) < 0) { if (send_write_result (client, 0, FILE_NOT_OPEN_FOR_WRITE) < 0) { printf ("\tWrite result could not reach client.\n"); } return; } // If we are requesting 0 bytes, return 0 bytes written if (count == 0) { if (send_write_result (client, 0, 0) < 0) { printf ("\tWrite result could not reach client.\n"); } return; } // Save the request id write_request_lookups[request_id] = request; write_request_lookups[replica_request_id] = request; active_write_requests[request] = write_request_info (client, inst.file_id, fd); // TODO: make some assertion about max write size here get_first_stripe (&stripe_id, &stripe_offset, stat.stripe_size, file_offset); while (bytes_written < (int)count) { if (count - bytes_written > stat.stripe_size - stripe_offset) { write_size = stat.stripe_size - stripe_offset; } else { write_size = count - bytes_written; } printf ("\t(request: (%d,%d)) sending stripe %d for processing (%d bytes)\n", request_id, replica_request_id, stripe_id, write_size); // TODO: add pathname here, get from persistent meta chunks_written = 0; replica_chunks_written = 0; process_write_stripe (request_id, replica_request_id, &chunks_written, &replica_chunks_written, inst.file_id, (char *)"", stripe_id, stat.stripe_size, stat.chunk_size, (uint8_t *)buf + bytes_written, stripe_offset, write_size); num_chunks += chunks_written; num_replica_chunks += replica_chunks_written; // TODO (?): Move the file size update and cursor to check_write_complete() update_file_size (inst.file_id, write_size, client); set_file_cursor (fd, get_file_cursor (fd) + write_size, client); stripe_offset = 0; bytes_written += write_size; ++stripe_id; } assert (write_request_exists (request_id)); active_write_requests[request].info.chunks_expected = num_chunks; active_write_requests[request].replica_info.chunks_expected = num_replica_chunks; check_write_complete(request_id); }
extern "C" void read_file (int fd, size_t count, struct client client) { struct file_instance inst; struct decafs_file_stat stat; uint32_t stripe_id, num_chunks = 0; int file_offset, stripe_offset, bytes_read = 0, read_size = 0; uint8_t *buf; uint32_t request_id = get_new_request_id(); assert (fd > 0); // Allocate space for the read request buf = (uint8_t *)malloc (count); inst = get_file_info((uint32_t)fd); printf ("\n(BARISTA) Read request (%d bytes)\n", (int)count); // If the client does not have permission to read, return an error if (has_exclusive_lock (client, inst.file_id) <= 0) { if (has_shared_lock (client, inst.file_id) <= 0) { if (send_read_result (client, 0, FILE_NOT_OPEN_FOR_READ, NULL) < 0) { printf ("\tRead result could not reach client.\n"); } return; } } if (decafs_file_stat (inst.file_id, &stat, client) < 0) { if (send_read_result (client, 0, UNABLE_TO_STAT_FILE, NULL) < 0) { printf ("\tRead result could not reach client.\n"); } return; } if ((file_offset = get_file_cursor (fd)) < 0) { if (send_read_result (client, 0, FILE_NOT_OPEN_FOR_READ, NULL) < 0) { printf ("\tRead result could not reach client.\n"); } return; } // TODO: make some assertion about max read size here // If we are trying to read past EOF or requesting 0 bytes, // return 0 bytes read if (file_offset >= (int)stat.size || count == 0) { if (send_read_result (client, fd, 0, NULL) < 0) { printf ("\tRead result could not reach client.\n"); } return; } // Save the request id. active_read_requests[request_id] = read_request_info (client, inst.file_id, fd, buf); get_first_stripe (&stripe_id, &stripe_offset, stat.stripe_size, file_offset); while (bytes_read < (int)count) { printf ("file cursor: %d\n", get_file_cursor(fd)); if (count - bytes_read > stat.stripe_size - stripe_offset) { read_size = stat.stripe_size - stripe_offset; } else { read_size = count - bytes_read; } printf ("\t(request: %d) sending stripe (%d) information for processing (%d bytes)\n", request_id, stripe_id, read_size); // TODO: add pathname here, get from persistent meta num_chunks += process_read_stripe (request_id, inst.file_id, (char *)"", stripe_id, stat.stripe_size, stat.chunk_size, (uint8_t *)buf + bytes_read, stripe_offset, read_size); set_file_cursor (fd, get_file_cursor (fd) + read_size, client); stripe_offset = 0; bytes_read += read_size; ++stripe_id; } assert (read_request_exists (request_id)); active_read_requests[request_id].info.chunks_expected = num_chunks; check_read_complete(request_id); }
/** * This function is called by all threads to treat to process the request and response. * It will also apply the plugins. */ void proxenet_process_http_request(sock_t server_socket) { sock_t client_socket; request_t req; int retcode; fd_set rfds; struct timespec ts; ssl_context_t ssl_context; bool is_ssl; sigset_t emptyset; size_t n; client_socket = retcode = n = -1; proxenet_xzero(&req, sizeof(request_t)); proxenet_xzero(&ssl_context, sizeof(ssl_context_t)); /* wait for any event on sockets */ for(;;) { if (server_socket < 0) { xlog(LOG_ERROR, "%s\n", "Sock browser->proxy died unexpectedly"); break; } ts.tv_sec = HTTP_TIMEOUT_SOCK; ts.tv_nsec = 0; FD_ZERO(&rfds); FD_SET(server_socket, &rfds); if (client_socket > 0) FD_SET(client_socket, &rfds); sigemptyset(&emptyset); retcode = pselect(FD_SETSIZE, &rfds, NULL, NULL, &ts, &emptyset); if (retcode < 0) { if (errno == EINTR) { continue; } else { xlog(LOG_CRITICAL, "[thread] pselect returned %d: %s\n", retcode, strerror(errno)); break; } } if (retcode == 0) { break; } is_ssl = ssl_context.use_ssl; /* is there data from web browser to proxy ? */ if( FD_ISSET(server_socket, &rfds ) ) { n = - 1; if(is_ssl) { n = proxenet_read_all(server_socket, &req.data, &(ssl_context.server.context)); } else { n = proxenet_read_all(server_socket, &req.data, NULL); } #ifdef DEBUG xlog(LOG_DEBUG, "[%d] Got %dB from client (%s)\n", req.id, n, (is_ssl)?"SSL":"PLAIN"); #endif if (n <= 0) break; req.size = n; /* is connection to server not established ? -> new request */ if (client_socket < 0) { retcode = create_http_socket(&req, &server_socket, &client_socket, &ssl_context); if (retcode < 0) { xlog(LOG_ERROR, "[%d] Failed to create %s->server socket\n", req.id, PROGNAME); proxenet_xfree(req.data); client_socket = -1; break; } if (ssl_context.use_ssl) { if (ssl_context.server.is_valid && ssl_context.client.is_valid) { #ifdef DEBUG xlog(LOG_DEBUG, "[%d] SSL interception established\n", req.id); #endif proxenet_xfree(req.data); continue; } xlog(LOG_ERROR, "[%d] Failed to establish interception\n", req.id); proxenet_xfree(req.data); client_socket = -1; break; } } req.type = REQUEST; req.id = get_new_request_id(); /* check if request is valid */ if (!cfg->proxy.host) { if (!is_ssl) { if (!is_valid_http_request(&req.data, &req.size)) { proxenet_xfree(req.data); client_socket = -1; break; } } else { set_https_infos(&req); } } if (cfg->verbose) { xlog(LOG_INFO, "New request %d to '%s:%d'\n", req.id, req.http_infos.hostname, req.http_infos.port); if (cfg->verbose > 1) xlog(LOG_INFO, "%s %s://%s:%d%s %s\n", req.http_infos.method, req.http_infos.proto, req.http_infos.hostname, req.http_infos.port, req.http_infos.uri, req.http_infos.version); } #ifdef DEBUG xlog(LOG_DEBUG, "[%d] Sending buffer %d bytes (%s) - pre-plugins\n", req.id, req.size, (req.http_infos.is_ssl)?"SSL":"PLAIN"); #endif /* hook request with all plugins in plugins_list */ if ( proxenet_apply_plugins(&req) < 0) { /* extremist action: any error on any plugin discard the whole request */ req.id = 0; proxenet_xfree( req.data ); continue; } #ifdef DEBUG xlog(LOG_DEBUG, "[%d] Sending buffer %d bytes (%s) - post-plugins\n", req.id, req.size, (req.http_infos.is_ssl)?"SSL":"PLAIN"); #endif /* send modified data */ if (is_ssl) { retcode = proxenet_ssl_write(client_socket, req.data, req.size, &(ssl_context.client.context)); } else { retcode = proxenet_write(client_socket, req.data, req.size); } proxenet_xfree(req.data); if (retcode < 0) { xlog(LOG_ERROR, "[%d] %s\n", req.id, "Failed to write to server"); if (req.id) req.id = 0; break; } } /* end FD_ISSET(data_from_browser) */ /* is there data from remote server to proxy ? */ if( client_socket > 0 && FD_ISSET(client_socket, &rfds ) ) { n = -1; if (is_ssl) n = proxenet_read_all(client_socket, &req.data, &ssl_context.client.context); else n = proxenet_read_all(client_socket, &req.data, NULL); #ifdef DEBUG xlog(LOG_DEBUG, "[%d] Got %dB from server\n", req.id, n); #endif if (n <= 0) break; /* update request data structure */ req.type = RESPONSE; req.size = n; /* execute response hooks */ if ( proxenet_apply_plugins(&req) < 0) { /* extremist action: any error on any plugin discard the whole request */ req.id = 0; proxenet_xfree(req.data); continue; } /* send modified data to client */ if (is_ssl) retcode = proxenet_ssl_write(server_socket, req.data, req.size, &ssl_context.server.context); else retcode = proxenet_write(server_socket, req.data, req.size); if (retcode < 0) { xlog(LOG_ERROR, "[%d] %s\n", req.id, "proxy->client: write failed"); } proxenet_xfree(req.data); } /* end FD_ISSET(data_from_server) */ } /* end for(;;) { select() } */ if (req.id) { #ifdef DEBUG xlog(LOG_DEBUG, "Free-ing request %d\n", req.id); #endif proxenet_xfree(req.http_infos.method); proxenet_xfree(req.http_infos.hostname); proxenet_xfree(req.http_infos.uri); proxenet_xfree(req.http_infos.version); } /* close client socket */ if (client_socket > 0) { #ifdef DEBUG xlog(LOG_DEBUG, "Closing proxy->server socket #%d\n", client_socket); #endif if (ssl_context.client.is_valid) { proxenet_ssl_finish(&(ssl_context.client), false); close_socket_ssl(client_socket, &ssl_context.client.context); } else { close_socket(client_socket); } } /* close local socket */ if (server_socket > 0) { #ifdef DEBUG xlog(LOG_DEBUG, "Closing browser->proxy socket #%d\n", server_socket); #endif if (ssl_context.server.is_valid) { proxenet_ssl_finish(&(ssl_context.server), true); close_socket_ssl(server_socket, &ssl_context.server.context); } else { close_socket(server_socket); } } /* and that's all folks */ return; }
/** * This function is called by all threads to treat to process the request and response. * It will also apply the plugins. * * @param server_socket is the socket received by the main thread from the web browser (acting like server * to web browser) */ void proxenet_process_http_request(sock_t server_socket) { sock_t client_socket; request_t req; int retcode, n; fd_set rfds; struct timespec ts; ssl_context_t ssl_context; bool is_ssl; sigset_t emptyset; bool is_new_http_connection = false; client_socket = retcode = n = -1; proxenet_xzero(&req, sizeof(request_t)); proxenet_xzero(&ssl_context, sizeof(ssl_context_t)); /* wait for any event on sockets */ while(proxy_state == ACTIVE) { if (server_socket < 0) { xlog(LOG_ERROR, "sock browser->%s (#%d) died unexpectedly\n", PROGNAME, server_socket); break; } ts.tv_sec = HTTP_TIMEOUT_SOCK; ts.tv_nsec = 0; FD_ZERO(&rfds); FD_SET(server_socket, &rfds); if (client_socket > 0) FD_SET(client_socket, &rfds); sigemptyset(&emptyset); retcode = pselect(FD_SETSIZE, &rfds, NULL, NULL, &ts, &emptyset); if (retcode < 0) { if (errno == EINTR) { continue; } else { xlog(LOG_CRITICAL, "[thread] pselect returned %d: %s\n", retcode, strerror(errno)); break; } } if (retcode == 0) { continue; } is_ssl = ssl_context.use_ssl; /* is there data from web browser to proxy ? */ if( FD_ISSET(server_socket, &rfds ) ) { if(is_ssl && req.do_intercept) { n = proxenet_read_all(server_socket, &req.data, &(ssl_context.server.context)); } else { n = proxenet_read_all(server_socket, &req.data, NULL); } #ifdef DEBUG xlog(LOG_DEBUG, "Got %dB from client (%s srv_sock=#%d intercept_flag=%s)\n", n, is_ssl?"SSL":"PLAIN", server_socket, req.do_intercept?"true":"false"); #endif if (n < 0) { xlog(LOG_ERROR, "%s\n", "read() failed, end thread"); break; } if (n == 0){ #ifdef DEBUG xlog(LOG_DEBUG, "%s\n", "Socket EOF from client"); #endif break; } /* from here, n can only be positive */ req.size = (size_t) n; bytes_sent += n; if (req.id > 0 && !req.do_intercept){ #ifdef DEBUG xlog(LOG_DEBUG, "Intercept disabled for browser->'%s'\n", req.http_infos.hostname); #endif goto send_to_server; } /* proxy keep-alive */ if (req.id > 0){ request_t* old_req = (request_t*)proxenet_xmalloc(sizeof(request_t)); memcpy(old_req, &req, sizeof(request_t)); char* host = proxenet_xstrdup2( req.http_infos.hostname ); free_http_infos(&(req.http_infos)); if (update_http_infos(&req) < 0){ xlog(LOG_ERROR, "Failed to update HTTP information for request %d\n", req.id); proxenet_xfree( host ); proxenet_xfree( old_req ); req.id = 0; break; } if (strcmp( host, req.http_infos.hostname )){ /* reset the client connection parameters */ if (cfg->verbose) xlog(LOG_INFO, "Reusing sock=%d (old request=%d, old sock=%d) %s/%s\n", server_socket, req.id, client_socket, host, req.http_infos.hostname ); proxenet_close_socket(client_socket, &(ssl_context.client)); free_http_infos(&(req.http_infos)); client_socket = -1; } proxenet_xclean( old_req, sizeof(request_t) ); proxenet_xfree( host ); } req.type = REQUEST; req.id = get_new_request_id(); /* is connection to server not established ? -> new request */ if ( client_socket < 0) { retcode = create_http_socket(&req, &server_socket, &client_socket, &ssl_context); if (retcode < 0) { xlog(LOG_ERROR, "Failed to create %s->server socket\n", PROGNAME); proxenet_xfree(req.data); req.id = 0; break; } if (ssl_context.use_ssl) { req.is_ssl = true; if (req.do_intercept == false) { #ifdef DEBUG xlog(LOG_DEBUG, "SSL interception client <-> %s <-> server disabled\n", PROGNAME); #endif proxenet_xfree(req.data); req.type = REQUEST; req.id = get_new_request_id(); continue; } else if (ssl_context.server.is_valid && ssl_context.client.is_valid) { #ifdef DEBUG xlog(LOG_DEBUG, "SSL interception client <-> %s <-> server established\n", PROGNAME); #endif proxenet_xfree(req.data); is_new_http_connection = true; continue; } xlog(LOG_ERROR, "%s\n", "Failed to establish interception"); proxenet_xfree(req.data); break; } is_new_http_connection = true; } /* if proxenet does not relay to another proxy */ if (!cfg->proxy.host) { if (is_new_http_connection) { if (is_ssl) { /* * SSL request fields still have the values gathered in the CONNECT * Those values must be updated to reflect the real request */ free_http_infos(&(req.http_infos)); retcode = update_http_infos(&req); } else { /* * Format requests * GET http://foo/bar.blah HTTP/1.1 ... * into * GET /bar.blah HTTP/1.1 ... */ retcode = format_http_request(&req.data, &req.size); } } else { /* if here, at least 1 request has been to server */ /* so simply forward */ /* e.g. using HTTP/1.1 100 Continue */ #ifdef DEBUG xlog(LOG_DEBUG, "Resuming stream '%d'->'%d'\n", client_socket, server_socket); #endif free_http_infos(&(req.http_infos)); retcode = update_http_infos(&req); } if (retcode < 0){ xlog(LOG_ERROR, "Failed to update %s information in request %d\n", is_ssl?"HTTPS":"HTTP", req.id); proxenet_xfree(req.data); break; } } if(cfg->ie_compat){ if (is_ssl) retcode = ie_compat_read_post_body(server_socket, &req, &(ssl_context.server.context)); else retcode = ie_compat_read_post_body(server_socket, &req, NULL); if (retcode < 0){ xlog(LOG_ERROR, "%s\n", "Extending IE POST: failed"); proxenet_xfree(req.data); break; } } /* apply plugins for requests (from browser to server) */ if (cfg->verbose) { xlog(LOG_INFO, "%s request to '%s:%d'\n", is_ssl?"SSL":"plain", req.http_infos.hostname, req.http_infos.port); if (cfg->verbose > 1) xlog(LOG_INFO, "%s %s %s\n", req.http_infos.method, req.http_infos.uri, req.http_infos.version); } #ifdef DEBUG xlog(LOG_DEBUG, "Request %d pre-plugins: buflen:%lu\n", req.id, req.size); #endif /* hook request with all plugins in plugins_list */ if ( proxenet_apply_plugins(&req) < 0) { /* extremist action: any error on any plugin discard the whole request */ proxenet_xfree( req.data ); break; } #ifdef DEBUG xlog(LOG_DEBUG, "Request %d post-plugins: buflen:%lu\n", req.id, req.size); if(cfg->verbose > 2) proxenet_hexdump(req.data, req.size); #endif send_to_server: /* send modified data */ if (is_ssl && req.do_intercept) { retcode = proxenet_ssl_write(&(ssl_context.client.context), req.data, req.size); } else { retcode = proxenet_write(client_socket, req.data, req.size); } /* reset data */ proxenet_xfree(req.data); req.size = 0; if (retcode < 0) { xlog(LOG_ERROR, "[%d] %s\n", req.id, "Failed to write to server"); break; } #ifdef DEBUG xlog(LOG_DEBUG, "Written %d bytes to server (socket=%s socket #%d)\n", retcode, is_ssl?"SSL":"PLAIN", client_socket); #endif } /* end FD_ISSET(data_from_browser) */ /* is there data from remote server to proxy ? */ if( client_socket > 0 && FD_ISSET(client_socket, &rfds ) ) { if(req.is_ssl && req.do_intercept) { n = proxenet_read_all(client_socket, &req.data, &ssl_context.client.context); } else { n = proxenet_read_all(client_socket, &req.data, NULL); } if (n < 0){ xlog(LOG_ERROR, "read() %s on cli_sock=#%d failed: %d\n", is_ssl?"SSL":"PLAIN", client_socket, n); break; } if (n==0){ #ifdef DEBUG xlog(LOG_DEBUG, "Socket EOF from server (cli_sock=#%d)\n", client_socket); #endif break; } /* update request data structure */ req.type = RESPONSE; /* from here, n can only be positive */ req.size = (size_t) n; bytes_recv += n; if (req.do_intercept==false){ #ifdef DEBUG xlog(LOG_DEBUG, "Intercept disabled for '%s'->browser\n", req.http_infos.hostname); #endif goto send_to_client; } /* apply plugins for response (from server to browser) */ #ifdef DEBUG xlog(LOG_DEBUG, "Response %d pre-plugins: buflen:%lu\n", req.id, req.size); #endif /* execute response hooks */ if ( proxenet_apply_plugins(&req) < 0) { /* extremist action: any error on any plugin discard the whole request */ proxenet_xfree(req.data); break; } #ifdef DEBUG xlog(LOG_DEBUG, "Response %d post-plugins: buflen:%lu\n", req.id, req.size); if(cfg->verbose > 2) proxenet_hexdump(req.data, req.size); #endif send_to_client: /* send modified data to client */ if (req.is_ssl && req.do_intercept) retcode = proxenet_ssl_write(&(ssl_context.server.context), req.data, req.size); else retcode = proxenet_write(server_socket, req.data, req.size); if (retcode < 0) { xlog(LOG_ERROR, "[%d] %s\n", req.id, "proxy->client: write failed"); proxenet_xfree(req.data); break; } #ifdef DEBUG xlog(LOG_DEBUG, "Written %d bytes to browser (socket=%s socket #%d)\n", retcode, is_ssl?"SSL":"PLAIN", client_socket); #endif proxenet_xfree(req.data); } /* end FD_ISSET(data_from_server) */ } /* end for(;;) { select() } */ if (req.id) { if (cfg->verbose) xlog(LOG_INFO, "End of request %d, cleaning context\n", req.id); free_http_infos(&(req.http_infos)); } /* close client socket */ if (client_socket > 0) { if (cfg->verbose >= 2) xlog(LOG_INFO, "Closing %s->server (fd=#%d)\n", PROGNAME, client_socket); proxenet_close_socket(client_socket, &(ssl_context.client)); } /* close local socket */ if (server_socket > 0) { if (cfg->verbose >= 2) xlog(LOG_INFO, "Closing browser->%s (fd=#%d)\n", PROGNAME, server_socket); proxenet_close_socket(server_socket, &(ssl_context.server)); } #ifdef DEBUG xlog(LOG_DEBUG, "Request %d: Structures closed, leaving\n", req.id); #endif /* and that's all folks */ return; }
/** * This function is called right after the configuration was parsed. * It simply: * - creates the main listening sockets (control and proxy) * - initialize the signal mask * - initialize all the VMs * - fill the plugin list with the valid plugins located in the autoload path * - then call the main thread loop * - once finished, it also cleans the structures * * @return 0 if everything went well, -1 otherwise with an error message */ int proxenet_start() { sock_t control_socket, listening_socket; struct sigaction saction; /* create control socket */ control_socket = proxenet_bind_control_socket(); if (control_socket < 0) { xlog(LOG_CRITICAL, "Cannot create control socket: %s\n", strerror(errno)); return -1; } if(cfg->verbose) xlog(LOG_INFO, "Control socket: %d\n", control_socket); /* create listening socket */ listening_socket = proxenet_bind_socket(cfg->iface, cfg->port); if (listening_socket < 0) { xlog(LOG_CRITICAL, "Cannot create bind socket: %s\n", strerror(errno)); return -1; } if(cfg->verbose) xlog(LOG_INFO, "Bind socket: %d\n", listening_socket); /* init everything */ initialize_sigmask(&saction); plugins_list = NULL; proxy_state = INACTIVE; active_threads_bitmask = 0; /* set up plugins */ if( proxenet_initialize_plugins_list() < 0 ) return -1; /* this call *MUST* succeed or die */ proxenet_initialize_plugins(); /* setting request counter */ request_id = 0; /* we "artificially" allocate an ID 0 so that all new requests will be > 0 */ /* for the child threads, a request id of 0 means not allocated */ get_new_request_id(); init_global_stats(); /* prepare threads and start looping */ xloop(listening_socket, control_socket); end_global_stats(); if (cfg->verbose) print_global_stats(); /* clean context */ proxenet_destroy_plugins_vm(); proxenet_free_all_plugins(); proxenet_close_socket(listening_socket, NULL); proxenet_close_socket(control_socket, NULL); unlink(CFG_CONTROL_SOCK_PATH); return 0; }