layer_state_t posix_asynch_io_layer_on_close( layer_connectivity_t* context )
{
    // prepare return value
    layer_state_t ret = LAYER_STATE_OK;

    //
    posix_asynch_data_t* posix_asynch_data = ( posix_asynch_data_t* ) context->self->user_data;

    if( shutdown( posix_asynch_data->socket_fd, SHUT_RDWR ) == -1 )
    {
        xi_set_err( XI_SOCKET_SHUTDOWN_ERROR );
        close( posix_asynch_data->socket_fd ); // just in case
        ret = LAYER_STATE_ERROR;
        goto err_handling;
    }

    // close the connection & the socket
    if( close( posix_asynch_data->socket_fd ) == -1 )
    {
        xi_set_err( XI_SOCKET_CLOSE_ERROR );
        ret = LAYER_STATE_ERROR;
        goto err_handling;
    }

err_handling:
    // cleanup the memory
    if( posix_asynch_data ) { XI_SAFE_FREE( posix_asynch_data ); }

    return ret;
}
Beispiel #2
0
void test_parse_http(void* data)
{
    (void)(data);

    // prepare structure
    http_response_t response;
    memset( &response, 0, sizeof( http_response_t ) );

    // simplest
    {
        const char test_response[] =
            "HTTP/1.1 200 OK\r\n"
            "Date: Sun, 14 Apr 2013 20:20:01 GMT\r\n"
            "Content-Type: text/plain; charset=utf-8\r\n"
            "Content-Length: 0\r\n"
            "Connection: keep-alive\r\n"
            "X-Request-Id: 9de9ac7071bdbf105804ce0eaf7979adc77f6e25\r\n"
            "Cache-Control: max-age=0\r\n"
            "Vary: Accept-Encoding\r\n\r\n";

        http_response_t* ret = parse_http( &response, test_response );

        tt_assert( ret != 0 );
        tt_assert( ret->http_headers_size == 7 );
    }

    memset( &response, 0, sizeof( http_response_t ) );
    xi_set_err( XI_NO_ERR );

    // with content
    {
        const char test_response[] =
            "HTTP/1.1 404 Not Found\r\n"
            "Date: Sun, 14 Apr 2013 20:20:01 GMT\r\n"
            "Content-Type: text/plain; charset=utf-8\r\n"
            "Content-Length: 9\r\n"
            "Connection: keep-alive\r\n"
            "Vary: Accept-Encoding\r\n\r\n"
            "Not Found";

        http_response_t* ret = parse_http( &response, test_response );

        tt_assert( ret != 0 );
        tt_assert( ret->http_headers_size == 5 );
        tt_assert( strcmp( ret->http_content, "Not Found" ) == 0 );
    }

    memset( &response, 0, sizeof( http_response_t ) );
    xi_set_err( XI_NO_ERR );

    /* Every test-case function needs to finish with an "end:"
       label and (optionally) code to clean up local variables. */
end:
    xi_set_err( XI_NO_ERR );
    ;
}
layer_state_t contiki_io_layer_connect(
	layer_connectivity_t* context
	, const void* data
	, const layer_hint_t hint )
{

 	XI_UNUSED( hint );

	uip_ipaddr_t *ip;
	resolv_status_t dns_status;
    xi_connection_data_t* connection_data;
    layer_t* layer = ( layer_t* ) context->self;
    contiki_data_t* s = (contiki_data_t* ) layer->user_data;
    struct uip_conn *c;

    s->process = PROCESS_CURRENT();
    if (s->state == CONNECTED) {
    	xi_debug_logger( "Connecting to the endpoint [ok]" );
    	return LAYER_STATE_OK;
    } else if (s->state == CONNECTING) {
    	return LAYER_STATE_WANT_WRITE;
    } else if (s->state == CLOSED) {
	    connection_data   = ( xi_connection_data_t* ) data;
	    dns_status = resolv_lookup(connection_data->address, &ip);

	    if (dns_status != RESOLV_STATUS_CACHED) {
	    	if (dns_status ==  RESOLV_STATUS_NOT_FOUND || dns_status == RESOLV_STATUS_ERROR) {
	    		xi_debug_logger( "Getting Host by name [failed]" );
	        	xi_set_err( XI_SOCKET_GETHOSTBYNAME_ERROR );
	        	return LAYER_STATE_ERROR;
	    	}
	    	if (dns_status != RESOLV_STATUS_RESOLVING) {
	    		resolv_query(connection_data->address);
	    	}
	    	return LAYER_STATE_WANT_WRITE;	/* no IP, cannot go further */
	   	}
	   	xi_debug_logger( "Getting Host by name [ok]" );
	    xi_debug_logger( "Connecting to the endpoint..." );

	    c = uip_connect(ip, uip_htons(connection_data->port));
	 	if(c == NULL) {
	        xi_debug_logger( "Connecting to the endpoint [failed]" );
	        xi_set_err( XI_SOCKET_CONNECTION_ERROR );
	        return LAYER_STATE_ERROR;
	    }
	    s->state = CONNECTING;
	    c->appstate.p = &xively_process;
	    c->appstate.state = s;
	    tcpip_poll_tcp(c);
		return LAYER_STATE_WANT_WRITE;
	}

	return LAYER_STATE_ERROR;
}
Beispiel #4
0
void test_csv_encode_datapoint( void* data )
{
    (void)(data);

    // prepare the data
    xi_datapoint_t data_point;
    memset( &data_point, 0, sizeof( xi_datapoint_t ) );

    // data
    // const char datastream_id[] = "test_datastream";

    // test
    {
        data_point.value.i32_value = 216;
        const char* o = csv_encode_datapoint( &data_point );

        // test values
        tt_assert( o != 0 );
        tt_assert( strcmp( o, "216\n" ) == 0 );
    }

    /* Every test-case function needs to finish with an "end:"
       label and (optionally) code to clean up local variables. */
end:
    xi_set_err( XI_NO_ERR );
    ;
}
Beispiel #5
0
void test_csv_decode_datapoint(void *data)
{
    (void)(data);

    // prepare the data
    xi_datapoint_t data_point;
    memset( &data_point, 0, sizeof( xi_datapoint_t ) );

    // data
    const char test_data[] = "2013-01-01T18:44:21.423452Z,216";

    // test
    const xi_datapoint_t* o = csv_decode_datapoint( test_data, &data_point );

    // test
    tt_assert( o != 0 );
    tt_assert( data_point.value.i32_value == 216 );
    tt_assert( data_point.timestamp.micro == 423452 );


    /* Every test-case function needs to finish with an "end:"
       label and (optionally) code to clean up local variables. */
end:
    xi_set_err( XI_NO_ERR );
    ;
}
Beispiel #6
0
void test_http_construct_content(void *data)
{
    (void)(data);

    // simple test
    {
        const char expected[] =
            "Content-Type: text/plain\r\n"
            "Content-Length: 128\r\n";

        const char* ret = http_construct_content( 128 );
        tt_assert( strcmp( expected, ret ) == 0 );
    }

end:
    xi_set_err( XI_NO_ERR );
    ;
}
Beispiel #7
0
void test_create_and_delete_context(void* data)
{
    (void)(data);

#define TEST_API_KEY_STRING "abcXYZ2398138172jckajf39djas_dasd-TyX"
#define TEST_FEED_ID_NUMBER 123456

    xi_context_t* xi_context
        = xi_create_context( XI_HTTP
                             , TEST_API_KEY_STRING
                             , TEST_FEED_ID_NUMBER );

    tt_assert( xi_context != 0 );
    tt_assert( strcmp( xi_context->api_key, TEST_API_KEY_STRING ) == 0 );
    tt_assert( xi_context->feed_id == TEST_FEED_ID_NUMBER );

    xi_delete_context( xi_context );

end:
    xi_set_err( XI_NO_ERR );
    ;
}
Beispiel #8
0
void test_csv_decode_datapoint_error( void * data )
{
    (void)(data);

    // prepare the data
    xi_datapoint_t data_point;
    memset( &data_point, 0, sizeof( xi_datapoint_t ) );

    {   // test case broken data
        // prepare data
        const char test_data[] = "213-01-01T18:44:21.423452Z,216";

        // call function
        const xi_datapoint_t* o = csv_decode_datapoint( test_data, &data_point );

        // test values
        tt_assert( o == 0 );
        tt_assert( XI_CSV_TIME_CONVERTION_ERROR == xi_get_last_error() );
    }

    {   // test case wrong content
        // prepare data
        const char test_data[] = "2013-01-01T18:44:21,216";

        // call function
        const xi_datapoint_t* o = csv_decode_datapoint( test_data, &data_point );

        // test values
        tt_assert( o == 0 );
        tt_assert( XI_CSV_DECODE_DATAPOINT_PARSER_ERROR == xi_get_last_error() );
    }

    /* Every test-case function needs to finish with an "end:"
       label and (optionally) code to clean up local variables. */
end:
    xi_set_err( XI_NO_ERR );
    ;
}
Beispiel #9
0
void test_csv_encode_create_datastream_error( void* data )
{
    (void)(data);

    // prepare the data
    xi_datapoint_t data_point;
    memset( &data_point, 0, sizeof( xi_datapoint_t ) );

    // data
    const char datastream_id[] =
        "abcdefghabcdefghabcdefghabcdefgh" // 32 * 8 + 1 = 257 should exceed the capacity
        "abcdefghabcdefghabcdefghabcdefgh"
        "abcdefghabcdefghabcdefghabcdefgh"
        "abcdefghabcdefghabcdefghabcdefgh"
        "abcdefghabcdefghabcdefghabcdefgh"
        "abcdefghabcdefghabcdefghabcdefgh"
        "abcdefghabcdefghabcdefghabcdefgh"
        "abcdefghabcdefghabcdefghabcdefgh"
        "a"; // 1 additional

    // test
    {
        data_point.value.i32_value = 216;
        const char* o = csv_encode_create_datastream(
                            datastream_id, &data_point );

        // test values
        tt_assert( o == 0 );
        tt_assert( XI_CSV_ENCODE_DATASTREAM_BUFFER_OVERRUN == xi_get_last_error() );
    }

    /* Every test-case function needs to finish with an "end:"
       label and (optionally) code to clean up local variables. */
end:
    xi_set_err( XI_NO_ERR );
    ;
}
Beispiel #10
0
void test_http_construct_request(void *data)
{
    (void)(data);

    // simple test
    {
        const char expected[] =
            "GET /v2/feeds/128/datastreams/test.csv HTTP/1.1\r\n"
            "Host: " XI_HOST "\r\n"
            "User-Agent: " XI_USER_AGENT "\r\n"
            "Accept: */*\r\n"
            "X-ApiKey: apikey\r\n";

        xi_feed_id_t feed_id = 128;
        const char* ret = http_construct_request_datastream( "GET", &feed_id, "test", "apikey" );
        tt_assert( strcmp( expected, ret ) == 0 );
    }

    // simple test2
    {
        const char expected[] =
            "GET /v2/feeds/128/datastreams.csv HTTP/1.1\r\n"
            "Host: " XI_HOST "\r\n"
            "User-Agent: " XI_USER_AGENT "\r\n"
            "Accept: */*\r\n"
            "X-ApiKey: apikey\r\n";

        xi_feed_id_t feed_id = 128;
        const char* ret = http_construct_request_datastream( "GET", &feed_id, 0, "apikey" );
        tt_assert( strcmp( expected, ret ) == 0 );
    }

end:
    xi_set_err( XI_NO_ERR );
    ;
}
Beispiel #11
0
void test_parse_http_status(void* data)
{
    (void)(data);

    // prepare structure
    http_response_t response;
    memset( &response, 0, sizeof( http_response_t ) );

    // simplest
    {
        const char test_status1[] =
            "HTTP/1.1 200 OK\r\n"
            "Date: Sun, 14 Apr 2013 19:32:40 GMT\r\n";

        const char* ret = parse_http_status( &response, test_status1 );

        tt_assert( ret != 0 );
        tt_assert( response.http_version1 == 1 );
        tt_assert( response.http_version2 == 1 );
        tt_assert( response.http_status == 200 );
        tt_assert( strcmp( response.http_status_string, "OK" ) == 0 );
        tt_assert( ret == test_status1 + 17 );

    }

    // simplest2
    {
        const char test_status1[] =
            "HTTP/1.1 404 Not Found\r\n"
            "Date: Sun, 14 Apr 2013 19:32:40 GMT\r\n";

        const char* ret = parse_http_status( &response, test_status1 );

        tt_assert( ret != 0 );
        tt_assert( response.http_version1 == 1 );
        tt_assert( response.http_version2 == 1 );
        tt_assert( response.http_status == 404 );
        tt_assert( strcmp( response.http_status_string, "Not Found" ) == 0 );
        tt_assert( ret == test_status1 + 24 );
    }


    // clean
    memset( &response, 0, sizeof( http_response_t ) );

    // malformed
    {
        const char test_status1[] =
            "HTTP1.1 200 OK\r\n"
            "Date: Sun, 14 Apr 2013 19:32:40 GMT\r\n";

        const char* ret = parse_http_status( &response, test_status1 );

        tt_assert( ret == 0 );
        tt_assert( xi_get_last_error() == XI_HTTP_STATUS_PARSE_ERROR );
    }

    // clean
    xi_set_err( XI_NO_ERR );
    memset( &response, 0, sizeof( http_response_t ) );

    // malformed2
    {
        const char test_status1[] =
            "HTTP1.1 200 OK";

        const char* ret = parse_http_status( &response, test_status1 );

        tt_assert( ret == 0 );
        tt_assert( xi_get_last_error() == XI_HTTP_STATUS_PARSE_ERROR );
    }

    /* Every test-case function needs to finish with an "end:"
       label and (optionally) code to clean up local variables. */
end:
    xi_set_err( XI_NO_ERR );
    ;
}
Beispiel #12
0
void test_parse_http_header(void *data)
{
    (void)(data);

    // prepare structure
    http_response_t response;
    memset( &response, 0, sizeof( http_response_t ) );

    // simplest
    {
        const char test_header1[] =
            "Date: Sun, 14 Apr 2013 19:32:40 GMT\r\n";

        const char* ret = parse_http_header( &response, test_header1 );

        tt_assert( ret != 0 );
        tt_assert( response.http_headers_size == 1 );
        tt_assert( response.http_headers[ 0 ].header_type == XI_HTTP_HEADER_DATE );
        tt_assert( strcmp( response.http_headers[ 0 ].name, "Date" ) == 0 );
        tt_assert( strcmp( response.http_headers[ 0 ].value, "Sun, 14 Apr 2013 19:32:40 GMT" ) == 0 );
        tt_assert( response.http_headers_checklist[ ( size_t ) XI_HTTP_HEADER_DATE ] == &response.http_headers[ 0 ] );
    }

    memset( &response, 0, sizeof( http_response_t ) );
    xi_set_err( XI_NO_ERR );

    // simplest2
    {
        const char test_header1[] =
            "Content-Length: 0\r\n";

        const char* ret = parse_http_header( &response, test_header1 );

        tt_assert( ret != 0 );
        tt_assert( response.http_headers_size == 1 );
        tt_assert( response.http_headers[ 0 ].header_type == XI_HTTP_HEADER_CONTENT_LENGTH );
        tt_assert( strcmp( response.http_headers[ 0 ].name, "Content-Length" ) == 0 );
        tt_assert( strcmp( response.http_headers[ 0 ].value, "0" ) == 0 );
        tt_assert( response.http_headers_checklist[ ( size_t ) XI_HTTP_HEADER_CONTENT_LENGTH ] == &response.http_headers[ 0 ] );
    }

    memset( &response, 0, sizeof( http_response_t ) );
    xi_set_err( XI_NO_ERR );

    // simplest3
    {
        const char test_header1[] =
            "Imaginary-Header: 0\r\n";

        const char* ret = parse_http_header( &response, test_header1 );

        tt_assert( ret != 0 );
        tt_assert( response.http_headers_size == 1 );
        tt_assert( response.http_headers[ 0 ].header_type == XI_HTTP_HEADER_UNKNOWN );
        tt_assert( strcmp( response.http_headers[ 0 ].name, "Imaginary-Header" ) == 0 );
        tt_assert( strcmp( response.http_headers[ 0 ].value, "0" ) == 0 );
    }

    memset( &response, 0, sizeof( http_response_t ) );
    xi_set_err( XI_NO_ERR );

    // malformed
    {
        const char test_header1[] =
            "Date Sun, 14 Apr 2013 19-32-40 GMT\r\n";

        const char* ret = parse_http_header( &response, test_header1 );

        tt_assert( ret == 0 );
        tt_assert( xi_get_last_error() == XI_HTTP_HEADER_PARSE_ERROR );
    }

    memset( &response, 0, sizeof( http_response_t ) );
    xi_set_err( XI_NO_ERR );

    // malformed
    {
        const char test_header1[] =
            "Date: Sun, 14 Apr 2013 19:32:40 GMT";

        const char* ret = parse_http_header( &response, test_header1 );

        tt_assert( ret == 0 );
        tt_assert( xi_get_last_error() == XI_HTTP_HEADER_PARSE_ERROR );
    }

    /* Every test-case function needs to finish with an "end:"
       label and (optionally) code to clean up local variables. */
end:
    xi_set_err( XI_NO_ERR );
    ;
}
layer_state_t posix_asynch_io_layer_connect(
      layer_connectivity_t* context
    , const void* data
    , const layer_hint_t hint )
{
    XI_UNUSED( hint );

    static uint16_t cs = 0; // local coroutine prereserved state

    xi_connection_data_t* connection_data   = ( xi_connection_data_t* ) data;
    layer_t* layer                          = ( layer_t* ) context->self;
    posix_asynch_data_t* posix_asynch_data  = ( posix_asynch_data_t* ) layer->user_data;

    BEGIN_CORO( cs )

    xi_debug_format( "Connecting layer [%d] to the endpoint", layer->layer_type_id );

    // socket specific data
    struct sockaddr_in name;
    struct hostent* hostinfo;

    // get the hostaddress
    hostinfo = gethostbyname( connection_data->address );

    // if null it means that the address has not been founded
    if( hostinfo == NULL )
    {
        xi_debug_logger( "Getting Host by name [failed]" );
        xi_set_err( XI_SOCKET_GETHOSTBYNAME_ERROR );
        goto err_handling;
    }

    xi_debug_logger( "Getting Host by name [ok]" );

    // set the address and the port for further connection attempt
    memset( &name, 0, sizeof( struct sockaddr_in ) );
    name.sin_family     = AF_INET;
    name.sin_addr       = *( ( struct in_addr* ) hostinfo->h_addr );
    name.sin_port       = htons( connection_data->port );

    xi_debug_logger( "Connecting to the endpoint..." );

    if( connect( posix_asynch_data->socket_fd, ( struct sockaddr* ) &name, sizeof( struct sockaddr ) ) == -1 )
    {
        if( errno != EINPROGRESS )
        {
            xi_debug_printf( "errno: %d", errno );
            xi_debug_logger( "Connecting to the endpoint [failed]" );
            xi_set_err( XI_SOCKET_CONNECTION_ERROR );
            goto err_handling;
        }
        else
        {
            YIELD( cs, LAYER_STATE_WANT_WRITE ); // return here whenever we can write
        }
    }

    EXIT( cs, LAYER_STATE_OK );

err_handling:
    // cleanup the memory
    if( posix_asynch_data )     { close( posix_asynch_data->socket_fd ); }
    if( layer->user_data )      { XI_SAFE_FREE( layer->user_data ); }

    EXIT( cs, LAYER_STATE_ERROR );

    END_CORO()
}
layer_state_t posix_asynch_io_layer_init(
      layer_connectivity_t* context
    , const void* data
    , const layer_hint_t hint )
{
    XI_UNUSED( hint );
    XI_UNUSED( data );

    // PRECONDITIONS
    assert( context != 0 );

    xi_debug_logger( "[posix_io_layer_init]" );

    layer_t* layer                              = ( layer_t* ) context->self;
    posix_asynch_data_t* posix_asynch_data      = xi_alloc( sizeof( posix_asynch_data_t ) );

    XI_CHECK_MEMORY( posix_asynch_data );

    layer->user_data                            = ( void* ) posix_asynch_data;

    xi_debug_logger( "Creating socket..." );

    posix_asynch_data->socket_fd                = socket( AF_INET, SOCK_STREAM, 0 );

    if( posix_asynch_data->socket_fd == -1 )
    {
        xi_debug_logger( "Socket creation [failed]" );
        xi_set_err( XI_SOCKET_INITIALIZATION_ERROR );
        return 0;
    }

    xi_debug_logger( "Setting socket non blocking behaviour..." );

    int flags = fcntl( posix_asynch_data->socket_fd, F_GETFL, 0 );

    if( flags == -1 )
    {
        xi_debug_logger( "Socket non blocking behaviour [failed]" );
        xi_set_err( XI_SOCKET_INITIALIZATION_ERROR );
        goto err_handling;
    }

    if( fcntl( posix_asynch_data->socket_fd, F_SETFL, flags | O_NONBLOCK ) == -1 )
    {
        xi_debug_logger( "Socket non blocking behaviour [failed]" );
        xi_set_err( XI_SOCKET_INITIALIZATION_ERROR );
        goto err_handling;
    }

    xi_debug_logger( "Socket creation [ok]" );

    // POSTCONDITIONS
    assert( layer->user_data != 0 );
    assert( posix_asynch_data->socket_fd != -1 );

    return LAYER_STATE_OK;

err_handling:
    // cleanup the memory
    if( posix_asynch_data )     { close( posix_asynch_data->socket_fd ); }
    if( layer->user_data )      { XI_SAFE_FREE( layer->user_data ); }

    return LAYER_STATE_ERROR;
}