int read_from_pipe(request * req) { off_t bytes_read; /* signed */ off_t bytes_to_read; /* unsigned */ /* XXX really? */ bytes_to_read = BUFFER_SIZE - (req->header_end - req->buffer - 1); if (bytes_to_read == 0) { /* buffer full */ if (req->cgi_status == CGI_PARSE) { /* got+parsed header */ req->cgi_status = CGI_BUFFER; *req->header_end = '\0'; /* points to end of read data */ /* Could the above statement overwrite data??? No, because req->header_end points to where new data should begin, not where old data is. */ return process_cgi_header(req); /* cgi_status will change */ } req->status = PIPE_WRITE; return 1; } bytes_read = read(req->data_fd, req->header_end, bytes_to_read); #ifdef FASCIST_LOGGING if (bytes_read > 0) { *(req->header_end + bytes_read) = '\0'; fprintf(stderr, "pipe.c - read %d bytes: \"%s\"\n", bytes_read, req->header_end); } else fprintf(stderr, "pipe.c - read %d bytes\n", bytes_read); fprintf(stderr, "status, cgi_status: %d, %d\n", req->status, req->cgi_status); #endif if (bytes_read == -1) { if (errno == EINTR) return 1; else if (errno == EWOULDBLOCK || errno == EAGAIN) return -1; /* request blocked at the pipe level, but keep going */ else { req->status = DEAD; log_error_doc(req); perror("pipe read"); return 0; } } *(req->header_end + bytes_read) = '\0'; if (bytes_read == 0) { /* eof, write rest of buffer */ req->status = PIPE_WRITE; if (req->cgi_status == CGI_PARSE) { /* hasn't processed header yet */ req->cgi_status = CGI_DONE; *req->header_end = '\0'; /* points to end of read data */ return process_cgi_header(req); /* cgi_status will change */ } req->cgi_status = CGI_DONE; return 1; } req->header_end += bytes_read; if (req->cgi_status != CGI_PARSE) return write_from_pipe(req); /* why not try and flush the buffer now? */ else { char *c, *buf; buf = req->header_line; c = strstr(buf, "\n\r\n"); if (c == NULL) { c = strstr(buf, "\n\n"); if (c == NULL) { return 1; } } req->cgi_status = CGI_DONE; *req->header_end = '\0'; /* points to end of read data */ return process_cgi_header(req); /* cgi_status will change */ } return 1; }
void process_requests(void) { int retval = 0; request *current, *trailer; current = request_ready; while (current) { #ifdef CRASHDEBUG crashdebug_current = current; #endif if (current->buffer_end) { req_flush(current); if (current->status == CLOSE) retval = 0; else retval = 1; } else { switch (current->status) { case READ_HEADER: case ONE_CR: case ONE_LF: case TWO_CR: retval = read_header(current); break; case BODY_READ: retval = read_body(current); break; case BODY_WRITE: retval = write_body(current); break; case WRITE: retval = process_get(current); break; case PIPE_READ: retval = read_from_pipe(current); break; case PIPE_WRITE: retval = write_from_pipe(current); break; default: retval = 0; #if 0 fprintf(stderr, "Unknown status (%d), closing!\n", current->status); #endif break; } } if (lame_duck_mode) SQUASH_KA(current); switch (retval) { case -1: /* request blocked */ trailer = current; current = current->next; block_request(trailer); break; default: /* everything else means an error, jump ship */ send_r_error(current); /* fall-through */ case 0: /* request complete */ trailer = current; current = current->next; free_request(&request_ready, trailer); break; case 1: /* more to do */ current->time_last = time_counter; current = current->next; break; } } #ifdef CRASHDEBUG crashdebug_current = current; #endif }
/*----------------------------------------------------------------------------- * FUNCTION: main * * DATE: January 25, 2010 * * REVISIONS: * * DESIGNER: Steffen L. Norgren <*****@*****.**> * * PROGRAMMER: Steffen L. Norgren <*****@*****.**> * * INTERFACE: int main(int argc, char **argv) * argc - argument count * argv - array of arguments * * RETURNS: Result on success or failure. * * NOTES: Main entry point into the application. Parses command line options * and sets up conditions to create new child processes. * *----------------------------------------------------------------------------*/ int main (int argc, char **argv) { PRIME_OPTIONS *opts; int c, option_index = 0; static struct option long_options[] = { {"processes" , required_argument , 0, 'p'}, {"output" , required_argument , 0, 'o'}, {"start" , required_argument , 0, 's'}, {"block" , required_argument , 0, 'b'}, {"help" , no_argument , 0, 'h'}, {0, 0, 0, 0} }; opts = malloc(sizeof(PRIME_OPTIONS)); /* Set Defaults */ opts->output = _OPTS_OUTPUT; opts->processes = _OPTS_PROCESSES; opts->start = _OPTS_START; opts->block = _OPTS_BLOCK; while (1) { c = getopt_long(argc, argv, "p:o:s:b:h", long_options, &option_index); if (c == -1) break; switch (c) { case 0: /* If the option set a flag, do nothing */ if (long_options[option_index].flag != 0) break; break; case 'p': if (atoi(optarg) > 0) opts->processes = atoi(optarg); break; case 'o': opts->output = optarg; break; case 's': if (atoi(optarg) > 0) opts->start = atoi(optarg); break; case 'b': if (atoi(optarg) > 0) opts->block = atoi(optarg); break; case 'h': print_usage(argv[0], _OPTS_HELP); break; default: print_usage(argv[0], _OPTS_ERROR); break; } } /* Print current settings */ print_settings(argc, opts); /* Start the child processes */ create_processes(opts); /* Start reading from the pipe and writing to the file */ printf("Parent pid %d writing output to file %s\n", getpid(), opts->output); write_from_pipe(opts); printf("Parent pid %d finished writing to file %s\n", getpid(), opts->output); free(opts); exit(_PARENT_EXIT); }
void process_requests(int server_sock) { int retval = 0; request *current, *trailer; if (pending_requests) { get_request(server_sock); #ifdef ORIGINAL_BEHAVIOR pending_requests = 0; #endif } current = request_ready; while (current) { time(¤t_time); retval = 1; /* emulate "success" in case we don't have to flush */ if (current->buffer_end && /* there is data in the buffer */ current->status < TIMED_OUT) { retval = req_flush(current); /* * retval can be -2=error, -1=blocked, or bytes left */ if (retval == -2) { /* error */ current->status = DEAD; retval = 0; } else if (retval >= 0) { /* notice the >= which is different from below? Here, we may just be flushing headers. We don't want to return 0 because we are not DONE or DEAD */ retval = 1; } } if (retval == 1) { switch (current->status) { case READ_HEADER: case ONE_CR: case ONE_LF: case TWO_CR: retval = read_header(current); break; case BODY_READ: retval = read_body(current); break; case BODY_WRITE: retval = write_body(current); break; case WRITE: retval = process_get(current); break; case PIPE_READ: retval = read_from_pipe(current); break; case PIPE_WRITE: retval = write_from_pipe(current); break; case IOSHUFFLE: #ifdef HAVE_SENDFILE retval = io_shuffle_sendfile(current); #else retval = io_shuffle(current); #endif break; case DONE: /* a non-status that will terminate the request */ retval = req_flush(current); /* * retval can be -2=error, -1=blocked, or bytes left */ if (retval == -2) { /* error */ current->status = DEAD; retval = 0; } else if (retval > 0) { retval = 1; } break; case TIMED_OUT: case DEAD: retval = 0; current->buffer_end = 0; SQUASH_KA(current); break; default: retval = 0; fprintf(stderr, "Unknown status (%d), " "closing!\n", current->status); current->status = DEAD; break; } } if (sigterm_flag) { SQUASH_KA(current); } /* we put this here instead of after the switch so that * if we are on the last request, and get_request is successful, * current->next is valid! */ if (pending_requests) get_request(server_sock); switch (retval) { case -1: /* request blocked */ trailer = current; current = current->next; block_request(trailer); break; case 0: /* request complete */ current->time_last = current_time; trailer = current; current = current->next; free_request(trailer); break; case 1: /* more to do */ current->time_last = current_time; current = current->next; break; default: log_error_doc(current); fprintf(stderr, "Unknown retval in process.c - " "Status: %d, retval: %d\n", current->status, retval); current->status = DEAD; current = current->next; break; } } }
void process_requests(int server_s, struct soap *soap)/*by SeanHou*/ { /* :TODO:Monday, December 01, 2014 11:17:36 HKT:SeanHou: */ int OnvifEN = 0; int lookupindex = 0; char service_uri[100] = ""; memset((void*)&soap->peer, 0, sizeof(soap->peer)); soap->socket = SOAP_INVALID_SOCKET; soap->error = SOAP_OK; soap->errmode = 0; soap->keep_alive = 0; fprintf(stderr, "Warning:" \ "(==>%s).\n", __func__); /* :TODO:End--- */ int retval = 0; request *current, *trailer; if (pending_requests) { get_request(server_s); #ifdef ORIGINAL_BEHAVIOR pending_requests = 0; #endif } current = request_ready; while (current) { /* :TODO:Monday, December 01, 2014 11:18:42 HKT:SeanHou: juge is onvif */ OnvifEN = isonvif(current->client_stream, service_uri, &lookupindex); if(OnvifEN == 1) { fprintf(stderr, "[boa:onvif] Warning: is onvif line[%d]remote port[%d]h2ns[%d]remote ip[%s]\n", __LINE__, current->remote_port, htons(current->remote_port), current->remote_ip_addr); struct sockaddr_in onvif_client_addr; memset(&onvif_client_addr, 0, sizeof(onvif_client_addr)); onvif_client_addr.sin_family = AF_INET; onvif_client_addr.sin_port = htons(current->remote_port);//随机端口 onvif_client_addr.sin_addr.s_addr = inet_addr(current->remote_ip_addr);// soap->socket = current->fd; soap->peer = onvif_client_addr; if (soap_valid_socket(soap->socket)) { soap->ip = ntohl(soap->peer.sin_addr.s_addr); soap->port = (int)ntohs(soap->peer.sin_port); soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0); } g_onvif_buffer = (char *)soap_malloc(soap, sizeof(current->client_stream)); strcpy(g_onvif_buffer, current->client_stream);//mark soap_begin_recv(soap); if (soap_envelope_begin_in(soap)) { soap_send_fault(soap); } if (soap_recv_header(soap)) { soap_send_fault(soap); } if (soap_body_begin_in(soap)) { soap_send_fault(soap); } int errorCode = 0; if (errorCode = soap_serve_request(soap)) { fprintf(stderr, "[boa:onvif]soap_serve_request fail, errorCode %d \n", errorCode); soap_send_fault(soap); } memset(current->client_stream, 0, CLIENT_STREAM_SIZE ); soap_dealloc(soap, NULL); soap_destroy(soap); soap_end(soap); current->status = DONE; close(soap->socket); continue; } /* :TODO:End--- */ time(¤t_time); if (current->buffer_end && /* there is data in the buffer */ current->status != DEAD && current->status != DONE) { retval = req_flush(current); /* * retval can be -2=error, -1=blocked, or bytes left */ if (retval == -2) { /* error */ current->status = DEAD; retval = 0; } else if (retval >= 0) { /* notice the >= which is different from below? Here, we may just be flushing headers. We don't want to return 0 because we are not DONE or DEAD */ retval = 1; } } else { switch (current->status) { case READ_HEADER: case ONE_CR: case ONE_LF: case TWO_CR: retval = read_header(current); break; case BODY_READ: retval = read_body(current); break; case BODY_WRITE: retval = write_body(current); break; case WRITE: retval = process_get(current); break; case PIPE_READ: retval = read_from_pipe(current); break; case PIPE_WRITE: retval = write_from_pipe(current); break; case DONE: /* a non-status that will terminate the request */ retval = req_flush(current); /* * retval can be -2=error, -1=blocked, or bytes left */ if (retval == -2) { /* error */ current->status = DEAD; retval = 0; } else if (retval > 0) { retval = 1; } break; case DEAD: retval = 0; current->buffer_end = 0; SQUASH_KA(current); break; default: retval = 0; fprintf(stderr, "Unknown status (%d), " "closing!\n", current->status); current->status = DEAD; break; } } if (sigterm_flag) SQUASH_KA(current); /* we put this here instead of after the switch so that * if we are on the last request, and get_request is successful, * current->next is valid! */ if (pending_requests) get_request(server_s); switch (retval) { case -1: /* request blocked */ trailer = current; current = current->next; block_request(trailer); break; case 0: /* request complete */ current->time_last = current_time; trailer = current; current = current->next; free_request(&request_ready, trailer); break; case 1: /* more to do */ current->time_last = current_time; current = current->next; break; default: log_error_time(); fprintf(stderr, "Unknown retval in process.c - " "Status: %d, retval: %d\n", current->status, retval); current = current->next; break; } } }