示例#1
0
文件: pipe.c 项目: gpg/boa
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;
}
示例#2
0
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
}
示例#3
0
/*-----------------------------------------------------------------------------
 * 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);
}
示例#4
0
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(&current_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;
        }
    }
}
示例#5
0
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(&current_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;
        }
    }
}