This chapter contains a description of various issues related to installation, setup, and usage of the NetX Duo Web HTTP component.
HTTP for NetX Duo is available at https://github.com/eclipse-threadx/netxduo. The package includes three source files, two include files, and a file that contains this document, as follows:
In order to use NetX Duo Web HTTP, the entire distribution mentioned previously should be copied to the same directory where NetX Duo is installed. For example, if NetX Duo is installed in the directory “\threadx\arm7\green” then the nx_web_http_client.h and nx_web_http_client.c for NetX Duo Web HTTP Client applications, and nx_web_http_server.h, nx_web_http_server.c, nx_tcpserver.c and nx_tcpserver.h for NetX Duo Web HTTP Server applications. For both client and server applications, nx_web_http_common.h must be in this directory as well. nx_md5.c should also be copied into this directory if digest authentication is being used. For the demo ‘ram driver’ application HTTP Client and Server files should be copied into the same directory.
If using TLS, you should have a separate NetX Duo Secure directory containing the TLS source files.
Using NetX Duo Web HTTP is easy. Basically, the application code must include nx_web_http_client.h and/or nx_web_http_server.h after it includes tx_api.h, fx_api.h, and nx_api.h (nx_web_http_common.h is automatically included). Those headers enable the application to use ThreadX, FileX, and NetX Duo, respectively. For HTTPS support, the headers must be included after the nx_secure_tls.h file is included to bring in TLS support.
Once the HTTP header files are included, the application code is then able to make the HTTP function calls specified later in this guide. The application must also link with nx_web_http_client.c for HTTP(S) clients, nx_web_http_server.c and nx_tcpserver.c for HTTP(S) servers, and nx_md5.c (for digest authentication) in the build process. These files must be compiled in the same manner as other application files and its object form must be linked along with the files of the application. This is all that is required to use NetX Duo Web HTTP.
Note: If NX_WEB_HTTP_DIGEST_ENABLE is not specified in the build process, the md5.c file does not need to be added to the application. Similarly, if no HTTP Client capabilities are required, the nx_web_http_client.c file may be omitted and if no HTTP Server capabilities are required, nx_web_http_server.c may be omitted.
Unless NX_WEB_HTTPS_ENABLE is defined in order to enable HTTPS (instead of using only plaintext HTTP) then NetX Duo Secure TLS does not need to be in the build.
Since HTTP utilizes NetX Duo TCP services, TCP must be enabled with the nx_tcp_enable() call prior to using HTTP.
When using HTTPS with NetX Duo Secure TLS, TLS must be initialized with nx_secure_tls_initialize() prior to calling HTTPS routines.
An example of how to use NetX Duo Web HTTP is described below.
Caution: This is provided for demonstration purposes only and is not guaranteed to compile and run as is.
Please refer to the NetX Duo HTTPS release code distribution for demo source code file(s) that will properly build in the native Express Logic environment. Also be aware that these demos are intentionally kept very simple as they are intended to introduce HTTPS and/or NetX Duo HTTPS application to new users.
In this example, the HTTP include file nx_web_http_client.h and nx_web_http_server.h are brought in (netx_web_http_common.h is included automatically). Next, the HTTP Server is created in “tx_application_define”. Note that the HTTP Server control block “Server” was defined as a global variable previously. After successful creation, the HTTPS Server is started. The HTTPS Client is then created. It writes the file and reads the file back.
Note: NX_WEB_HTTPS_ENABLE is defined on this system.
/* This is a small demo of HTTPS on the high-performance NetX Duo TCP/IP stack.
This demo relies on ThreadX, NetX Duo, and FileX to show an HTML
transfer from the client and then back from the server. */
#include "tx_api.h"
#include "fx_api.h"
#include "nx_api.h"
#include "nx_crypto.h"
#include "nx_secure_tls_api.h"
#include "nx_secure_x509.h"
#include "nx_web_http_client.h"
#include "nx_web_http_server.h"
#define DEMO_STACK_SIZE 4096
/* Define the ThreadX and NetX object control blocks... */
TX_THREAD thread_0;
TX_THREAD thread_1;
NX_PACKET_POOL pool_0;
NX_PACKET_POOL pool_1;
NX_IP ip_0;
NX_IP ip_1;
FX_MEDIA ram_disk;
/* Define HTTP objects. */
NX_WEB_HTTP_SERVER my_server;
NX_WEB_HTTP_CLIENT my_client;
/* Define the counters used in the demo application... */
ULONG error_counter;
/* Define the RAM disk memory. */
UCHAR ram_disk_memory[32000];
/* Include cryptographic routines for TLS. */
extern const NX_SECURE_TLS_CRYPTO nx_crypto_tls_ciphers;
/* Define TLS data for HTTPS. */
CHAR crypto_metadata[8928 * NX_WEB_HTTP_SESSION_MAX];
UCHAR tls_packet_buffer[16500];
/* NX_WEB_HTTP_SERVER_SESSION_MAX defaults to 2 in nx_web_http_server.h */
UCHAR server_tls_packet_buffer[16500 * NX_WEB_HTTP_SERVER_SESSION_MAX];
/* Define certificate containers. The server certificate is used to identify the NetX
Web HTTPS server and the trusted certificate is used by the client to verify the
server's identity certificate. */
NX_SECURE_X509_CERT server_certificate;
NX_SECURE_X509_CERT trusted_certificate;
/* Remote certificates need both an NX_SECURE_X509_CERT container and an associated
buffer. The number of certificates depends on the remote host, but usually at least
two certificates will be sent – the identity certificate for the host and the
certificate that issued the identity certificate. */
NX_SECURE_X509_CERT remote_certificate, remote_issuer;
UCHAR remote_cert_buffer[2000];
UCHAR remote_issuer_buffer[2000];
/* Certificate information for server and client (see NetX Duo Secure TLS reference on X.509
certificates for more information). Arrays are populated with binary versions Of
certificates and keys and the corresponding "len" variables are assigned the lengths
of that data. Trusted certificates do not need a private key. */
const UCHAR server_cert_der[] = { … };
const UINT server_cert_derlen = … ;
const UCHAR server_cert_key_der[] = { … };
const UINT server_cert_key_derlen = … ;
const UCHAR trusted_cert_der[] = { … };
const UINT trusted_cert_derlen = … ;
/* Define function prototypes. */
void thread_0_entry(ULONG thread_input);
VOID _fx_ram_driver(FX_MEDIA *media_ptr) ;
void _nx_ram_network_driver(struct NX_IP_DRIVER_STRUCT *driver_req);
UINT authentication_check(NX_WEB_HTTP_SERVER *server_ptr, UINT request_type,
CHAR *resource, CHAR **name, CHAR **password, CHAR **realm);
UINT tls_setup_callback(NX_WEB_HTTP_CLIENT *client_ptr,
NX_SECURE_TLS_SESSION *tls_session);
/* Define the application's authentication check. This is called by
the HTTP server whenever a new request is received. */
UINT authentication_check(NX_WEB_HTTP_SERVER *server_ptr, UINT request_type,
CHAR *resource, CHAR **name, CHAR **password, CHAR **realm)
{
/* Just use a simple name, password, and realm for all
requests and resources. */
*name = "name";
*password = "password";
*realm = "NetX Web HTTP demo";
/* Request basic authentication. */
return(NX_WEB_HTTP_BASIC_AUTHENTICATE);
}
/* Define the TLS setup callback for HTTPS Client. This function is invoked when the
HTTPS client is started – all TLS per-session initialization should go in here. */
UINT tls_setup_callback(NX_WEB_HTTP_CLIENT *client_ptr,
NX_SECURE_TLS_SESSION *tls_session)
{
UINT status;
/* Initialize and create TLS session. */
nx_secure_tls_session_create(tls_session, &nx_crypto_tls_ciphers,
crypto_metadata, sizeof(crypto_metadata));
/* Allocate space for packet reassembly. */
nx_secure_tls_session_packet_buffer_set(tls_session, tls_packet_buffer,
sizeof(tls_packet_buffer));
/* Add a CA Certificate to our trusted store for verifying incoming server
certificates. */
nx_secure_x509_certificate_initialize(&trusted_certificate, trusted_cert_der,
trusted_cert_der_len, NX_NULL, 0, NULL, 0,
NX_SECURE_X509_KEY_TYPE_NONE);
nx_secure_tls_trusted_certificate_add(tls_session, &trusted_certificate);
/* Need to allocate space for the certificate coming in from the remote host. */
nx_secure_tls_remote_certificate_allocate(tls_session, &remote_certificate,
remote_cert_buffer, sizeof(remote_cert_buffer));
nx_secure_tls_remote_certificate_allocate(tls_session,
&remote_issuer, remote_issuer_buffer,
sizeof(remote_issuer_buffer));
return(NX_SUCCESS);
}
/* Define main entry point. */
int main()
{
/* Enter the ThreadX kernel. */
tx_kernel_enter();
}
/* Define what the initial system looks like. */
void tx_application_define(void *first_unused_memory)
{
CHAR *pointer;
/* Setup the working pointer. */
pointer = (CHAR *) first_unused_memory;
/* Create the main thread. */
tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,
pointer, DEMO_STACK_SIZE,
2, 2, TX_NO_TIME_SLICE, TX_AUTO_START);
pointer = pointer + DEMO_STACK_SIZE;
/* Initialize the NetX system. */
nx_system_initialize();
/* Create packet pool. */
nx_packet_pool_create(&pool_0, "NetX Packet Pool 0",
600, pointer, 8192);
pointer = pointer + 8192;
/* Create an IP instance. */
nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(1, 2, 3, 4),
0xFFFFFF00UL, &pool_0, _nx_ram_network_driver,
pointer, 4096, 1);
pointer = pointer + 4096;
/* Create another packet pool. */
nx_packet_pool_create(&pool_1, "NetX Packet Pool 1", 600, pointer, 8192);
pointer = pointer + 8192;
/* Create another IP instance. */
nx_ip_create(&ip_1, "NetX IP Instance 1", IP_ADDRESS(1, 2, 3, 5),
0xFFFFFF00UL, &pool_1, _nx_ram_network_driver,
pointer, 4096, 1);
pointer = pointer + 4096;
/* Enable ARP and supply ARP cache memory for IP Instance 0. */
nx_arp_enable(&ip_0, (void *) pointer, 1024);
pointer = pointer + 1024;
/* Enable ARP and supply ARP cache memory for IP Instance 1. */
nx_arp_enable(&ip_1, (void *) pointer, 1024);
pointer = pointer + 1024;
/* Enable TCP processing for both IP instances. */
nx_tcp_enable(&ip_0);
nx_tcp_enable(&ip_1);
/* Open the RAM disk. */
fx_media_open(&ram_disk, "RAM DISK",
_fx_ram_driver, ram_disk_memory, pointer, 4096);
pointer += 4096;
/* Create the NetX Web HTTP Server. */
nx_web_http_server_create(&my_server, "My HTTP Server", &ip_1,
NX_WEB_HTTPS_SERVER_PORT, &ram_disk,
pointer, 4096, &pool_1, authentication_check, NX_NULL);
pointer = pointer + 4096;
/* The TLS server needs an identity certificate which is imported as a binary DER-
encoded X.509 certificate and its associated private key (e.g. DER-encoded PKCS#1
RSA private key). */
nx_secure_x509_certificate_initialize(&server_certificate, server_cert_der,
server_cert_der_len, NX_NULL, 0,
server_cert_key_der, server_cert_key_der_len,
NX_SECURE_X509_KEY_TYPE_RSA_PKCS1_DER);
/* Setup TLS session data for the TCP server.
This enables TLS and HTTPS for the server. */
nx_web_http_server_secure_configure(&my_server, &nx_crypto_tls_ciphers,
crypto_metadata, sizeof(crypto_metadata), server_tls_packet_buffer,
sizeof(server_tls_packet_buffer), &server_certificate, NX_NULL, 0,
NX_NULL, 0, NX_NULL, 0);
/* Start the HTTP Server. */
nx_web_http_server_start(&my_server);
}
/* Define the test thread. */
void thread_0_entry(ULONG thread_input)
{
NX_PACKET *my_packet;
UINT status;
/* Create an HTTP client instance. */
status = nx_web_http_client_create(&my_client, "My Client", &ip_0, &pool_0, 600);
/* Check status. */
if (status)
error_counter++;
/* Prepare to send the simple 103-byte HTML file to the Server over HTTPS. */
status = nx_web_http_client_put_secure_start(&my_client, IP_ADDRESS(1,2,3,5),
NX_WEB_HTTPS_SERVER_PORT, "/test.htm", "name", "password", 103, tls_setup_callback, 50);
/* Check status. */
if (status)
error_counter++;
/* Allocate a packet. */
status = nx_web_http_client_request_packet_allocate(&pool_0, &my_packet,
NX_TCP_PACKET, NX_WAIT_FOREVER);
/* Check status. */
if (status != NX_SUCCESS)
return;
/* Build a simple 103-byte HTML page. */
nx_packet_data_append(my_packet, "<HTML>\r\n", 8,
&pool_0, NX_WAIT_FOREVER);
nx_packet_data_append(my_packet,
"<HEAD><TITLE>NetX HTTP Test</TITLE></HEAD>\r\n", 44,
&pool_0, NX_WAIT_FOREVER);
nx_packet_data_append(my_packet, "<BODY>\r\n", 8,
&pool_0, NX_WAIT_FOREVER);
nx_packet_data_append(my_packet, "<H1>NetX Test Page</H1>\r\n", 25,
&pool_0, NX_WAIT_FOREVER);
nx_packet_data_append(my_packet, "</BODY>\r\n", 9,
&pool_0, NX_WAIT_FOREVER);
nx_packet_data_append(my_packet, "</HTML>\r\n", 9,
&pool_0, NX_WAIT_FOREVER);
/* Complete the PUT by writing the total length. */
status = nx_web_http_client_put_packet(&my_client, my_packet, 50);
/* Check status. */
if (status)
error_counter++;
/* Now GET the file back! */
status = nx_web_http_client_get_secure_start(&my_client, IP_ADDRESS(1,2,3,5),
NX_WEB_HTTPS_SERVER_PORT, "/test.htm",
"name", "password", tls_setup_callback, 50);
/* Check status. */
if (status)
error_counter++;
/* Get a packet. */
status = nx_web_http_client_response_body_get(&my_client, &my_packet, 20);
/* Check for an error. */
if ((status) || (my_packet -> nx_packet_length != 103))
error_counter++;
/* Check to see if we have a packet. */
if (status == NX_SUCCESS)
{
/* Yes, release it! */
nx_packet_release(my_packet);
}
/* Make sure TLS shuts down properly. */
nx_web_http_client_delete(&my_client);
/* Flush the media. */
fx_media_flush(&ram_disk);
}
There are several configuration options for building HTTP for NetX Duo. Following is a list of all options, where each is described in detail. The default values are listed but can be redefined prior to inclusion of nx_web_http_client.h and nx_web_http_server.h: