Exemplo n.º 1
0
static void
handle_read( int cnum, struct timeval* nowP )
    {
    char buf[30000];	/* must be larger than throttle / 2 */
    int bytes_to_read, bytes_read, bytes_handled;
    float elapsed;
    ClientData client_data;
    register long checksum;

    tmr_reset( nowP, connections[cnum].idle_timer );

    if ( do_throttle )
	bytes_to_read = throttle / 2.0;
    else
	bytes_to_read = sizeof(buf);
    if ( ! connections[cnum].did_response )
	{
	connections[cnum].did_response = 1;
	connections[cnum].response_at = *nowP;
	}
#ifdef USE_SSL
    if ( urls[connections[cnum].url_num].protocol == PROTO_HTTPS )
	bytes_read = SSL_read( connections[cnum].ssl, buf, bytes_to_read );
    else
	bytes_read = read( connections[cnum].conn_fd, buf, bytes_to_read );
#else
    bytes_read = read( connections[cnum].conn_fd, buf, bytes_to_read );
#endif
    if ( bytes_read <= 0 )
	{
	close_connection( cnum );
	return;
	}

    for ( bytes_handled = 0; bytes_handled < bytes_read; )
	{
	switch ( connections[cnum].conn_state )
	    {
	    case CNST_HEADERS:
	    /* State machine to read until we reach the file part.  Looks for
	    ** Content-Length header too.
	    */
	    for ( ; bytes_handled < bytes_read && connections[cnum].conn_state == CNST_HEADERS; ++bytes_handled )
		{
		switch ( connections[cnum].header_state )
		    {

		    case HDST_LINE1_PROTOCOL:
		    switch ( buf[bytes_handled] )
			{
			case ' ': case '\t':
			connections[cnum].header_state = HDST_LINE1_WHITESPACE;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			}
		    break;

		    case HDST_LINE1_WHITESPACE:
		    switch ( buf[bytes_handled] )
			{
			case ' ': case '\t':
			break;
			case '0': case '1': case '2': case '3': case '4':
			case '5': case '6': case '7': case '8': case '9':
			connections[cnum].http_status =
			    buf[bytes_handled] - '0';
			connections[cnum].header_state = HDST_LINE1_STATUS;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_LINE1_STATUS:
		    switch ( buf[bytes_handled] )
			{
			case '0': case '1': case '2': case '3': case '4':
			case '5': case '6': case '7': case '8': case '9':
			connections[cnum].http_status =
			    connections[cnum].http_status * 10 +
			    buf[bytes_handled] - '0';
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_BOL:
		    switch ( buf[bytes_handled] )
			{
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			case 'C': case 'c':
			connections[cnum].header_state = HDST_C;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_TEXT:
		    switch ( buf[bytes_handled] )
			{
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			break;
			}
		    break;

		    case HDST_LF:
		    switch ( buf[bytes_handled] )
			{
			case '\n':
			connections[cnum].conn_state = CNST_READING;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			case 'C': case 'c':
			connections[cnum].header_state = HDST_C;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CR:
		    switch ( buf[bytes_handled] )
			{
			case '\n':
			connections[cnum].header_state = HDST_CRLF;
			break;
			case '\r':
			connections[cnum].conn_state = CNST_READING;
			break;
			case 'C': case 'c':
			connections[cnum].header_state = HDST_C;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CRLF:
		    switch ( buf[bytes_handled] )
			{
			case '\n':
			connections[cnum].conn_state = CNST_READING;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CRLFCR;
			break;
			case 'C': case 'c':
			connections[cnum].header_state = HDST_C;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CRLFCR:
		    switch ( buf[bytes_handled] )
			{
			case '\n': case '\r':
			connections[cnum].conn_state = CNST_READING;
			break;
			case 'C': case 'c':
			connections[cnum].header_state = HDST_C;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_C:
		    switch ( buf[bytes_handled] )
			{
			case 'O': case 'o':
			connections[cnum].header_state = HDST_CO;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CO:
		    switch ( buf[bytes_handled] )
			{
			case 'N': case 'n':
			connections[cnum].header_state = HDST_CON;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CON:
		    switch ( buf[bytes_handled] )
			{
			case 'T': case 't':
			connections[cnum].header_state = HDST_CONT;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CONT:
		    switch ( buf[bytes_handled] )
			{
			case 'E': case 'e':
			connections[cnum].header_state = HDST_CONTE;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CONTE:
		    switch ( buf[bytes_handled] )
			{
			case 'N': case 'n':
			connections[cnum].header_state = HDST_CONTEN;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CONTEN:
		    switch ( buf[bytes_handled] )
			{
			case 'T': case 't':
			connections[cnum].header_state = HDST_CONTENT;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CONTENT:
		    switch ( buf[bytes_handled] )
			{
			case '-':
			connections[cnum].header_state = HDST_CONTENT_;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CONTENT_:
		    switch ( buf[bytes_handled] )
			{
			case 'L': case 'l':
			connections[cnum].header_state = HDST_CONTENT_L;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CONTENT_L:
		    switch ( buf[bytes_handled] )
			{
			case 'E': case 'e':
			connections[cnum].header_state = HDST_CONTENT_LE;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CONTENT_LE:
		    switch ( buf[bytes_handled] )
			{
			case 'N': case 'n':
			connections[cnum].header_state = HDST_CONTENT_LEN;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CONTENT_LEN:
		    switch ( buf[bytes_handled] )
			{
			case 'G': case 'g':
			connections[cnum].header_state = HDST_CONTENT_LENG;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CONTENT_LENG:
		    switch ( buf[bytes_handled] )
			{
			case 'T': case 't':
			connections[cnum].header_state = HDST_CONTENT_LENGT;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CONTENT_LENGT:
		    switch ( buf[bytes_handled] )
			{
			case 'H': case 'h':
			connections[cnum].header_state = HDST_CONTENT_LENGTH;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CONTENT_LENGTH:
		    switch ( buf[bytes_handled] )
			{
			case ':':
			connections[cnum].header_state = HDST_CONTENT_LENGTH_COLON;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CONTENT_LENGTH_COLON:
		    switch ( buf[bytes_handled] )
			{
			case ' ': case '\t':
			connections[cnum].header_state = HDST_CONTENT_LENGTH_COLON_WHITESPACE;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CONTENT_LENGTH_COLON_WHITESPACE:
		    switch ( buf[bytes_handled] )
			{
			case ' ': case '\t':
			break;
			case '0': case '1': case '2': case '3': case '4':
			case '5': case '6': case '7': case '8': case '9':
			connections[cnum].content_length = buf[bytes_handled] - '0';
			connections[cnum].header_state = HDST_CONTENT_LENGTH_COLON_WHITESPACE_NUM;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CONTENT_LENGTH_COLON_WHITESPACE_NUM:
		    switch ( buf[bytes_handled] )
			{
			case '0': case '1': case '2': case '3': case '4':
			case '5': case '6': case '7': case '8': case '9':
			connections[cnum].content_length =
			    connections[cnum].content_length * 10 +
			    buf[bytes_handled] - '0';
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    }
		}
	    break;

	    case CNST_READING:
	    connections[cnum].bytes += bytes_read - bytes_handled;
	    if ( do_throttle )
		{
		/* Check if we're reading too fast. */
		elapsed = delta_timeval( &connections[cnum].started_at, nowP ) / 1000000.0;
		if ( elapsed > 0.01 && connections[cnum].bytes / elapsed > throttle )
		    {
		    connections[cnum].conn_state  = CNST_PAUSING;
		    client_data.i = cnum;
		    connections[cnum].wakeup_timer = tmr_create(
			nowP, wakeup_connection, client_data, 1000L, 0 );
		    }
		}
	    if ( do_checksum )
		{
		checksum = connections[cnum].checksum;
		for ( ; bytes_handled < bytes_read; ++bytes_handled )
		    {
		    if ( checksum & 1 )
			checksum = ( checksum >> 1 ) + 0x8000;
		    else
			checksum >>= 1;
		    checksum += buf[bytes_handled];
		    checksum &= 0xffff;
		    }
		connections[cnum].checksum = checksum;
		}
	    else
		bytes_handled = bytes_read;

	    if ( connections[cnum].content_length != -1 &&
		 connections[cnum].bytes >= connections[cnum].content_length )
		{
		close_connection( cnum );
		return;
		}

	    break;
	    }
Exemplo n.º 2
0
int main(int argc, char *argv[])
{
#if 0
	int c, major, minor, flags = 0;

	while ((c = getopt(argc, argv, "f:vV")) != EOF)
		switch (c) {
		case 'v':
			flags |= WALK_VERBOSE;
			break;
		case 'f':
			flags |= strtol(optarg, NULL, 0);
			break;
		case 'V':
			samlib_version(&major, &minor);
			printf("Version  '%d.%d'  '%s'\n",
				   major, minor, samlib_versionstr());
			exit(0);
		}

	if (argc == optind) {
		fputs("I need a directory!\n", stderr);
		exit(1);
	}

	return walkfiles(NULL, argv[optind], NULL, 0);
#else
	struct timeval start, end;

	start.tv_sec = 10;
	start.tv_usec = 100;
	end.tv_sec = 10;
	end.tv_usec = 101;

	if (delta_timeval(&start, &end) != 1)
		puts("PROBS 1");

	start.tv_sec = 10;
	start.tv_usec = 999999;
	end.tv_sec = 11;
	end.tv_usec = 0;

	if (delta_timeval(&start, &end) != 1)
		puts("PROBS 2");

	start.tv_sec = 10;
	start.tv_usec = 100;
	end.tv_sec = 11;
	end.tv_usec = 101;

	if (delta_timeval(&start, &end) != 1000001)
		puts("PROBS 3");

	start.tv_sec = 10;
	start.tv_usec = 999999;
	end.tv_sec = 12;
	end.tv_usec = 0;

	if (delta_timeval(&start, &end) != 1000001)
		puts("PROBS 4");

	start.tv_sec = 10;
	start.tv_usec = 101;
	end.tv_sec = 10;
	end.tv_usec = 100;

	if (delta_timeval(&start, &end) != ~0UL)
		puts("PROBS 5");

	start.tv_sec = 10;
	start.tv_usec = 999999;
	end.tv_sec = 10;
	end.tv_usec = 0;

	if (delta_timeval(&start, &end) != ~0UL)
		puts("PROBS 6");

	return 0;
#endif
}