Chapter 2 - Installation and use of NetX HTTP

This chapter contains a description of various issues related to installation, setup, and usage of the NetX HTTP component.

Product Distribution

Azure RTOS NetX can be obtained from our public source code repository at https://github.com/azure-rtos/netx.

  • nx_http_client.h Header file for HTTP Client for NetX
  • nx_http_server.h Header file for HTTP Server for NetX
  • nx_http_client.c C Source file for HTTP Client for NetX
  • nx_http_server.c C Source file for HTTP Server for NetX
  • nx_md5.c MD5 digest algorithms
  • filex_stub.h Stub file if FileX is not present
  • nx_http.pdf Description of HTTP for NetX
  • demo_netx_http.c NetX HTTP demonstration

HTTP Installation

In order to use HTTP for NetX, the entire distribution mentioned previously should be copied to the same directory where NetX is installed. For example, if NetX is installed in the directory “\threadx\arm7\green” then the nx_http_client.h and nx_http_client.c for NetX HTTP Client applications, and nx_http_server.h and nx_http_server.c for NetX HTTP Server applications. nx_md5.c should be copied into this directory. For the demo ‘ram driver’ application NetX HTTP Client and Server files should be copied into the same directory.

Using HTTP

Using HTTP for NetX is easy. Basically, the application code must include nx_http_client.h and/or nx_http_server.h after it includes tx_api.h, fx_api.h, and nx_api.h, in order to use ThreadX, FileX, and NetX, respectively. 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 include nx_http_client.c, nx_http_server.c, and md5.c 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 HTTP.

Note

If NX_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_http_client.c file may be omitted.

Note

Since HTTP utilizes NetX TCP services, TCP must be enabled with the nx_tcp_enable call prior to using HTTP.

Small Example System

An example of how easy it is to use NetX HTTP is described in Figure 1.1 that appears below. In this example, the HTTP include file nx_http_client.h and nx_http_server.h are brought in at line 8. Next, the HTTP Server is created in “tx_application_define” at line 131.

Note

The HTTP Server control block “Server” was defined as a global variable at line 25 previously.

After successful creation, an HTTP Server is started at line 136. At line 149 the HTTP Client is created. And finally, the Client writes the file at line 157 and reads the file back at line 195.

/* This is a small demo of HTTP on the high-performance NetX TCP/IP stack.
This demo relies on ThreadX, NetX, and FileX to show a simple 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_http_client.h"
#include "nx_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_HTTP_SERVER    my_server;
NX_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];

/* 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_HTTP_SERVER *server_ptr, UINT request_type,
                              CHAR *resource, CHAR **name, CHAR **password, 
                              CHAR **realm);

/* Define the application's authentication check. This is called by
the HTTP server whenever a new request is received. */
UINT authentication_check(NX_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 HTTP demo";

    /* Request basic authentication. */
    return(NX_HTTP_BASIC_AUTHENTICATE);
}

/* 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_ram_driver, ram_disk_memory, pointer, 4096) ;
                 pointer += 4096;

    /* Create the NetX HTTP Server. */
    nx_http_server_create(&my_server, "My HTTP Server", &ip_1, &ram_disk,
                         pointer, 4096, &pool_1, authentication_check, NX_NULL);
                         pointer = pointer + 4096;

    /* Start the HTTP Server. */
    nx_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_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. */
    status = nx_http_client_put_start(&my_client, IP_ADDRESS(1,2,3,5),
                                      "/test.htm", "name", "password", 103, 50);
    /* Check status. */
    if (status)
        error_counter++;

    /* Allocate a packet. */
    status = nx_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_http_client_put_packet**(&my_client, my_packet, 50);

    /* Check status. */
    if (status)
        error_counter++;

    /* Now GET the file back! */
    status = nx_http_client_get_start(&my_client, IP_ADDRESS(1,2,3,5),
                                     "/test.htm", NX_NULL, 0, "name", 
                                     "password", 50);

    /* Check status. */
    if (status)
        error_counter++;

    /* Get a packet. */
    status = nx_http_client_get_packet(&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);
    }

    /* Flush the media. */
     fx_media_flush(&ram_disk);
 }

Figure 1.1 Example of HTTP use with NetX

Configuration Options

