174.1. Introduction

The eCos HTTPD package provides a simple HTTP
server for use with applications in eCos. This server is specifically
aimed at the remote control and monitoring requirements of embedded
applications. For this reason the emphasis is on dynamically generated
content, simple forms handling and a basic CGI interface. It is
not intended to be a general purpose server for
delivering arbitrary web content. For these purposes a port of the
GoAhead web server is available from www.goahead.com.

This server is also capable of serving content using IPv6 when
the eCos configuration contains IPv6.

174.2. Server Organization

The server consists of one or more threads running in parallel to any
application threads and which serve web pages to clients. Apart from
defining content, the application does not need to do anything to
start the HTTP server.

The HTTP server is, by default, started by a static constructor. This
simply creates an initial thread and sets it running. Since this is
called before the scheduler is started, nothing will happen until the
application calls cyg_scheduler_start(). The
server thread can also be started explicitly by the application, see
the CYGNUM_HTTPD_SERVER_AUTO_START option for
details.

When the thread gets to run it first optionally delays for some period
of time. This is to allow the application to perform any
initialization free of any interference from the HTTP server. When the
thread does finally run it creates a socket, binds it to the HTTP
server port, and puts it into listen mode. It will then create any
additional HTTPD server threads that have been configured before
becoming a server thread itself.

Each HTTPD server thread simply waits for a connection to be made to
the server port. When the connection is made it reads the HTTP request
and extracts the filename being accessed. If the request also contains
form data, this is also preserved. The filename is then looked up in a
table.

Each table entry contains a filename pattern string, a
pointer to a handler function, and a user defined argument for the
function. Table entries are defined using the same link-time table
building mechanism used to generate device tables. This is all handled
by the CYG_HTTPD_TABLE_ENTRY() macro which has the
following format:

The __name argument is a variable name for the
table entry since C does not allow us to define anonymous data
structures. This name should be chosen so that it is unique and does
not pollute the name space. The __pattern
argument is the match pattern. The __handler
argument is a pointer to the handler function and
__arg the user defined value.

The link-time table building means that several different pieces of
code can define server table entries, and so long as the patterns do
not clash they can be totally oblivious of each other. However, note
also that this mechanism does not guarantee the order in which entries
appear, this depends on the order of object files in the link, which
could vary from one build to the next. So any tricky pattern matching
that relies on this may not always work.

A request filename matches an entry in the table if either it exactly
matches the pattern string, or if the pattern ends in an asterisk, and
it matches everything up to that point. So for example the pattern
"/monitor/threads.html" will only match that exact filename,
but the pattern "/monitor/thread-*" will match
"/monitor/thread-0040.html",
"/monitor/thread-0100.html" and any other filename starting
with "/monitor/thread-".

When a pattern is matched, the hander function is called. It has the
following prototype:

The client argument is the TCP connection to
the client: anything output through this stream will be returned to
the browser. The filename argument is the
filename from the HTTP request and the formdata
argument is any form response data, or NULL if none was sent. The
arg argument is the user defined value from the
table entry.

The handler is entirely responsible for generating the response to the
client, both HTTP header and content. If the handler decides that it
does not want to generate a response it can return
false, in which case the table scan is resumed for
another match. If no match is found, or no handler returns true, then
a default response page is generated indicating that the requested
page cannot be found.

Finally, the server thread closes the connection to the client and
loops back to accept a new connection.

174.3. Server Configuration

The HTTP server has a number of configuration options:

CYGNUM_HTTPD_SERVER_PORT

This option defines the TCP port that the server will listen on. It
defaults to the standard HTTP port number 80. It may be changed to a
different number if, for example, another HTTP server is using the
main HTTP port.

CYGDAT_HTTPD_SERVER_ID

This is the string that is reported to the client in the
"Server:" field of the HTTP header.

CYGNUM_HTTPD_THREAD_COUNT

The HTTP server can be configured to use more than one thread to
service HTTP requests. If you expect to serve complex pages with many
images or other components that are fetched separately, or if any
pages may take a long time to send, then it may be useful to increase
the number of server threads. For most uses, however, the connection
queuing in the TCP/IP stack and the speed with which each page is
generated, means that a single thread is usually adequate.

CYGNUM_HTTPD_THREAD_PRIORITY

The HTTP server threads can be run at any priority. The exact priority
depends on the importance of the server relative to the rest of the
system. The default is to put them in the middle of the priority range
to provide reasonable response without impacting genuine high priority
threads.

CYGNUM_HTTPD_THREAD_STACK_SIZE

This is the amount of stack to be allocated for each of the HTTPD
threads. The actual stack size allocated will be this value plus the
values of CYGNUM_HAL_STACK_SIZE_MINIMUM and
CYGNUM_HTTPD_SERVER_BUFFER_SIZE.

CYGNUM_HTTPD_SERVER_BUFFER_SIZE

This defines the size of the buffer used to receive the first line of
each HTTP request. If you expect to use particularly long URLs or have
very complex forms, this should be increased.

CYGNUM_HTTPD_SERVER_AUTO_START

