Exemplo n.º 1
0
void msg_event_handler( int fd, int msgid, int event ) {
    char buf[PACK_DATA_SIZE];
    ssize_t n;
//	printf( "event 0x%03x for msg %d\n", event, msgid );
    switch ( event ) {
    case MSG_EVT_ACCEPT_READY:
        if ( msg_accept( fd, msgid ) != 0 )
            msg_set_read( fd, msgid );
        // These are commands
        break;
    case MSG_EVT_READ_READY:
        msg_clr_read( fd, msgid );

        n = msg_read( fd, msgid, buf, sizeof( buf ) );
        if ( n <= 0 ) {
            cleanup_connection( msg_get_type( fd, msgid ) );
            break;
        }

        if ( msg_get_type( fd, msgid ) < 0 ) {
            /* If the msgid is less than zero, it refers to a command and
               the message should not be routed to a file descriptor. */

            // the entire command must fit inside one transport
            command_handler( fd, msgid, buf, n );

        } else {
            zs_set_write( msg_get_type( fd, msgid ) );
            /* if msgid is zero or greater it refers to a socket file
               descriptor that the message should be routed to. */
            if ( zs_write( msg_get_type( fd, msgid ), buf, n ) == -1 )
                cleanup_connection( msg_get_type( fd, msgid ) );
        }
        break;
    case MSG_EVT_WRITE_READY:
        if ( msgid < 0 ) break;
        zs_set_read( msg_get_type( fd, msgid ) );
        msg_clr_write( fd, msgid );
        break;
    case MSG_SWITCH_EVT_IO_ERROR:
        //zclose( msg_switch->sockfd );
        if ( website_get_by_sockfd( fd ) )
            remove_website( fd );
        else {
            for ( n = 0; n < FD_SETSIZE; n++ ) {
                if ( msg_exists( fd, n ) ) {
                    if ( msg_get_type( fd, n ) > 0 )
                        cleanup_connection( msg_get_type( fd, n ) );
                    //	else
                    //		msg_close( fd, n );
                }
            }
            msg_switch_destroy( fd );
            zs_close( fd );
        }
        break;
    }
}
Exemplo n.º 2
0
int forward_client_to_service(struct ConnectionState *st) {
  char buf[4096];
  int r = 1;
  int ret = SSL_read(st->ssl, buf, sizeof(buf));
  int err = SSL_get_error(st->ssl, ret);
  switch (err) {
  case SSL_ERROR_NONE:
  {
//    fcntl(st->service_conn, F_SETFL, 0);
    assert(ret > 0);
    stats.up_bytes += ret;
    int status = sendall(st->service_conn, buf, ret);
    log_data(st, buf, ret);
    if (status < 0) {
      fprintf(stderr, "couldn't forward data to service\n");
      cleanup_connection(st);
      return 0;
    }
//    fcntl(st->service_conn, F_SETFL, O_NONBLOCK);
    break;
  }
  case SSL_ERROR_ZERO_RETURN:
  case SSL_ERROR_WANT_CONNECT:
  case SSL_ERROR_WANT_ACCEPT:
  case SSL_ERROR_WANT_X509_LOOKUP:
  case SSL_ERROR_SYSCALL:
  case SSL_ERROR_SSL:
    if (err == SSL_ERROR_SSL) {
      extern BIO *bio_err;
      if (!bio_err) {
        bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
      }
      ERR_print_errors(bio_err);
    } else if (err == SSL_ERROR_SYSCALL) {
        // Socket closed
        cleanup_connection_after_ssl(st, 1);
        return 0;
    }
    cleanup_connection(st);
    r = 0;
    break;
  case SSL_ERROR_WANT_READ:
  case SSL_ERROR_WANT_WRITE:
    //fprintf(stderr, "Ignoring recoverable SSL error %d while forwarding to service\n", err);
    break;
  }

  return r;
}
Exemplo n.º 3
0
int remove_website( int fd ) {
    website_t* website;

    if ( !( website = website_get_by_sockfd( fd ) ) ) {
        syslog( LOG_WARNING, "stop_website: tried to stop a nonexisting website" );
        return 0;
    }

    syslog( LOG_INFO, "website: stopping \"%s\" on \"%s\"", website->full_url, website->ip );
    website_data_t* website_data = (website_data_t*) website->udata;

    int i;
    for ( i = 0; i < FD_SETSIZE; i++ ) {
        if ( connections[ i ] && connections[ i ]->website_sockfd == website->sockfd )
            cleanup_connection( i );
    }

    msg_switch_destroy( fd );
    zs_close( fd );

    if ( website_data->exlisnfd != -1 )
        zs_close( website_data->exlisnfd );

    free( website_data );
    website_remove( website );

    return 1;
}
Exemplo n.º 4
0
int main(int argc, char **argv)
{
	(void)argc;
	(void)argv;
	const uint32_t net = 0x0a0a0a00;
	char *password;

	setup_test("tcpr-test", "test-spurious-fins");
	password = get_password(htonl(net | 2), 8888, htonl(net | 3), 9999);

	setup_connection(net | 2, net | 4, net | 3, 8888, 9999, 0xdeadbeef,
				0xcafebabe, test_options_size, test_options,
				peer_mss, peer_ws, password);

	fprintf(stderr, "Application: FIN (failure)\n");
	send_segment(internal_log, net | 4, net | 2, 9999, 8888,
			TH_ACK | TH_FIN, 0xcafebabe + 1, 0xdeadbeef + 1, 0,
			NULL, 0, NULL, password);

	fprintf(stderr, "     Filter: RST\n");
	recv_segment(internal_log, net | 2, net | 4, 8888, 9999, TH_RST,
			0xdeadbeef + 1, 0, 0, NULL, 0, NULL, password);

	cleanup_connection(net | 2, net | 4, 8888, 9999, 0xcafebabe + 1,
				0xdeadbeef + 1, 0);

	cleanup_test();
	return EXIT_SUCCESS;
}
Exemplo n.º 5
0
static void on_read_ready(int fd, short event_type, struct ConnectionState *st) {
  assert(event_type == EV_READ);
  if (st->client_conn == fd) {
    st->client_ready[READ] = 1;
    event_del(st->ev_client_read);

    if (st->cleanup_waiting == SSL_ERROR_WANT_READ) {
      cleanup_connection_ssl_try_shutdown(st);
      return;
    } 

//    g_slice_free(st->ev_client_read);
//    st->ev_client_read = 0;
  } else if (st->service_conn == fd) {
    st->service_ready[READ] = 1;
    event_del(st->ev_service_read);
//    g_slice_free(st->ev_service_read);
//    st->ev_service_read = 0;
  } else {
    //fprintf(stderr,"Error: on_read_ready(%d, %d, %p)\n", fd, event_type, st);
    cleanup_connection(st);
    return;
  }

  try_to_forward(st);
  pet_watchdog(st);
}
Exemplo n.º 6
0
int forward_service_to_client(struct ConnectionState *st) {
  assert(st->client_conn >= 0);

  int conn = st->service_conn;
  int r = 1;
  char buf[4096];
  int num_received = recv(conn, buf, sizeof(buf), 0);
  if (num_received < 0) {
    perror("Error reading from service");
    if (errno == EAGAIN || errno == EWOULDBLOCK) {
      fprintf(stderr, "on_service_read called, but we'd block\n");
      return r;
    }

    cleanup_connection(st);
    r = 0;
    return r;
  } else if (num_received == 0) {
    cleanup_connection(st);
    r = 0;
    return r;
  }
  stats.down_bytes += num_received;

  // TODO(swolchok): some error codes are non-fatal...
  int ret = SSL_write(st->ssl, buf, num_received);
  int err = SSL_get_error(st->ssl, ret);
  switch (err) {
  case SSL_ERROR_NONE:
    break;
  case SSL_ERROR_WANT_WRITE:
  case SSL_ERROR_WANT_READ:
    //fprintf(stderr, "Recoverable SSL error %d writing to client", err);
    break;
  default:
    fprintf(stderr, "SSL error %d writing to client\n", err);
    cleanup_connection(st);
    r = 0;
    break;
  }

  return r;
}
Exemplo n.º 7
0
void cleanup_iet_isns(void)
{
	struct portal *p;

	cleanup_connection(sock_fd);
	if (iet_entity)
		free(iet_entity);
	while (iet_portal) {
		p = iet_portal->next;
		free(iet_portal);
		iet_portal = p;
	};
}
Exemplo n.º 8
0
MemcachedStore::~MemcachedStore()
{
  // Destroy the updater (if it was created).
  delete _updater;

  // Clean up this thread's connection now, rather than waiting for
  // pthread_exit.  This is to support use by single-threaded code
  // (e.g., UTs), where pthread_exit is never called.
  connection* conn = (connection*)pthread_getspecific(_thread_local);
  if (conn != NULL)
  {
    pthread_setspecific(_thread_local, NULL);
    cleanup_connection(conn);
  }

  pthread_rwlock_destroy(&_view_lock);
}
Exemplo n.º 9
0
int main(int argc, char **argv)
{
	(void)argc;
	(void)argv;
	const uint32_t net = 0x0a0a0a00;
	char *password;

	setup_test("tcpr-test", "test-recover-peer-send");
	password = get_password(htonl(net | 2), 8888, htonl(net | 3), 9999);

	setup_connection(net | 2, net | 4, net | 3, 8888, 9999, 0xdeadbeef,
				0xcafebabe, test_options_size, test_options,
				peer_mss, peer_ws, password);

	recover_connection(net | 5, net | 2, net | 3, 9999, 8888, 0xfeedbead,
				0xcafebabe, 0xdeadbeef, test_options_size, test_options,
				peer_mss, peer_ws, TCPR_HAVE_ACK | TCPR_HAVE_PEER_MSS
				| TCPR_HAVE_PEER_WS, password);

	fprintf(stderr, "       Peer: \"baz\" (retransmit)\n");
	send_segment(external_log, net | 2, net | 3, 8888, 9999, TH_ACK,
			0xdeadbeef + 1, 0xcafebabe + 1, 0, NULL, 4, "baz", password);
	recv_segment(internal_log, net | 2, net | 5, 8888, 9999, TH_ACK,
			0xdeadbeef + 1, 0xfeedbead + 1, 0, NULL, 4, "baz", password);

	fprintf(stderr, "Application: ACK\n");
	send_segment(internal_log, net | 5, net | 2, 9999, 8888, TH_ACK,
			0xfeedbead + 1, 0xdeadbeef + 5, 0, NULL, 0, NULL, password);

	fprintf(stderr, "Application: update\n");
	send_update(net | 2, net | 5, 8888, 9999, 0xcafebabe + 1,
			0xdeadbeef + 5, 0, 0,
			(0xfeedbead + 1) - (0xcafebabe + 1), TCPR_HAVE_ACK);

	fprintf(stderr, "     Filter: ACK\n");
	recv_segment(external_log, net | 3, net | 2, 9999, 8888, TH_ACK,
			0xcafebabe + 1, 0xdeadbeef + 5, 0, NULL, 0, NULL, password);

	cleanup_connection(net | 2, net | 4, 8888, 9999, 0xcafebabe + 1,
				0xdeadbeef + 1,
				(0xfeedbead + 1) - (0xcafebabe + 1));

	cleanup_test();
	return EXIT_SUCCESS;
}
Exemplo n.º 10
0
int main(int argc, char **argv)
{
	(void)argc;
	(void)argv;
	const uint32_t net = 0x0a0a0a00;
	char *password;

	setup_test("tcpr-test", "test-filter-recovery");
	password = get_password(htonl(net | 2), 8888, htonl(net | 3), 9999);

	fprintf(stderr, "Application: \"a\"\n");
	send_segment(internal_log, net | 4, net | 2, 9999, 8888, TH_ACK,
			0xbeefbead, 0xbabedeed, 0, NULL, 2, "a", password);

	fprintf(stderr, "     Filter: update (failure)\n");
	recv_update(net | 2, net | 4, 8888, 9999, 0, 0, 0, 0, 0, 0);

	fprintf(stderr, "Application: update\n");
	send_update(net | 2, net | 4, 8888, 9999, 0xbeefbead, 0xbabedeed - 4,
			peer_mss, peer_ws, 0, TCPR_HAVE_ACK);

	fprintf(stderr, "     Filter: ACK\n");
	recv_segment(external_log, net | 3, net | 2, 9999, 8888, TH_ACK,
			0xbeefbead + 2, 0xbabedeed - 4, 0, NULL, 0, NULL, password);

	fprintf(stderr, "Application: \"a\" (retransmit)\n");
	send_segment(internal_log, net | 4, net | 2, 9999, 8888, TH_ACK,
			0xbeefbead, 0xbabedeed, 0, NULL, 2, "a", password);
	recv_segment(external_log, net | 3, net | 2, 9999, 8888, TH_ACK,
			0xbeefbead, 0xbabedeed - 4, 0, NULL, 2, "a", password);

	cleanup_connection(net | 2, net | 4, 8888, 9999, 0xbeefbead,
				0xbabedeed - 4, 0);

	cleanup_test();
	return EXIT_SUCCESS;
}
Exemplo n.º 11
0
int main(int argc, char **argv)
{
    (void)argc;
    (void)argv;
    const uint32_t net = 0x0a0a0a00;
    char *password;

    setup_test("tcpr-test", "test-simultaneous-recovery");
    password = get_password(htonl(net | 2), 8888, htonl(net | 3), 9999);

    fprintf(stderr, "Application: SYN (simultaneous recovery)\n");
    send_segment(internal_log, net | 4, net | 2, 9999, 8888, TH_SYN,
                 0xcafebabe, 0, 0, NULL, 0, NULL, password);
    recv_segment(external_log, net | 3, net | 2, 9999, 8888, TH_SYN,
                 0xcafebabe, 0, 0, NULL, 0, NULL, password);

    fprintf(stderr, "       Peer: ACK (answer unacceptable SYN)\n");
    send_segment(external_log, net | 2, net | 3, 8888, 9999, TH_ACK,
                 0xdeadbeef + 5, 0xcafebabe + 1, 0, NULL, 0, NULL, password);

    fprintf(stderr, "     Filter: update (failure)\n");
    recv_update(net | 2, net | 4, 8888, 9999, 0xcafebabe + 1, 0, 0, 0, 0,
                0);

    fprintf(stderr, "Application: update\n");
    send_update(net | 2, net | 4, 8888, 9999, 0xcafebabe + 1,
                0xdeadbeef + 5, 0, 0, 0, TCPR_HAVE_ACK);

    fprintf(stderr, "     Filter: ACK\n");
    recv_segment(external_log, net | 3, net | 2, 9999, 8888, TH_ACK,
                 0xcafebabe + 1, 0xdeadbeef + 5, 0, NULL, 0, NULL, password);

    fprintf(stderr, "Application: SYN (retransmit)\n");
    send_segment(internal_log, net | 4, net | 2, 9999, 8888, TH_SYN,
                 0xcafebabe, 0, 0, NULL, 0, NULL, password);

    fprintf(stderr, "     Filter: SYN ACK\n");
    recv_segment(internal_log, net | 2, net | 4, 8888, 9999,
                 TH_SYN | TH_ACK, 0xdeadbeef + 4, 0xcafebabe + 1, 0,
                 NULL, 0, NULL, password);

    fprintf(stderr, "     Filter: update\n");
    recv_update(net | 2, net | 4, 8888, 9999, 0xcafebabe + 1,
                0xdeadbeef + 5, 0, 0, 0, TCPR_HAVE_ACK);

    fprintf(stderr, "Application: ACK\n");
    send_segment(internal_log, net | 4, net | 2, 9999, 8888, TH_ACK,
                 0xcafebabe + 1, 0xdeadbeef + 5, 0, NULL, 0, NULL, password);
    recv_segment(external_log, net | 3, net | 2, 9999, 8888, TH_ACK,
                 0xcafebabe + 1, 0xdeadbeef + 5, 0, NULL, 0, NULL, password);

    fprintf(stderr, "Application: update (reset)\n");
    send_update(net | 2, net | 4, 8888, 9999, 0xcafebabe + 1,
                0xdeadbeef + 5, 0, 0, 0,
                TCPR_HAVE_ACK | TCPR_TIME_WAIT);

    cleanup_connection(net | 2, net | 4, 8888, 9999, 0xcafebabe + 1,
                       0xdeadbeef + 1, 0);

    cleanup_test();
    return EXIT_SUCCESS;
}
Exemplo n.º 12
0
void exread( int sockfd ) {
    void* ptr;
    conn_data_t* conn_data = connections[ sockfd ];

    if ( !conn_data->buffer ) {
        conn_data->buffer = malloc(PACK_DATA_SIZE);
        conn_data->bufferlen = 0;
        memset( conn_data->buffer, 0, PACK_DATA_SIZE );
    }

    website_t* website;

    ssize_t len = zs_read( sockfd, conn_data->buffer + conn_data->bufferlen, PACK_DATA_SIZE - conn_data->bufferlen );

    // TODO: wait for entire header before looking up website
    if ( len <= 0 ) {
cleanup:
        // cleanup
        cleanup_connection( sockfd );
        return;
    }

    if ( conn_data->postlen == -1 ) /* if we have received all the data already, ignore */
        return;

    conn_data->bufferlen += len;
    //printf( "%d: read %zu\n", sockfd, len );

    ptr = conn_data->buffer;

    if ( conn_data->website_sockfd == -1 ) {
        /* If req_info is NULL this is the start of a request and the
           HTTP request headers need to be parsed. */
        struct hostent* hp;
        hp = NULL;//gethostbyaddr( (char*) &conn_data->addr, sizeof( conn_data->addr ), AF_INET );

        char* endofhdrs;
        if ( !( endofhdrs = strnstr( conn_data->buffer, HTTP_HDR_ENDL HTTP_HDR_ENDL, PACK_DATA_SIZE ) ) ) {
            if ( conn_data->bufferlen == PACK_DATA_SIZE ) {
                /* If the end of the headers was not found the request was either
                   malformatted or too long, DO NOT send to website. */
                zs_write( sockfd, html_error_414, sizeof( html_error_414 ) );
                syslog( LOG_WARNING, "exread: headers to long" );
                goto cleanup;
            }
            // Have not received the full header yet, wait
            zs_set_read( sockfd );
            return;
        }
        endofhdrs += sizeof( HTTP_HDR_ENDL HTTP_HDR_ENDL ) - 1;
        /* Get HTTP request type */
        if ( startswith( conn_data->buffer, HTTP_GET ) )
            conn_data->request_type = HTTP_GET_TYPE;
        else if ( startswith( conn_data->buffer, HTTP_POST ) )
            conn_data->request_type = HTTP_POST_TYPE;
        else {
            zs_write( sockfd, html_error_400, sizeof( html_error_400 ) );
            goto cleanup;
        }

        /* Find website for request from HTTP header */
        char urlbuf[ PACK_DATA_SIZE ];
        if ( !get_url_from_http_header( conn_data->buffer, urlbuf, sizeof( urlbuf ) ) ) {
            //syslog( LOG_WARNING, "exread: no url found in http request headers: %s %s",
            //  inet_ntoa( conn_data->addr.sin_addr ), hp ? hp->h_name : "" );
            zs_write( sockfd, html_error_400, sizeof( html_error_400 ) );
            goto cleanup;
        }

        if ( !( website = website_find( urlbuf, conn_data->is_https ? "https://" : "http://",
                                        inet_ntoa( zs_get_addr( conn_data->exlisnfd )->sin_addr ) ) ) ) {
            //syslog( LOG_WARNING, "exread: no website to service request: %s %s %s",
            //  inet_ntoa( conn_data->addr.sin_addr ), hp ? hp->h_name : "", urlbuf );
            zs_write( sockfd, html_error_404, sizeof( html_error_404 ) );
            goto cleanup;
        }

        /* Set the website id so that furthur sections of this
           request can check if the website is still alive. */
        conn_data->website_sockfd = website->sockfd;

        /* Check the websites socket to make sure the request came in on
           the right socket. */
        website_data_t* website_data = website->udata;

        if ( website_data->exlisnfd != conn_data->exlisnfd ) {
            //syslog( LOG_WARNING, "exread: no website to service request: %s %s %s",
            //  inet_ntoa( conn_data->addr.sin_addr ), hp ? hp->h_name : "", urlbuf );
            zs_write( sockfd, html_error_404, sizeof( html_error_404 ) );
            goto cleanup;
        }
        //printf( "%s\n", buffer );

        /* Create a new message to send the request to the corresponding
           website. The msgid should be set to the external file descriptor
           to send the response back to. */
        conn_data->msgid = msg_open( website->sockfd, sockfd );
        zs_set_write( sockfd );

        // If request_type is POST check if there is content after the HTTP header
        char postlenbuf[ 32 ];
        memset( postlenbuf, 0, sizeof( postlenbuf ) );
        if ( conn_data->request_type == HTTP_POST_TYPE && ( ptr = strnstr( conn_data->buffer, "Content-Length: ", PACK_DATA_SIZE ) ) ) {
            char* tmp = strnstr( ptr + 16, HTTP_HDR_ENDL, PACK_DATA_SIZE - ( (long)ptr + 16 - (long)conn_data->buffer ) );
            if ( !tmp ) {
                zs_write( sockfd, html_error_400, sizeof( html_error_400 ) );
                goto cleanup;
            }
            memcpy( postlenbuf, ptr + 16, (long) tmp - (long) ( ptr + 16 ) );
            conn_data->postlen = strtoumax( postlenbuf, NULL, 0 );
            if ( conn_data->postlen < 0 ) {
                zs_write( sockfd, html_error_400, sizeof( html_error_400 ) );
                goto cleanup;
            }
        }

        // Write the message length
        size_t msglen = ( endofhdrs - conn_data->buffer ) + conn_data->postlen + sizeof( conn_data->addr.sin_addr ) + 1;
        if ( hp ) msglen += strlen( hp->h_name );
        if ( msg_write( website->sockfd, conn_data->msgid, (void*) &msglen, sizeof( size_t ) ) == -1 ) {
            zs_write( sockfd, html_error_502, sizeof( html_error_502 ) );
            goto cleanup;
        }

        // Write the ip address and hostname of the request
        if ( msg_write( website->sockfd, conn_data->msgid, (void*) &conn_data->addr.sin_addr, sizeof( conn_data->addr.sin_addr ) ) == -1
                || ( hp && msg_write( website->sockfd, conn_data->msgid, (void*) hp->h_name, strlen( hp->h_name ) ) == -1 )
                || msg_write( website->sockfd, conn_data->msgid, (void*) "\0", 1 ) == -1 ) {
            zs_write( sockfd, html_error_502, sizeof( html_error_502 ) );
            goto cleanup;
        }

        // Send the whole header to the website
        if ( msg_write( website->sockfd, conn_data->msgid, (void*) conn_data->buffer, ( endofhdrs - conn_data->buffer ) ) == -1 ) {
            zs_write( sockfd, html_error_502, sizeof( html_error_502 ) );
            goto cleanup;
        }

        ptr = endofhdrs;
    }

    else {
        if ( !( website = website_get_by_sockfd( conn_data->website_sockfd ) ) ) {
            //	syslog( LOG_WARNING, "exread: no website to service request" );
            zs_write( sockfd, html_error_502, sizeof( html_error_502 ) );
            goto cleanup;
        }
    }

    if ( conn_data->request_type == HTTP_POST_TYPE && conn_data->postlen ) {
        int left = conn_data->bufferlen - ( ptr - (void*)conn_data->buffer );

        if ( left > conn_data->postlen )
            conn_data->postlen = left;

        if ( msg_write( website->sockfd, conn_data->msgid, (void*) ptr, left ) == -1 ) {
            zs_write( sockfd, html_error_502, sizeof( html_error_502 ) );
            goto cleanup;
        }

        conn_data->postlen -= left;
    }

    if ( !conn_data->postlen ) { /* If there isn't more data coming, */
        msg_flush( website->sockfd, conn_data->msgid );

        /* must make sure to keep sockfd in read mode to detect a connection close from
           the other end */
        conn_data->postlen = -1;
        zs_set_read( sockfd );
    } else
        msg_set_write( website->sockfd, conn_data->msgid );

    free( conn_data->buffer );
    conn_data->buffer = NULL;
    //printf( "%d: still needs %d post data\n", sockfd, conn_data->postlen );
}