There are several configuration options for building HTTP for NetX. 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_http_client.h and nx_http_server.h:

  • NX_DISABLE_ERROR_CHECKING Defined, this option removes the basic HTTP error checking. It is typically used after the application has been debugged.
  • NX_HTTP_SERVER_PRIORITY The priority of the HTTP Server thread. By default, this value is defined as 16 to specify priority 16.
  • NX_HTTP_NO_FILEX Defined, this option provides a stub for FileX dependencies. The HTTP Client will function without any change if this option is defined. The HTTP Server will need to either be modified or the user will have to create a handful of FileX services in order to function properly.
  • NX_HTTP_TYPE_OF_SERVICE Type of service required for the HTTP TCP requests. By default, this value is defined as NX_IP_NORMAL to indicate normal IP packet service.
  • NX_HTTP_SERVER_THREAD_TIME_SLICE The number of timer ticks the Server thread is allowed to run before yielding to threads of the same priority. The default value is 2.
  • NX_HTTP_FRAGMENT_OPTION Fragment enable for HTTP TCP requests. By default, this value is NX_DONT_FRAGMENT to disable HTTP TCP fragmenting.
  • NX_HTTP_SERVER_WINDOW_SIZE Server socket window size. By default, this value is 2048 bytes.
  • NX_HTTP_TIME_TO_LIVE Specifies the number of routers this packet can pass before it is discarded. The default value is set to 0x80.
  • NX_HTTP_SERVER_TIMEOUT Specifies the number of ThreadX ticks that internal services will suspend for. The default value is set to 10 seconds (10 * NX_IP_PERIODIC_RATE).
  • NX_HTTP_SERVER_TIMEOUT_ACCEPT Specifies the number of ThreadX ticks that internal services will suspend for in internal nx_tcp_server_socket_accept calls. The default value is set to (10 * NX_IP_PERIODIC_RATE).
  • NX_HTTP_SERVER_TIMEOUT_DISCONNECT Specifies the number of ThreadX ticks that internal services will suspend for in internal nx_tcp_socket_disconnect calls. The default value is set to 10 seconds (10 * NX_IP_PERIODIC_RATE).
  • NX_HTTP_SERVER_TIMEOUT_RECEIVE Specifies the number of ThreadX ticks that internal services will suspend for in internal nx_tcp_socket_receive calls. The default value is set to 10 seconds (10 * NX_IP_PERIODIC_RATE).
  • NX_HTTP_SERVER_TIMEOUT_SEND Specifies the number of ThreadX ticks that internal services will suspend for in internal nx_tcp_socket_send calls. The default value is set to 10 seconds (10 * NX_IP_PERIODIC_RATE).
  • NX_HTTP_MAX_HEADER_FIELD Specifies the maximum size of the HTTP header field. The default value is 256.
  • NX_HTTP_MULTIPART_ENABLE If defined, enables HTTP Server to support multipart HTTP requests.
  • NX_HTTP_SERVER_MAX_PENDING Specifies the number of connections that can be queued for the HTTP Server. The default value is set to 5.
  • NX_HTTP_MAX_RESOURCE Specifies the number of bytes allowed in a client supplied resource name. The default value is set to 40.
  • NX_HTTP_MAX_NAME Specifies the number of bytes allowed in a client supplied username. The default value is set to 20.
  • NX_HTTP_MAX_PASSWORD Specifies the number of bytes allowed in a client supplied password. The default value is set to 20.
  • NX_HTTP_SERVER_MIN_PACKET_SIZE Specifies the minimum size of the packets in the pool specified at Server creation. The minimum size is needed to ensure the complete HTTP header can be contained in one packet. The default value is set to 600.
  • NX_HTTP_CLIENT_MIN_PACKET_SIZE Specifies the minimum size of the packets in the pool specified at Client creation. The minimum size is needed to ensure the complete HTTP header can be contained in one packet. The default value is set to 300.
  • NX_HTTP_SERVER_RETRY_SECONDS Set the Server socket retransmission timeout in seconds. The default value is set to 2.
  • NX_HTTP_SERVER_RETRY_MAX This sets the maximum number of retransmissions on Server socket. The default value is set to 10.
  • NX_HTTP_SERVER_RETRY_SHIFT This value is used to set the next retransmission timeout. The current timeout is multiplied by the number of retransmissions thus far, shifted by the value of the socket timeout shift. The default value is set to 1 for doubling the timeout.
  • NX_HTTP_ SERVER_TRANSMIT_QUEUE_DEPTH This specifies the maximum number of packets that can be enqueued on the Server socket retransmission queue. If the number of packets enqueued reaches this number, no more packets can be sent until one or more enqueued packets are released. The default value is set to 20.