int platform_network_connect(Network* n, char* hostname, int port) { wiced_ip_address_t ip_address; wiced_result_t rc = -1; int attempt = 1; do { platform_printf("trying to resolve hostname (attempt %d)\n", attempt); if ((rc = wiced_hostname_lookup(hostname, &ip_address, 10000)) == WICED_SUCCESS) { platform_printf("hostname resolved\n"); break; } } while (++attempt <= 5); if (rc != WICED_SUCCESS) { platform_printf("failed to resolve ip address of %s, rc = %d\n", hostname, rc); return rc; } if (n->tls_enabled) wiced_tls_init_simple_context(&n->tls_context, hostname); /* Create a TCP socket */ rc = wiced_tcp_create_socket(&n->socket, WICED_STA_INTERFACE); if (rc != WICED_SUCCESS) { platform_printf("tcp socket creation failed, rc = %d\n", rc); return rc; } if (n->tls_enabled) wiced_tcp_enable_tls(&n->socket, &n->tls_context); rc = wiced_tcp_connect(&n->socket, &ip_address, port, 5000); if (rc != WICED_SUCCESS) { platform_printf("unable to establish connection to %s:%d, rc = %d\n", hostname, port, rc); goto exit; } rc = wiced_tcp_stream_init(&n->stream, &n->socket); if (rc != WICED_SUCCESS) { platform_printf("unable to init tcp stream, rc = %d\n", rc); goto exit; } rc = WICED_SUCCESS; exit: if (rc != WICED_SUCCESS) platform_network_disconnect(n); return rc; }
wiced_result_t xively_create_datastream( xively_feed_t* feed, xively_datastream_t* stream, const char* channel_name, uint32_t data_size, uint32_t number_of_datapoints ) { char content_length_str[ 5 ]; uint16_t content_length = 0; if ( wiced_tcp_stream_init( &stream->tcp_stream, &feed->socket ) != WICED_SUCCESS ) { return WICED_ERROR; } stream->channel_name = channel_name; stream->data_size = data_size; stream->number_of_datapoints = number_of_datapoints; /* Write METHOD and API Endpoint */ WICED_VERIFY( wiced_tcp_stream_write( &stream->tcp_stream, (void*)PUT_START, sizeof( PUT_START ) - 1 ) ); WICED_VERIFY( wiced_tcp_stream_write( &stream->tcp_stream, (void*)feed->id, strlen( feed->id ) ) ); WICED_VERIFY( wiced_tcp_stream_write( &stream->tcp_stream, (void*)PUT_END, sizeof( PUT_END ) - 1 ) ); /* Write Host */ WICED_VERIFY( wiced_tcp_stream_write( &stream->tcp_stream, (void*)HOST_TEMPLATE, sizeof( HOST_TEMPLATE ) - 1 ) ); /* Write API Key */ WICED_VERIFY( wiced_tcp_stream_write( &stream->tcp_stream, (void*)API_KEY_HEADER, sizeof( API_KEY_HEADER ) - 1 ) ); WICED_VERIFY( wiced_tcp_stream_write( &stream->tcp_stream, (void*)feed->api_key, strlen( feed->api_key ) ) ); WICED_VERIFY( wiced_tcp_stream_write( &stream->tcp_stream, (void*)NEWLINE, sizeof( NEWLINE ) - 1 ) ); /* Write data stream content length */ content_length = (uint16_t)( number_of_datapoints * ( strlen( channel_name ) + ( sizeof( COMMA ) - 1 ) + sizeof(wiced_iso8601_time_t) + ( sizeof( COMMA ) - 1 ) + data_size + ( sizeof( NEWLINE ) - 1 ) ) ); memset( content_length_str, 0, sizeof( content_length_str ) ); xively_u16toa( content_length, content_length_str, sizeof( content_length_str ) ); WICED_VERIFY( wiced_tcp_stream_write( &stream->tcp_stream, (void*)CONTENT_LENGTH, sizeof( CONTENT_LENGTH ) - 1 ) ); WICED_VERIFY( wiced_tcp_stream_write( &stream->tcp_stream, (void*)content_length_str, sizeof( content_length_str ) ) ); WICED_VERIFY( wiced_tcp_stream_write( &stream->tcp_stream, (void*)NEWLINE, sizeof( NEWLINE ) - 1 ) ); WICED_VERIFY( wiced_tcp_stream_write( &stream->tcp_stream, (void*)NEWLINE, sizeof( NEWLINE ) - 1 ) ); return WICED_SUCCESS; }
// The nonsecure server thread static void tcp_server_nonsecure_thread_main(wiced_thread_arg_t arg) { wiced_result_t result; wiced_tcp_stream_t stream; // The TCP stream wiced_tcp_socket_t socket; uint8_t rbuffer[MAX_LEGAL_MSG]; char returnMessage[128]; // better use less than 128 bytes // setup the server by creating the socket and hooking it to the correct TCP Port result = wiced_tcp_create_socket(&socket, INTERFACE); if(WICED_SUCCESS != result) { WPRINT_APP_INFO(("Create socket failed\n")); return; // this is a bad outcome } wiced_tcp_stream_init(&stream,&socket); if(WICED_SUCCESS != result) { WPRINT_APP_INFO(("Init stream failed\n")); return; // this is a bad outcome } result = wiced_tcp_listen( &socket, TCP_SERVER_NONSECURE_LISTEN_PORT ); if(WICED_SUCCESS != result) { WPRINT_APP_INFO(("Listen socket failed\n")); return; } while (1 ) { result = wiced_tcp_accept( &socket ); // this halts the thread until there is a connection if(result != WICED_SUCCESS) // this occurs if the accept times out continue; nonsecureConnectionCount += 1; /// Figure out which client is talking to us... and on which port wiced_ip_address_t peerAddress; uint16_t peerPort; wiced_tcp_server_peer(&socket,&peerAddress,&peerPort); uint32_t dataReadCount; wiced_tcp_stream_read_with_count(&stream,&rbuffer,MAX_LEGAL_MSG,100,&dataReadCount); // timeout in 100 ms processClientCommand(rbuffer, dataReadCount ,returnMessage); displayResult(peerAddress,peerPort,returnMessage); // send response and close things up wiced_tcp_stream_write(&stream,returnMessage,strlen(returnMessage)); wiced_tcp_stream_flush(&stream); wiced_tcp_disconnect(&socket); // disconnect the connection wiced_tcp_stream_deinit(&stream); // clear the stream if any crap left wiced_tcp_stream_init(&stream,&socket); // setup for next connection } }
wiced_result_t open_websocket(websocket_handshake_t *hs, websocket_msg_handler_t binary_msg_handler, websocket_msg_handler_t text_msg_handler, void *ctx) { wiced_result_t ret; wiced_ip_address_t host_ip; wiced_tls_context_t tls_ctx; wiced_tcp_socket_t sock; wiced_tcp_stream_t stream; char *buf = NULL; uint32_t i; https_header_t *header; WPRINT_LIB_INFO( ("Starting WebSocket handshake to https://%s%s\n", hs->hostname, hs->path) ); ret = wiced_hostname_lookup(hs->hostname, &host_ip, DNS_TIMEOUT); if (ret != WICED_SUCCESS) { WPRINT_LIB_INFO( ("DNS lookup failed for %s (err=%u)\n", hs->hostname, ret) ); return ret; } wiced_tls_init_context(&tls_ctx, NULL, NULL); wiced_tcp_create_socket(&sock, WICED_STA_INTERFACE); wiced_tcp_enable_tls(&sock, &tls_ctx); { char ip_str[48]; ip_to_str(&host_ip, ip_str); WPRINT_LIB_INFO( ("Establishing TLS connection to %s port %d\n", ip_str, HTTPS_PORT) ); } ret = wiced_tcp_connect(&sock, &host_ip, HTTPS_PORT, HTTPS_CONNECT_TIMEOUT); if (ret != WICED_SUCCESS) { WPRINT_LIB_INFO( ("Failed to create TCP connection (err=%u)\n", ret) ); wiced_tcp_delete_socket(&sock); return ret; } do { ret = wiced_tcp_stream_init(&stream, &sock); if (ret != WICED_SUCCESS) { WPRINT_LIB_INFO( ("Failed to initialize TCP stream (err=%u)\n", ret) ); break; } buf = (char *)malloc(STREAM_BUF_SIZE); snprintf(buf, STREAM_BUF_SIZE, "GET %s HTTP/1.1\r\n", hs->path); WRITE_STREAM(stream, buf, ret); // Required headers. snprintf(buf, STREAM_BUF_SIZE, "Host: %s\r\n" \ "Connection: upgrade\r\n" \ "Upgrade: websocket\r\n" \ "Sec-WebSocket-Key: %s\r\n" \ "Sec-WebSocket-Version: 13\r\n", hs->hostname, hs->key); WRITE_STREAM(stream, buf, ret); // Additional headers. for (i = 0; i < hs->num_headers; i++) { header = &(hs->headers[i]); snprintf(buf, STREAM_BUF_SIZE, "%s: %s\r\n", header->name, header->value); WRITE_STREAM(stream, buf, ret); } if (i < hs->num_headers) { break; } strcpy(buf, "\r\n"); WRITE_STREAM(stream, buf, ret); ret = wiced_tcp_stream_flush(&stream); if (ret != WICED_SUCCESS) { break; } ret = process_handshake_response(hs, &sock); } while (WICED_FALSE); if (buf) { free(buf); } wiced_tcp_stream_deinit(&stream); if (ret == WICED_SUCCESS) { WPRINT_LIB_INFO( ("WebSocket handshake OK\n") ); process_frames(&sock, binary_msg_handler, text_msg_handler, ctx); WPRINT_LIB_INFO( ("Closing WebSocket.\n") ); } else { WPRINT_LIB_INFO( ("WebSocket handshake failed (err=%u)\n", ret) ); } wiced_tcp_disconnect(&sock); wiced_tcp_delete_socket(&sock); return ret; }
wiced_result_t wiced_establish_websocket_handshake( wiced_websocket_t* websocket, wiced_websocket_handshake_fields_t* websocket_header_fields ) { wiced_tcp_stream_t stream; wiced_packet_t* tcp_reply_packet; uint16_t tcp_data_available; uint16_t total_received_bytes; uint8_t* received_handshake; /*Initialise the tcp stream*/ wiced_tcp_stream_init(&stream, &websocket->socket); /*Initialise key array*/ memset(websocket_key_base64,0x0,CLIENT_WEBSOCKET_BASE64_KEY_LENGTH); /*generate a unique websocket key to send to server as part of initial handshake*/ WICED_VERIFY( wiced_generate_client_websocket_key( websocket_key_base64 ) ); /*build the handshaking headers*/ /*< GET /uri HTTP/1.1 >*/ wiced_tcp_stream_write( &stream, "GET ",( uint16_t )strlen("GET ") ); wiced_tcp_stream_write(&stream, websocket_header_fields->request_uri, ( uint16_t )strlen(websocket_header_fields->request_uri) ); wiced_tcp_stream_write( &stream, " HTTP/1.1\r\n",( uint16_t )strlen(" HTTP/1.1\r\n") ); /*< Host: ip1.ip2.ip3.ip4 >*/ wiced_tcp_stream_write( &stream, "Host: ",( uint16_t )strlen("Host: ") ); wiced_tcp_stream_write(&stream, websocket_header_fields->host, ( uint16_t )strlen(websocket_header_fields->host) ); wiced_tcp_stream_write( &stream, "\r\n",( uint16_t )strlen("\r\n") ); /*< Upgrade: websocket>*/ wiced_tcp_stream_write(&stream, "Upgrade: websocket\r\n",( uint16_t )strlen("Upgrade: websocket\r\n") ); /*< Connection: Upgrade >*/ wiced_tcp_stream_write(&stream, "Connection: Upgrade\r\n",( uint16_t )strlen("Connection: Upgrade\r\n") ); /*< Sec-WebSocket-Key: random_base4_value >*/ wiced_tcp_stream_write(&stream, "Sec-WebSocket-Key: ",( uint16_t )strlen("Sec-WebSocket-Key: ") ); wiced_tcp_stream_write(&stream, websocket_key_base64, ( uint16_t )strlen((char*)websocket_key_base64) ); wiced_tcp_stream_write(&stream, "\r\n", ( uint16_t )strlen("\r\n") ); /*< Origin: ip1.ip2.ip3.ip4 >*/ wiced_tcp_stream_write(&stream, "Origin: ", ( uint16_t )strlen("Origin: ") ); wiced_tcp_stream_write(&stream, websocket_header_fields->origin, ( uint16_t )strlen( websocket_header_fields->origin ) ); wiced_tcp_stream_write(&stream, "\r\n",( uint16_t )strlen("\r\n") ); /*The sec_websocket_protocol is optional, so check if it has been added, include in header if required*/ if ( websocket_header_fields->sec_websocket_protocol != NULL) { /*< Sec-WebSocket-Protocol: server_understood_protocol >*/ wiced_tcp_stream_write(&stream, "Sec-WebSocket-Protocol: ",( uint16_t )strlen("Sec-WebSocket-Protocol: ") ); wiced_tcp_stream_write(&stream, websocket_header_fields->sec_websocket_protocol, ( uint16_t )strlen( websocket_header_fields->sec_websocket_protocol ) ); wiced_tcp_stream_write(&stream, "\r\n",( uint16_t )strlen("\r\n") ); } /*< Sec-WebSocket-Version: 13 >*/ wiced_tcp_stream_write(&stream, "Sec-WebSocket-Version: 13\r\n\r\n",strlen("Sec-WebSocket-Version: 13\r\n\r\n") ); /*send the handshake to server*/ wiced_tcp_stream_flush( &stream ); wiced_tcp_stream_deinit( &stream ); WICED_VERIFY( wiced_tcp_receive( &websocket->socket, &tcp_reply_packet, WICED_WAIT_FOREVER ) ); wiced_packet_get_data( tcp_reply_packet, 0, (uint8_t**)&received_handshake, &total_received_bytes, &tcp_data_available ); WICED_VERIFY( wiced_verify_server_handshake( (char*)received_handshake ) ); return WICED_SUCCESS; }
static wiced_result_t process_request( ota_http_request_message_t* request, wiced_tcp_socket_t* socket, const ota_http_page_t* server_url_list ) { /* Search the url to find the question mark if there is one */ int i = 0; wiced_tcp_stream_t stream; wiced_bool_t found = WICED_FALSE; /* Init the tcp stream */ wiced_tcp_stream_init(&stream, socket); /* Search URL list to determine if request matches one of our pages */ while ( server_url_list[i].ota_url != NULL ) { /* Compare request to a path */ if ( 0 == strncmp( server_url_list[i].ota_url, (const char*)request->url_ptr, request->url_length ) ) { /* Matching path found */ found = WICED_TRUE; /* Call the content handler function to write the page content into the packet and adjust the write pointers */ switch (server_url_list[i].ota_url_content_type) { case OTA_DYNAMIC_URL_CONTENT: write_reply_header(&stream, server_url_list[i].ota_mime_type, WICED_TRUE); /* Fall through */ case OTA_RAW_DYNAMIC_URL_CONTENT: server_url_list[i].ota_url_content.ota_dynamic_data.generator( request, &stream, server_url_list[i].ota_url_content.ota_dynamic_data.arg ); wiced_tcp_stream_flush(&stream); break; case OTA_STATIC_URL_CONTENT: write_reply_header(&stream, server_url_list[i].ota_mime_type, WICED_FALSE); /* Fall through */ case OTA_RAW_STATIC_URL_CONTENT: wiced_tcp_stream_write(&stream, server_url_list[i].ota_url_content.ota_static_data.ptr, server_url_list[i].ota_url_content.ota_static_data.length); wiced_tcp_stream_flush(&stream); break; case OTA_RESOURCE_URL_CONTENT: write_reply_header(&stream, server_url_list[i].ota_mime_type, WICED_FALSE); /* Fall through */ case OTA_RAW_RESOURCE_URL_CONTENT: wiced_tcp_stream_write_resource( &stream, server_url_list[i].ota_url_content.ota_resource_data ); wiced_tcp_stream_flush( &stream ); break; default: wiced_assert("Unknown entry in URL list", 0 != 0 ); break; } break; } i++; } /* Check if page was not found */ if ( found == WICED_FALSE ) { /* Send back 404 */ wiced_tcp_stream_write(&stream, not_found_header, sizeof(not_found_header)-1); wiced_tcp_stream_flush(&stream); } wiced_assert( "Page Serve finished with data still in stream", stream.tx_packet == NULL ); return WICED_SUCCESS; }
static void tcp_server_thread_main(wiced_thread_arg_t arg) { wiced_bool_t wwepSecurity = (wiced_bool_t)arg; wiced_result_t result; wiced_tcp_stream_t stream; // The TCP stream wiced_tcp_socket_t socket; platform_dct_security_t *dct_security; wiced_tls_identity_t tls_identity; wiced_tls_context_t tls_context; uint8_t rbuffer[MAX_LEGAL_MSG]; char returnMessage[128]; // better use less than 128 bytes // setup the server by creating the socket and hooking it to the correct TCP Port result = wiced_tcp_create_socket(&socket, INTERFACE); if(WICED_SUCCESS != result) { WPRINT_APP_INFO(("Create socket failed\n")); return; // this is a bad outcome } if(wwepSecurity == WICED_TRUE) { WPRINT_APP_INFO(("Starting secure\n")); } else { WPRINT_APP_INFO(("Starting non-secure\n")); } result = wiced_tcp_listen( &socket, (wwepSecurity == WICED_TRUE)?TCP_SERVER_SECURE_LISTEN_PORT:TCP_SERVER_NONSECURE_LISTEN_PORT ); if(WICED_SUCCESS != result) { WPRINT_APP_INFO(("Listen socket failed\n")); return; } if(wwepSecurity == WICED_TRUE) { /* Lock the DCT to allow us to access the certificate and key */ WPRINT_APP_INFO(( "Read the certificate Key from DCT\n" )); result = wiced_dct_read_lock( (void**) &dct_security, WICED_FALSE, DCT_SECURITY_SECTION, 0, sizeof( *dct_security ) ); if ( result != WICED_SUCCESS ) { WPRINT_APP_INFO(("Unable to lock DCT to read certificate\n")); return; } /* Setup TLS identity */ result = wiced_tls_init_identity( &tls_identity, dct_security->private_key, strlen( dct_security->private_key ), (uint8_t*) dct_security->certificate, strlen( dct_security->certificate ) ); if ( result != WICED_SUCCESS ) { WPRINT_APP_INFO(( "Unable to initialize TLS identity. Error = [%d]\n", result )); return; } } else { wiced_tcp_stream_init(&stream,&socket); if(WICED_SUCCESS != result) { WPRINT_APP_INFO(("Init stream failed\n")); return; // this is a bad outcome } } while (1 ) { if(wwepSecurity == WICED_TRUE) { result = wiced_tls_init_context( &tls_context, &tls_identity, NULL ); if(result != WICED_SUCCESS) { WPRINT_APP_INFO(("Init context failed %d",result)); return; } result = wiced_tcp_enable_tls(&socket,&tls_context); if(result != WICED_SUCCESS) { WPRINT_APP_INFO(("Enabling TLS failed %d",result)); return; } wiced_tcp_stream_init(&stream,&socket); if(WICED_SUCCESS != result) { WPRINT_APP_INFO(("Init stream failed\n")); return; // this is a bad outcome } } result = wiced_tcp_accept( &socket ); // this halts the thread until there is a connection if(result != WICED_SUCCESS) // this occurs if the accept times out continue; if(wwepSecurity == WICED_TRUE) secureConnectionCount += 1; else nonsecureConnectionCount += 1; /// Figure out which client is talking to us... and on which port wiced_ip_address_t peerAddress; uint16_t peerPort; wiced_tcp_server_peer(&socket,&peerAddress,&peerPort); uint32_t dataReadCount; wiced_tcp_stream_read_with_count(&stream,&rbuffer,MAX_LEGAL_MSG,100,&dataReadCount); // timeout in 100 ms processClientCommand(rbuffer, dataReadCount ,returnMessage); displayResult(peerAddress,peerPort,returnMessage); // send response and close things up wiced_tcp_stream_write(&stream,returnMessage,strlen(returnMessage)); wiced_tcp_stream_flush(&stream); wiced_tcp_disconnect(&socket); // disconnect the connection if(wwepSecurity == WICED_TRUE) { wiced_tls_deinit_context(&tls_context); } wiced_tcp_stream_deinit(&stream); // clear the stream if any crap left wiced_tcp_stream_init(&stream,&socket); // setup for next connection } }