This option causes the HTTP Daemon to be started automatically during
system initialization. If this option is not set then the application
must start the daemon explicitly by calling
cyg_httpd_startup(). This option is set by
default.

CYGNUM_HTTPD_SERVER_DELAY

This defines the number of system clock ticks that the HTTP server
will wait before initializing itself and spawning any extra server
threads. This is to give the application a chance to initialize
properly without any interference from the HTTPD.

174.4. Support Functions and Macros

The emphasis of this server is on dynamically generated content,
rather than fetching it from a filesystem. To do this the handler
functions make calls to fprintf() and
fputs(). Such handler functions would end up a
mass of print calls, with the actual structure of the HTML page hidden
in the format strings and arguments, making maintenance and debugging
very difficult. Such an approach would also result in the definition
of many, often only slightly different, format strings, leading to
unnecessary bloat.

In an effort to expose the structure of the HTML in the structure of
the C code, and to maximize the sharing of string constants, the
cyg/httpd/httpd.h header file defines a set of
helper functions and macros. Most of these are wrappers for predefined
print calls on the client stream passed to the
hander function. For examples of their use, see the System Monitor
example.

Note

All arguments to macros are pointers to strings, unless otherwise
stated. In general, wherever a function or macro has an
attr or __attr
parameter, then the contents of this string will be inserted into the
tag being defined as HTML attributes. If it is a NULL or empty string
it will be ignored.

174.4.1. HTTP Support

The function cyg_http_start() generates a simple
HTTP response header containing the value of
CYGDAT_HTTPD_SERVER_ID in the "Server" field, and the
values of content_type and
content_length in the "Content-type"
and "Content-length" field respectively. The function
cyg_http_finish() just adds an extra newline to
the end of the output and then flushes it to force the data out to the
client.

The macro html_begin() generates an HTTP header
with a "text/html" content type followed by an opening
"<html>" tag. html_end() generates
a closing "</html>" tag and calls
cyg_http_finish().

The function cyg_html_tag_begin() generates an
opening tag with the given name. The function
cyg_html_tag_end() generates a closing tag with
the given name. The macros html_tag_begin() and
html_tag_end are just wrappers for these functions.

The macro html_head() generates an HTML header
section with __title as the title. The
__meta argument defines any meta tags that will
be inserted into the header. html_body_begin() and
html_body_end generate HTML body begin and end
tags.

html_heading() generates a complete HTML header
where __level is a numerical level, between 1
and 6, and __heading is the heading
text. html_para_begin() generates a paragraph
break.

html_url() inserts a URL where
__text is the displayed text and
__link is the URL of the linked
page. html_image() inserts an image tag where
__source is the URL of the image to be
included and __alt is the alternative text for
when the image is not displayed.

html_form_begin() begins a form, the
__url argument is the value for the
action
attribute. html_form_end() ends the form.

html_form_input() defines a general form input
element with the given type, name and
value. html_form_input_radio creates a radio button
with the given name and value; the __checked
argument is a boolean expression that is used to determine whether the
checked attribute is added to the tag. Similarly
html_form_input_checkbox() defines a checkbox
element. html_form_input_hidden() defines a hidden
form element with the given name and value.

html_form_select_begin() begins a multiple choice
menu with the given name. html_form_select_end()
end it. html_form_option() defines a menu entry
with the given value and label; the __selected
argument is a boolean expression controlling whether the
selected attribute is added to the tag.

cyg_formdata_parse() converts a form response
string into an NULL-terminated array of
"name=value" entries. The data
argument is the string as passed to the handler function; note that
this string is not copied and will be updated in place to form the
list entries. list is a pointer to an array of
character pointers, and is size elements long.
cyg_formlist_find() searches a list generated by
cyg_formdata_parse() and returns a pointer to the
value part of the string whose name part matches
name; if there is no match it will return
NULL.

cyg_httpd_send_data() Sends arbitrary data to the
client. The argument is a pointer to a cyg_httpd_data
structure that defines the content type and length of the data, and a
pointer to the data itself. The CYG_HTTPD_DATA()
macro automates the definition of the structure. Here is a typical
example of its use:

174.5. System Monitor

Included in the HTTPD package is a simple System Monitor that is
intended to act as a test and an example of how to produce servers.
It is also hoped that it might be of some use in and of itself.

The System Monitor is intended to work in the background of any
application. Adding the network stack and the HTTPD package to any
configuration will enable the monitor by default. It may be disabled
by disabling the CYGPKG_HTTPD_MONITOR option.

The monitor is intended to be simple and self-explanatory in use. It
consists of four main pages. The thread monitor page presents a table
of all current threads showing such things as id, state, priority,
name and stack dimensions. Clicking on the thread ID will link to a
thread edit page where the thread's state and priority may be
manipulated. The interrupt monitor just shows a table of the current
interrupts and indicates which are active. The memory monitor shows a
256 byte page of memory, with controls to change the base address and
display element size. Note: Accessing invalid memory locations can cause
memory exceptions and the program to crash. The network monitor page shows
information extracted from the active network interfaces and
protocols. Finally, if kernel instrumentation is enabled, the
instrumentation page provides some controls over the instrumentation
mechanism, and displays the instrumentation buffer.