OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /or1k/trunk/ecos-2.0/packages/net/httpd
    from Rev 1254 to Rev 1765
    Reverse comparison

Rev 1254 → Rev 1765

/v2_0/cdl/httpd.cdl
0,0 → 1,183
# ====================================================================
#
# httpd.cdl
#
# HTTPD configuration data
#
# ====================================================================
#####ECOSGPLCOPYRIGHTBEGIN####
## -------------------------------------------
## This file is part of eCos, the Embedded Configurable Operating System.
## Copyright (C) 2002 Nick Garnett
##
## eCos is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free
## Software Foundation; either version 2 or (at your option) any later version.
##
## eCos is distributed in the hope that it will be useful, but WITHOUT ANY
## WARRANTY; without even the implied warranty of MERCHANTABILITY or
## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
## for more details.
##
## You should have received a copy of the GNU General Public License along
## with eCos; if not, write to the Free Software Foundation, Inc.,
## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
##
## As a special exception, if other files instantiate templates or use macros
## or inline functions from this file, or you compile this file and link it
## with other works to produce a work based on this file, this file does not
## by itself cause the resulting work to be covered by the GNU General Public
## License. However the source code for this file must still be made available
## in accordance with section (3) of the GNU General Public License.
##
## This exception does not invalidate any other reasons why a work based on
## this file might be covered by the GNU General Public License.
##
## -------------------------------------------
#####ECOSGPLCOPYRIGHTEND####
# ====================================================================
######DESCRIPTIONBEGIN####
#
# Author(s): nickg
# Original data: nickg
# Contributors:
# Date: 2002-10-15
#
#####DESCRIPTIONEND####
#
# ====================================================================
 
cdl_package CYGPKG_HTTPD {
display "HTTP Daemon"
parent CYGPKG_NET
doc ref/net-httpd.html
include_dir cyg/httpd
requires CYGPKG_IO
requires { 0 != CYGINT_ISO_STDLIB_STRCONV }
requires { 0 != CYGINT_ISO_STDIO_FORMATTED_IO }
requires { 0 != CYGINT_ISO_STRING_STRFUNCS }
requires { 0 != CYGINT_ISO_ERRNO }
requires { 0 != CYGINT_ISO_ERRNO_CODES }
requires CYGPKG_NET
description "
HTTP Daemon. This is an embedded 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."
 
compile httpd.c
compile -library=libextras.a init.cxx monitor.c
cdl_option CYGNUM_HTTPD_SERVER_PORT {
display "HTTP port"
flavor data
default_value 80
description "HTTP port to which browsers will connect.
This defaults to the standard port 80, but may
be changed to any other port number if required."
}
 
cdl_option CYGDAT_HTTPD_SERVER_ID {
display "HTTP server ID"
flavor data
default_value { "\"eCos/1.0\"" }
description "This is the string that will be used as the server
identifier in the HTTP header."
}
cdl_option CYGNUM_HTTPD_THREAD_COUNT {
display "HTTPD thread count"
flavor data
default_value 1
description "The HTTP server can be configured to use more than
one thread to service requests. This is useful if you
expect to serve complex pages, or if you expect to have
several simultaneous users. For most purposes, just
one thread is perfectly adequate."
}
 
cdl_option CYGNUM_HTTPD_THREAD_PRIORITY {
display "HTTPD thread priority"
flavor data
default_value { CYGNUM_KERNEL_SCHED_PRIORITIES/2 }
legal_values 0 to CYGNUM_KERNEL_SCHED_PRIORITIES
description "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 it in the middle of the priority range to provide
reasonable response without impacting genuine high
priority threads."
}
 
cdl_option CYGNUM_HTTPD_THREAD_STACK_SIZE {
display "HTTPD thread stack size"
flavor data
default_value 2048
description "This is the amount of stack to be allocated for each
of the HTTPD threads. This quantity is in addition to the values
of CYGNUM_HAL_STACK_SIZE_MINIMUM and
CYGNUM_HTTPD_SERVER_BUFFER_SIZE."
}
 
cdl_option CYGNUM_HTTPD_SERVER_BUFFER_SIZE {
display "HTTPD server buffer size"
flavor data
default_value 256
description "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."
}
 
cdl_option CYGNUM_HTTPD_SERVER_DELAY {
display "HTTPD server startup delay"
flavor data
default_value 0
description "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."
}
 
cdl_component CYGPKG_HTTPD_MONITOR {
display "Simple Web System Monitor"
default_value 1
description "This enables a simple system monitor that displays the
status of an eCos system using a small number of HTML pages."
 
compile -library=libextras.a monitor.c
}
cdl_component CYGPKG_HTTPD_OPTIONS {
display "HTTP server build options"
flavor none
no_define
 
cdl_option CYGPKG_HTTPD_CFLAGS_ADD {
display "Additional compiler flags"
flavor data
no_define
default_value { "-D__ECOS" }
description "
This option modifies the set of compiler flags for
building the HTTP server package.
These flags are used in addition
to the set of global flags."
}
 
cdl_option CYGPKG_HTTPD_CFLAGS_REMOVE {
display "Suppressed compiler flags"
flavor data
no_define
default_value { "" }
description "
This option modifies the set of compiler flags for
building the HTTP server package. These flags are removed from
the set of global flags if present."
}
}
}
 
# EOF httpd.cdl
/v2_0/include/httpd.h
0,0 → 1,279
#ifndef CYGONCE_NET_HTTPD_HTTPD_H
#define CYGONCE_NET_HTTPD_HTTPD_H
/* =================================================================
*
* httpd.h
*
* A simple embedded HTTP server
*
* =================================================================
* ####ECOSGPLCOPYRIGHTBEGIN####
* -------------------------------------------
* This file is part of eCos, the Embedded Configurable Operating
* System.
* Copyright (C) 2002 Nick Garnett
*
* eCos is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 or (at your option)
* any later version.
*
* eCos is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with eCos; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
* As a special exception, if other files instantiate templates or
* use macros or inline functions from this file, or you compile this
* file and link it with other works to produce a work based on this
* file, this file does not by itself cause the resulting work to be
* covered by the GNU General Public License. However the source code
* for this file must still be made available in accordance with
* section (3) of the GNU General Public License.
*
* This exception does not invalidate any other reasons why a work
* based on this file might be covered by the GNU General Public
* License.
*
* -------------------------------------------
* ####ECOSGPLCOPYRIGHTEND####
* =================================================================
* #####DESCRIPTIONBEGIN####
*
* Author(s): nickg@calivar.com
* Contributors: nickg@calivar.com
* Date: 2002-10-14
* Purpose:
* Description:
*
* ####DESCRIPTIONEND####
*
* =================================================================
*/
 
#include <pkgconf/system.h>
#include <pkgconf/isoinfra.h>
#include <pkgconf/httpd.h>
 
#include <cyg/hal/hal_tables.h>
 
#include <stdio.h>
 
/* ================================================================= */
/* Lookup Table
*
*
*/
 
typedef cyg_bool cyg_httpd_handler(FILE *client, char *filename,
char *formdata, void *arg);
 
struct cyg_httpd_table_entry
{
char *pattern;
cyg_httpd_handler *handler;
void *arg;
} CYG_HAL_TABLE_TYPE;
 
typedef struct cyg_httpd_table_entry cyg_httpd_table_entry;
 
#define CYG_HTTPD_TABLE_ENTRY( __name, __pattern, __handler, __arg ) \
cyg_httpd_table_entry __name CYG_HAL_TABLE_ENTRY( httpd_table ) = { __pattern, __handler, __arg }
 
/* ================================================================= */
/* Useful handler functions
*/
 
/* ----------------------------------------------------------------- */
/*
*/
 
__externC int cyg_httpd_send_html( FILE *client, char *filename,
char *request, void *arg );
 
/* ----------------------------------------------------------------- */
/*
*/
 
typedef struct
{
char *content_type;
cyg_uint32 content_length;
cyg_uint8 *data;
} cyg_httpd_data;
 
__externC int cyg_httpd_send_data( FILE *client, char *filename,
char *request, void *arg );
 
#define CYG_HTTPD_DATA( __name, __type, __length, __data ) \
cyg_httpd_data __name = { __type, __length, __data }
 
/* ================================================================= */
/* HTTP and HTML helper macros and functions
*/
 
/* ----------------------------------------------------------------- */
/* HTTP header support
*
* cyg_http_start() sends an HTTP header with the given content type
* and length. cyg_http_finish() terminates an HTTP send.
* html_begin() starts an HTML document, and html_end() finishes it.
*/
 
__externC void cyg_http_start( FILE *client, char *content_type,
int content_length );
__externC void cyg_http_finish( FILE *client );
 
#define html_begin(__client) \
cyg_http_start( __client, "text/html", 0 ); \
html_tag_begin( __client, "html", "" )
 
#define html_end( __client ) \
html_tag_end( __client, "html" ); \
cyg_http_finish( __client )
 
/* ----------------------------------------------------------------- */
/*
*/
 
 
__externC void cyg_html_tag_begin( FILE *client, char *tag, char *attr );
__externC void cyg_html_tag_end( FILE *client, char *tag );
 
#define html_tag_begin( __client, __tag, __attr ) \
cyg_html_tag_begin( __client, __tag, __attr )
 
#define html_tag_end( __client, __tag ) cyg_html_tag_end( __client, __tag )
 
 
/* ----------------------------------------------------------------- */
/*
*/
 
 
#define html_head( __client, __title, __meta ) \
{ \
fprintf(__client, "<%s><%s>", "head", "title" ); \
fputs( __title, __client ); \
fprintf(__client, "</%s>%s</%s>\n", "title", __meta, "head"); \
}
 
#define html_body_begin( __client, __attr ) \
cyg_html_tag_begin( __client, "body", __attr );
 
#define html_body_end( __client ) \
cyg_html_tag_end( __client, "body" );
 
#define html_heading( __client, __level, __heading ) \
fprintf(__client,"<h%d>%s</h%d>\n",__level,__heading,__level);
 
/* ----------------------------------------------------------------- */
/*
*/
 
 
#define html_url( __client, __text, __link ) \
fprintf( __client, "<a href=\"%s\">%s</a>\n",__link,__text);
 
#define html_para_begin( __client, __attr ) \
cyg_html_tag_begin( __client, "p", __attr );
 
#define html_image( __client, __source, __alt, __attr ) \
fprintf( __client, "<%s %s=\"%s\" %s=\"%s\" %s>\n", "img", \
"src",__source, \
"alt",__alt, \
(__attr)?(__attr):"" );
 
/* ----------------------------------------------------------------- */
/*
*/
 
 
#define html_table_begin( __client, __attr ) \
cyg_html_tag_begin( __client, "table", __attr );
 
#define html_table_end( __client ) \
cyg_html_tag_end( __client, "table" );
 
#define html_table_header( __client, __content, __attr ) \
{ \
cyg_html_tag_begin( __client, "th", __attr); \
fputs( __content, __client ); \
cyg_html_tag_end( __client, "th" ); \
}
 
#define html_table_row_begin( __client, __attr ) \
cyg_html_tag_begin( __client, "tr", __attr );
 
#define html_table_row_end( __client ) \
cyg_html_tag_end( __client, "tr" );
 
#define html_table_data_begin( __client, __attr ) \
cyg_html_tag_begin( __client, "td", __attr );
 
#define html_table_data_end( __client ) \
cyg_html_tag_end( __client, "td" );
 
/* ----------------------------------------------------------------- */
/*
*/
 
 
#define html_form_begin( __client, __url, __attr ) \
fprintf(__client, "<%s %s=\"%s\" %s>\n","form", \
"action",__url, \
(__attr)?(__attr):"" );
 
#define html_form_end( __client ) \
cyg_html_tag_end( __client, "form" );
 
#define html_form_input( __client, __type, __name, __value, __attr ) \
{ \
char *__lattr = (__attr); \
fprintf(__client, "<%s %s=\"%s\" %s=\"%s\" %s=\"%s\" %s>\n","input", \
"type",__type, \
"name",__name, \
"value",__value, \
__lattr?__lattr:"" ); \
}
 
#define html_form_input_radio( __client, __name, __value, __checked ) \
html_form_input( __client, "radio", __name, __value, (__checked)?"checked":"" )
 
#define html_form_input_checkbox( __client, __name, __value, __checked ) \
html_form_input( __client, "checkbox", __name, __value, (__checked)?"checked":"" )
 
#define html_form_input_hidden( __client, __name, __value ) \
html_form_input( __client, "hidden", __name, __value, "" )
 
#define html_form_select_begin( __client, __name, __attr ) \
fprintf( __client, "<%s %s=\"%s\" %s>\n","select", \
"name",__name, \
(__attr)?(__attr):"" );
 
#define html_form_option( __client, __value, __label, __selected ) \
fprintf( __client, "<%s %s=\"%s\" %s>\n","option", \
"value", __value, \
(__selected)?"selected":"" ); \
fputs(__label, __client );
 
#define html_form_select_end( __client ) \
cyg_html_tag_end( __client, "select" );
 
 
/* ================================================================= */
/*
*/
 
 
__externC void cyg_formdata_parse( char *data, char *list[], int size );
 
__externC char *cyg_formlist_find( char *list[], char *name );
 
/* ----------------------------------------------------------------- */
#endif /* CYGONCE_NET_HTTPD_HTTPD_H */
/* end of httpd.c */
/v2_0/doc/httpd.sgml
0,0 → 1,532
 
<!-- =============================================================== -->
<!-- -->
<!-- httpd.sgml -->
<!-- -->
<!-- eCos HTTP Server -->
<!-- -->
<!-- =============================================================== -->
<!-- ####COPYRIGHTBEGIN#### -->
<!-- -->
<!-- =============================================================== -->
<!-- Copyright (C) 2002 Nick Garnett -->
<!-- This material may be distributed only subject to the terms -->
<!-- and conditions set forth in the Open Publication License, v1.0 -->
<!-- or later (the latest version is presently available at -->
<!-- http://www.opencontent.org/openpub/) -->
<!-- Distribution of the work or derivative of the work in any -->
<!-- standard (paper) book form is prohibited unless prior -->
<!-- permission obtained from the copyright holder -->
<!-- =============================================================== -->
<!-- -->
<!-- ####COPYRIGHTEND#### -->
<!-- =============================================================== -->
<!-- #####DESCRIPTIONBEGIN#### -->
<!-- -->
<!-- ####DESCRIPTIONEND#### -->
<!-- =============================================================== -->
 
<part id="net-httpd">
<title>Embedded HTTP Server</title>
<chapter id="net-httpd-chapter">
<title>Embedded HTTP Server</title>
 
<sect1 id="net-httpd-intro">
<title>Intrduction</title>
<para>
The <emphasis>eCos</emphasis> 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
<emphasis>not</emphasis> 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 <ulink
url="www.goahead.com">www.goahead.com</ulink>.
</para>
</sect1>
 
<sect1 id="net-httpd-organization">
<title>Server Organization</title>
<para>
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.
</para>
<para>
The HTTP server is 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 <function>cyg_scheduler_start()</function>.
</para>
<para>
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.
</para>
<para>
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.
</para>
<para>
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 <literal>CYG_HTTPD_TABLE_ENTRY()</literal> macro which has the
following format:
</para>
<programlisting width=72>
 
#include &lt;cyg/httpd/httpd.h&gt;
 
CYG_HTTPD_TABLE_ENTRY( __name, __pattern, __handler, __arg )
 
</programlisting>
<para>
The <parameter>__name</parameter> 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 <parameter>__pattern</parameter>
argument is the match pattern. The <parameter>__handler</parameter>
argument is a pointer to the handler function and
<parameter>__arg</parameter> the user defined value.
</para>
<para>
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.
</para>
<para>
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
&quot;/monitor/threads.html&quot; will only match that exact filename,
but the pattern &quot;/monitor/thread-*&quot; will match
&quot;/monitor/thread-0040.html&quot;,
&quot;/monitor/thread-0100.html&quot; and any other filename starting
with &quot;/monitor/thread-&quot;.
</para>
<para>
When a pattern is matched, the hander function is called. It has the
following prototype:
</para>
<programlisting width=72>
cyg_bool cyg_httpd_handler(FILE *client,
char *filename,
char *formdata,
void *arg);
</programlisting>
<para>
The <parameter>client</parameter> argument is the TCP connection to
the client: anything output through this stream will be returned to
the browser. The <parameter>filename</parameter> argument is the
filename from the HTTP request and the <parameter>formdata</parameter>
argument is any form response data, or NULL if none was sent. The
<parameter>arg</parameter> argument is the user defined value from the
table entry.
</para>
<para>
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
<literal>false</literal>, 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.
</para>
<para>
Finally, the server thread closes the connection to the client and
loops back to accept a new connection.
</para>
</sect1>
 
<!-- =============================================================== -->
 
<sect1 id="net-httpd-configuration">
<title>Server Configuration</title>
<para>
The HTTP server has a number of configuration options:
</para>
 
<sect2>
<title><literal>CYGNUM_HTTPD_SERVER_PORT</literal></title>
<para>
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.
</para>
</sect2>
 
<sect2>
<title><literal>CYGDAT_HTTPD_SERVER_ID</literal></title>
<para>
This is the string that is reported to the client in the
&quot;Server:&quot; field of the HTTP header.
</para>
</sect2>
 
<sect2>
<title><literal>CYGNUM_HTTPD_THREAD_COUNT</literal></title>
<para>
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.
</para>
</sect2>
 
<sect2>
<title><literal>CYGNUM_HTTPD_THREAD_PRIORITY</literal></title>
<para>
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.
</para>
</sect2>
 
<sect2>
<title><literal>CYGNUM_HTTPD_THREAD_STACK_SIZE</literal></title>
<para>
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 <literal>CYGNUM_HAL_STACK_SIZE_MINIMUM</literal> and
<literal>CYGNUM_HTTPD_SERVER_BUFFER_SIZE</literal>.
</para>
</sect2>
 
<sect2>
<title><literal>CYGNUM_HTTPD_SERVER_BUFFER_SIZE</literal></title>
<para>
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.
</para>
</sect2>
 
<sect2>
<title><literal>CYGNUM_HTTPD_SERVER_DELAY</literal></title>
<para>
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.
</para>
</sect2>
 
</sect1>
 
<!-- =============================================================== -->
 
<sect1 id="net-httpd-html">
<title>Support Functions and Macros</title>
<para>
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 <function>fprintf()</function> and
<function>fputs()</function>. 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.
</para>
<para>
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
<filename>cyg/httpd/httpd.h</filename> header file defines a set of
helper functions and macros. Most of these are wrappers for predefined
print calls on the <parameter>client</parameter> stream passed to the
hander function. For examples of their use, see the System Monitor
example.
</para>
<note>
<para>
All arguments to macros are pointers to strings, unless otherwise
stated. In general, wherever a function or macro has an
<parameter>attr</parameter> or <parameter>__attr</parameter>
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.
</para>
</note>
 
<sect2>
<title>HTTP Support</title>
<programlisting width=72>
void cyg_http_start( FILE *client, char *content_type, int content_length );
void cyg_http_finish( FILE *client );
#define html_begin(__client)
#define html_end( __client )
</programlisting>
<para>
The function <function>cyg_http_start()</function> generates a simple
HTTP response header containing the value of
<literal>CYGDAT_HTTPD_SERVER_ID</literal> in the &quot;Server&quot; field, and the
values of <parameter>content_type</parameter> and
<parameter>content_length</parameter> in the &quot;Content-type&quot;
and &quot;Content-length&quot; field respectively. The function
<function>cyg_http_finish()</function> just adds an extra newline to
the end of the output and then flushes it to force the data out to the
client.
</para>
<para>
The macro <literal>html_begin()</literal> generates an HTTP header
with a &quot;text/html&quot; content type followed by an opening
&quot;&lt;html&gt;&quot; tag. <literal>html_end()</literal> generates
a closing &quot;&lt;/html&gt;&quot; tag and calls
<function>cyg_http_finish()</function>.
</para>
</sect2>
 
<sect2>
<title>General HTML Support</title>
<programlisting width=72>
void cyg_html_tag_begin( FILE *client, char *tag, char *attr );
void cyg_html_tag_end( FILE *client, char *tag );
#define html_tag_begin( __client, __tag, __attr )
#define html_tag_end( __client, __tag )
#define html_head( __client, __title, __meta )
#define html_body_begin( __client, __attr )
#define html_body_end( __client )
#define html_heading( __client, __level, __heading )
#define html_para_begin( __client, __attr )
#define html_url( __client, __text, __link )
#define html_image( __client, __source, __alt, __attr )
</programlisting>
<para>
The function <function>cyg_html_tag_begin()</function> generates an
opening tag with the given name. The function
<function>cyg_html_tag_end()</function> generates a closing tag with
the given name. The macros <literal>html_tag_begin()</literal> and
<literal>html_tag_end</literal> are just wrappers for these functions.
</para>
<para>
The macro <literal>html_head()</literal> generates an HTML header
section with <parameter>__title</parameter> as the title. The
<parameter>__meta</parameter> argument defines any meta tags that will
be inserted into the header. <literal>html_body_begin()</literal> and
<literal>html_body_end</literal> generate HTML body begin and end
tags.
</para>
<para>
<literal>html_heading()</literal> generates a complete HTML header
where <parameter>__level</parameter> is a numerical level, between 1
and 6, and <parameter>__heading</parameter> is the heading
text. <literal>html_para_begin()</literal> generates a paragraph
break.
</para>
<para>
<literal>html_url()</literal> inserts a URL where
<parameter>__text</parameter> is the displayed text and
<parameter>__link</parameter> is the URL of the linked
page. <literal>html_image()</literal> inserts an image tag where
<parameter>__source</parameter> is the URL of the image to be
included and <parameter>__alt</parameter> is the alternative text for
when the image is not displayed.
</para>
</sect2>
 
<sect2>
<title>Table Support</title>
<programlisting width=72>
#define html_table_begin( __client, __attr )
#define html_table_end( __client )
#define html_table_header( __client, __content, __attr )
#define html_table_row_begin( __client, __attr )
#define html_table_row_end( __client )
#define html_table_data_begin( __client, __attr )
#define html_table_data_end( __client )
</programlisting>
<para>
<literal>html_table_begin()</literal> starts a table and
<literal>html_table_end()</literal> end
it. <literal>html_table_header()</literal> generates a simple table
column header containg the string <parameter>__content</parameter>.
</para>
<para>
<literal>html_table_row_begin()</literal> and
<literal>html_table_row_end()</literal> begin and end a table row,
and similarly <literal>html_table_data_begin()</literal> and
<literal>html_table_data_end()</literal> begin and end a table
entry.
</para>
</sect2>
 
<sect2>
<title>Forms Support</title>
<programlisting width=72>
#define html_form_begin( __client, __url, __attr )
#define html_form_end( __client )
#define html_form_input( __client, __type, __name, __value, __attr )
#define html_form_input_radio( __client, __name, __value, __checked )
#define html_form_input_checkbox( __client, __name, __value, __checked )
#define html_form_input_hidden( __client, __name, __value )
#define html_form_select_begin( __client, __name, __attr )
#define html_form_option( __client, __value, __label, __selected )
#define html_form_select_end( __client )
void cyg_formdata_parse( char *data, char *list[], int size );
char *cyg_formlist_find( char *list[], char *name );
</programlisting>
<para>
<literal>html_form_begin()</literal> begins a form, the
<parameter>__url</parameter> argument is the value for the
<literal>action</literal>
attribute. <literal>html_form_end()</literal> ends the form.
</para>
<para>
<literal>html_form_input()</literal> defines a general form input
element with the given type, name and
value. <literal>html_form_input_radio</literal> creates a radio button
with the given name and value; the <parameter>__checked</parameter>
argument is a boolean expression that is used to determine whether the
<literal>checked</literal> attribute is added to the tag. Similarly
<literal>html_form_input_checkbox()</literal> defines a checkbox
element. <literal>html_form_input_hidden()</literal> defines a hidden
form element with the given name and value.
</para>
<para>
<literal>html_form_select_begin()</literal> begins a multiple choice
menu with the given name. <literal>html_form_select_end()</literal>
end it. <literal>html_form_option()</literal> defines a menu entry
with the given value and label; the <parameter>__selected</parameter>
argument is a boolean expression controlling whether the
<literal>selected</literal> attribute is added to the tag.
</para>
<para>
<function>cyg_formdata_parse()</function> converts a form response
string into an <literal>NULL</literal>-terminated array of
&quot;name=value&quot; entries. The <parameter>data</parameter>
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. <parameter>list</parameter> is a pointer to an array of
character pointers, and is <parameter>size</parameter> elements long.
<function>cyg_formlist_find()</function> searches a list generated by
<function>cyg_formdata_parse()</function> and returns a pointer to the
value part of the string whose name part matches
<parameter>name</parameter>; if there is no match it will return
<literal>NULL</literal>.
</para>
</sect2>
 
<sect2>
<title>Predefined Handlers</title>
<programlisting width=72>
 
int cyg_httpd_send_html( FILE *client, char *filename, char *request, void *arg );
 
typedef struct
{
char *content_type;
cyg_uint32 content_length;
cyg_uint8 *data;
} cyg_httpd_data;
#define CYG_HTTPD_DATA( __name, __type, __length, __data )
 
int cyg_httpd_send_data( FILE *client, char *filename, char *request, void *arg );
 
</programlisting>
<para>
The HTTP server defines a couple of predefined handers to make it
easier to deliver simple, static content.
</para>
<para>
<function>cyg_httpd_send_html()</function> takes a
<literal>NULL</literal>-terminated string as the argument and sends it
to the client with an HTTP header indicating that it is HTML. The
following is an example of its use:
</para>
<programlisting width=72>
 
char cyg_html_message[] = "&lt;head&gt;&lt;title&gt;Welcome&lt;/title&gt;&lt;/head&gt;\n"
"&lt;body&gt;&lt;h2&gt;Welcome to my Web Page&lt;/h2&gt;&lt;/body&gt;\n"
 
CYG_HTTPD_TABLE_ENTRY( cyg_html_message_entry,
"/message.html",
cyg_httpd_send_html,
cyg_html_message );
 
</programlisting>
<para>
<function>cyg_httpd_send_data()</function> Sends arbitrary data to the
client. The argument is a pointer to a <type>cyg_httpd_data</type>
structure that defines the content type and length of the data, and a
pointer to the data itself. The <literal>CYG_HTTPD_DATA()</literal>
macro automates the definition of the structure. Here is a typical
example of its use:
</para>
<programlisting width=72>
 
static cyg_uint8 ecos_logo_gif[] = {
...
};
 
CYG_HTTPD_DATA( cyg_monitor_ecos_logo_data,
"image/gif",
sizeof(ecos_logo_gif),
ecos_logo_gif );
 
CYG_HTTPD_TABLE_ENTRY( cyg_monitor_ecos_logo,
"/monitor/ecos.gif",
cyg_httpd_send_data,
&amp;cyg_monitor_ecos_logo_data );
 
</programlisting>
</sect2>
 
</sect1>
 
<!-- =============================================================== -->
 
<sect1 id="net-httpd-monitor">
<title>System Monitor</title>
<para>
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.
</para>
<para>
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 <literal>CYGPKG_HTTPD_MONITOR</literal> option.
</para>
<para>
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. 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.
</para>
</sect1>
 
<!-- =============================================================== -->
 
</chapter>
</part>
/v2_0/ChangeLog
0,0 → 1,24
2003-02-24 Jonathan Larmour <jifl@eCosCentric.com>
 
* cdl/httpd.cdl: Add doc link.
 
2003-02-14 Bob Koninckx <bob.koninckx@mech.kuleuven.ac.be>
 
* include/httpd.h (html_end): fix typo.
 
2002-12-06 Nick Garnett <nickg@ecoscentric.com>
 
* include/httpd.h:
* src/init.cxx:
* src/httpd.c:
* src/monitor.c:
* doc/httpd.sgml:
* cdl/httpd.cdl:
Created HTTPD package.
# Copyright (C) 2002 Nick Garnett
# All Rights Reserved.
#
# Permission is granted to use, copy, modify and redistribute this
# file.
/v2_0/src/httpd.c
0,0 → 1,520
/* =================================================================
*
* httpd.c
*
* A simple embedded HTTP server
*
* =================================================================
* ####ECOSGPLCOPYRIGHTBEGIN####
* -------------------------------------------
* This file is part of eCos, the Embedded Configurable Operating
* System.
* Copyright (C) 2002 Nick Garnett.
*
* eCos is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 or (at your option)
* any later version.
*
* eCos is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with eCos; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
* As a special exception, if other files instantiate templates or
* use macros or inline functions from this file, or you compile this
* file and link it with other works to produce a work based on this
* file, this file does not by itself cause the resulting work to be
* covered by the GNU General Public License. However the source code
* for this file must still be made available in accordance with
* section (3) of the GNU General Public License.
*
* This exception does not invalidate any other reasons why a work
* based on this file might be covered by the GNU General Public
* License.
*
* -------------------------------------------
* ####ECOSGPLCOPYRIGHTEND####
* =================================================================
* #####DESCRIPTIONBEGIN####
*
* Author(s): nickg@calivar.com
* Contributors: nickg@calivar.com
* Date: 2002-10-14
* Purpose:
* Description:
*
* ####DESCRIPTIONEND####
*
* =================================================================
*/
 
#include <pkgconf/system.h>
#include <pkgconf/isoinfra.h>
#include <pkgconf/httpd.h>
 
#include <cyg/infra/cyg_trac.h> /* tracing macros */
#include <cyg/infra/cyg_ass.h> /* assertion macros */
 
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
 
#include <network.h>
#include <arpa/inet.h>
 
#include <cyg/httpd/httpd.h>
 
/* ================================================================= */
 
#if 0
#define HTTPD_DIAG diag_printf
#else
#define HTTPD_DIAG(...)
#endif
 
/* ================================================================= */
/* Server socket address and file descriptor.
*/
 
static struct sockaddr_in server_address;
 
static int server_socket = -1;
 
/* ================================================================= */
/* Thread stacks, etc.
*/
 
static cyg_uint8 httpd_stacks[CYGNUM_HTTPD_THREAD_COUNT]
[CYGNUM_HAL_STACK_SIZE_MINIMUM+
CYGNUM_HTTPD_SERVER_BUFFER_SIZE+
CYGNUM_HTTPD_THREAD_STACK_SIZE];
 
static cyg_handle_t httpd_thread[CYGNUM_HTTPD_THREAD_COUNT];
 
static cyg_thread httpd_thread_object[CYGNUM_HTTPD_THREAD_COUNT];
 
/* ================================================================= */
/* Filename lookup table
*/
 
CYG_HAL_TABLE_BEGIN( cyg_httpd_table, httpd_table );
CYG_HAL_TABLE_END( cyg_httpd_table_end, httpd_table );
 
__externC cyg_httpd_table_entry cyg_httpd_table[];
__externC cyg_httpd_table_entry cyg_httpd_table_end[];
 
/* ================================================================= */
/* Page not found message
*/
 
static char cyg_httpd_not_found[] =
"<head><title>Page Not found</title></head>\n"
"<body><h2>The requested URL was not found on this server.</h2></body>\n";
 
/* ================================================================= */
/* Simple pattern matcher for filenames
*
* This performs a simple pattern match between the given name and the
* pattern. At present the only matching supported is either exact, or
* if the pattern ends in * then that matches all remaining
* characters. At some point we might want to implement a more
* complete regular expression parser here.
*/
 
static cyg_bool match( char *name, char *pattern )
{
while( *name != 0 && *pattern != 0 && *name == *pattern )
name++, pattern++;
 
if( *name == 0 && *pattern == 0 )
return true;
 
if( *pattern == '*' )
return true;
 
return false;
}
 
/* ================================================================= */
/* Main HTTP server
*
* This just loops, collects client connections, reads the HTTP
* header, look it up in the table and calls the handler.
*/
 
static void cyg_httpd_server( cyg_addrword_t arg )
{
do
{
int err;
int client_socket;
struct sockaddr_in client_address;
int calen;
int nlc = 0;
char request[CYGNUM_HTTPD_SERVER_BUFFER_SIZE];
FILE *client;
cyg_httpd_table_entry *entry = cyg_httpd_table;
char *filename;
char *formdata = NULL;
char *p;
cyg_bool success = false;
 
/* Wait for a connection.
*/
client_socket = accept( server_socket, (struct sockaddr *)&client_address, &calen );
HTTPD_DIAG("Connection from %08x[%d]\n",client_address.sin_addr.s_addr,
client_address.sin_port);
 
/* Convert the file descriptor to a C library FILE object so
* we can use fprintf() and friends on it.
*/
client = fdopen( client_socket, "r+");
 
/* We are really only interested in the first line.
*/
fgets( request, sizeof(request), client );
 
HTTPD_DIAG("Request >%s<\n", request );
/* Absorb the rest of the header. We nibble it away a
* character at a time like this to avoid having to define
* another buffer to read lines into. If we ever need to take
* more interest in the header fields, we will need to be a
* lot more sophisticated than this.
*/
do{
int c = getc( client );
HTTPD_DIAG("%c",c);
if( c == '\n' )
nlc++;
else if( c != '\r' )
nlc = 0;
} while(nlc < 2);
 
/* Extract the filename and any form data being returned.
* We know that the "GET " request takes 4 bytes.
* TODO: handle POST type requests as well as GET's.
*/
 
filename = p = request+4;
 
/* Now scan the filename until we hit a space or a '?'. If we
* end on a '?' then the rest is a form request. Put NULs at
* the end of each string.
*/
while( *p != ' ' && *p != '?' )
p++;
if( *p == '?' )
formdata = p+1;
*p = 0;
 
if( formdata != NULL )
{
while( *p != ' ' )
p++;
*p = 0;
}
 
HTTPD_DIAG("Request filename >%s< formdata >%s<\n",filename,formdata?formdata:"-NULL-");
 
HTTPD_DIAG("table: %08x...%08x\n",cyg_httpd_table, cyg_httpd_table_end);
 
/* Now scan the table for a matching entry. If we find one
* call the handler routine. If that returns true then we
* terminate the scan, otherwise we keep looking.
*/
while( entry != cyg_httpd_table_end )
{
HTTPD_DIAG("try %08x: %s\n", entry, entry->pattern);
if( match( filename, entry->pattern ) )
{
if( (success = entry->handler( client, filename, formdata, entry->arg )) )
break;
}
 
entry++;
}
 
/* If we failed to find a match in the table, send a "not
* found" response.
* TODO: add an optional fallback to go look for files in
* some filesystem, somewhere.
*/
if( !success )
cyg_httpd_send_html( client, NULL, NULL, cyg_httpd_not_found );
 
/* All done, close the connection
*/
err = fclose( client );
CYG_ASSERT( err == 0, "fclose() returned error");
} while(1);
}
 
/* ================================================================= */
/* Initialization thread
*
* Optionally delay for a time before getting the network
* running. Then create and bind the server socket and put it into
* listen mode. Spawn any further server threads, then enter server
* mode.
*/
 
static void cyg_httpd_init(cyg_addrword_t arg)
{
int i;
int err = 0;
 
/* Delay for a configurable length of time to give the application
* a chance to get going, or even complete, without interference
* from the HTTPD.
*/
if( CYGNUM_HTTPD_SERVER_DELAY > 0 )
{
cyg_thread_delay( CYGNUM_HTTPD_SERVER_DELAY );
}
server_address.sin_family = AF_INET;
server_address.sin_len = sizeof(server_address);
server_address.sin_addr.s_addr = INADDR_ANY;
server_address.sin_port = htons(CYGNUM_HTTPD_SERVER_PORT);
 
/* Get the network going. This is benign if the application has
* already done this.
*/
init_all_network_interfaces();
 
/* Create and bind the server socket.
*/
server_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
CYG_ASSERT( server_socket > 0, "Socket create failed");
 
err = bind( server_socket, (struct sockaddr *)&server_address,
sizeof(server_address) );
CYG_ASSERT( err == 0, "bind() returned error");
 
err = listen( server_socket, SOMAXCONN );
CYG_ASSERT( err == 0, "listen() returned error" );
 
/* If we are configured to have more than one server thread,
* create them now.
*/
for( i = 1; i < CYGNUM_HTTPD_THREAD_COUNT; i++ )
{
cyg_thread_create( CYGNUM_HTTPD_THREAD_PRIORITY,
cyg_httpd_server,
0,
"HTTPD",
&httpd_stacks[i][0],
sizeof(httpd_stacks[i]),
&httpd_thread[i],
&httpd_thread_object[i]
);
cyg_thread_resume( httpd_thread[i] );
}
 
/* Now go be a server ourself.
*/
cyg_httpd_server(arg);
}
 
/* ================================================================= */
/* System initializer
*
* This is called from the static constructor in init.cxx. It spawns
* the main server thread and makes it ready to run.
*/
 
__externC void cyg_httpd_startup(void)
{
cyg_thread_create( CYGNUM_HTTPD_THREAD_PRIORITY,
cyg_httpd_init,
0,
"HTTPD",
&httpd_stacks[0][0],
sizeof(httpd_stacks[0]),
&httpd_thread[0],
&httpd_thread_object[0]
);
cyg_thread_resume( httpd_thread[0] );
}
 
/* ================================================================= */
/* HTTP protocol handling
*
* cyg_http_start() generates an HTTP header with the given content
* type and, if non-zero, length.
* cyg_http_finish() just adds a couple of newlines for luck and
* flushes the stream.
*/
 
__externC void cyg_http_start( FILE *client, char *content_type,
int content_length )
{
fputs( "HTTP/1.1 200 OK\n"
"Server: " CYGDAT_HTTPD_SERVER_ID,
client );
 
if( content_type != NULL )
fprintf( client,"Content-type: %s\n", content_type );
 
if( content_length != 0 )
fprintf( client, "Content-length: %d\n", content_length );
 
fputs( "Connection: close\n"
"\n",
client );
}
 
__externC void cyg_http_finish( FILE *client )
{
fputs( "\n\n", client );
fflush( client );
}
 
/* ================================================================= */
/* HTML tag generation
*
* These functions generate standard HTML begin and end tags. By using
* these rather than direct printf()s we help to reduce the number of
* distinct strings present in the executable.
*/
 
__externC void cyg_html_tag_begin( FILE *client, char *tag, char *attr )
{
char *pad = "";
 
if( attr == NULL )
attr = pad;
else if( attr[0] != 0 )
pad = " ";
 
fprintf(client, "<%s%s%s>\n",tag,pad,attr);
}
 
__externC void cyg_html_tag_end( FILE *client, char *tag )
{
fprintf( client, "<%s%s%s>\n","/",tag,"");
}
 
/* ================================================================= */
/* Parse form request data
*
* Given a form response string, we parse it into an argv/environment
* style array of "name=value" strings. We also convert any '+'
* separators back into spaces.
*
* TODO: also translate any %xx escape sequences back into real
* characters.
*/
 
__externC void cyg_formdata_parse( char *data, char *list[], int size )
{
char *p = data;
int i = 0;
 
list[i] = p;
while( *p != 0 && i < size-1 )
{
if( *p == '&' )
{
*p++ = 0;
list[++i] = p;
continue;
}
if( *p == '+' )
*p = ' ';
p++;
}
 
list[++i] = 0;
}
 
/* ----------------------------------------------------------------- */
/* Search for a form response value
*
* Search a form response list generated by cyg_formdata_parse() for
* the named element. If it is found a pointer to the value part is
* returned. If it is not found a NULL pointer is returned.
*/
 
__externC char *cyg_formlist_find( char *list[], char *name )
{
while( *list != 0 )
{
char *p = *list;
char *q = name;
 
while( *p == *q )
p++, q++;
 
if( *q == 0 && *p == '=' )
return p+1;
list++;
}
 
return 0;
}
 
/* ================================================================= */
/* Predefined page handlers
*/
 
/* ----------------------------------------------------------------- */
/* Send an HTML page from a single string
*
* This just sends the string passed as the argument with an HTTP
* header that describes it as HTML. This is useful for sending
* straightforward static web content.
*/
 
__externC cyg_bool cyg_httpd_send_html( FILE *client, char *filename,
char *request, void *arg )
{
html_begin( client );
fwrite( arg, 1, strlen((char *)arg), client );
 
html_end( client );
 
return true;
}
 
/* ----------------------------------------------------------------- */
/* Send arbitrary data
*
* This takes a pointer to a cyg_httpd_data structure as the argument
* and sends the data therein after a header that uses the content
* type and size from the structure. This is useful for non-HTML data
* such a images.
*/
 
__externC cyg_bool cyg_httpd_send_data( FILE *client, char *filename,
char *request, void *arg )
{
cyg_httpd_data *data = (cyg_httpd_data *)arg;
 
cyg_http_start( client, data->content_type, data->content_length );
fwrite( data->data, 1, data->content_length, client );
 
return true;
}
 
/* ----------------------------------------------------------------- */
/* end of httpd.c */
/v2_0/src/init.cxx
0,0 → 1,93
/* =================================================================
*
* init.cxx
*
* Constructor for HTTPD
*
* =================================================================
* ####ECOSGPLCOPYRIGHTBEGIN####
* -------------------------------------------
* This file is part of eCos, the Embedded Configurable Operating
* System.
* Copyright (C) 2002 Nick Garnett.
*
* eCos is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 or (at your option)
* any later version.
*
* eCos is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with eCos; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
* As a special exception, if other files instantiate templates or
* use macros or inline functions from this file, or you compile this
* file and link it with other works to produce a work based on this
* file, this file does not by itself cause the resulting work to be
* covered by the GNU General Public License. However the source code
* for this file must still be made available in accordance with
* section (3) of the GNU General Public License.
*
* This exception does not invalidate any other reasons why a work
* based on this file might be covered by the GNU General Public
* License.
*
* -------------------------------------------
* ####ECOSGPLCOPYRIGHTEND####
* =================================================================
* #####DESCRIPTIONBEGIN####
*
* Author(s): nickg@calivar.com
* Contributors: nickg@calivar.com
* Date: 2002-10-14
* Purpose:
* Description:
*
* ####DESCRIPTIONEND####
*
* =================================================================
*/
 
#include <pkgconf/system.h>
#include <pkgconf/isoinfra.h>
#include <pkgconf/httpd.h>
 
#include <cyg/infra/cyg_trac.h> // tracing macros
#include <cyg/infra/cyg_ass.h> // assertion macros
 
/* ================================================================= */
 
__externC void cyg_httpd_startup(void);
 
/* ================================================================= */
/* Initialization object
*/
 
class Cyg_Httpd_Init_Class
{
public:
Cyg_Httpd_Init_Class();
};
 
/* ----------------------------------------------------------------- */
/* Static initialization object instance. The constructor is
* prioritized to run at the same time as any filesystem constructors.
*/
static Cyg_Httpd_Init_Class httpd_initializer CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_IO_FS);
 
/* ----------------------------------------------------------------- */
/* Constructor, just calls the startup routine.
*/
 
Cyg_Httpd_Init_Class::Cyg_Httpd_Init_Class()
{
cyg_httpd_startup();
}
 
/* ----------------------------------------------------------------- */
/* end of httpd.c */
/v2_0/src/monitor.c
0,0 → 1,1483
/* =================================================================
*
* monitor.c
*
* An HTTP system monitor
*
* =================================================================
* ####ECOSGPLCOPYRIGHTBEGIN####
* -------------------------------------------
* This file is part of eCos, the Embedded Configurable Operating
* System.
* Copyright (C) 2002 Nick Garnett.
*
* eCos is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 or (at your option)
* any later version.
*
* eCos is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with eCos; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
* As a special exception, if other files instantiate templates or
* use macros or inline functions from this file, or you compile this
* file and link it with other works to produce a work based on this
* file, this file does not by itself cause the resulting work to be
* covered by the GNU General Public License. However the source code
* for this file must still be made available in accordance with
* section (3) of the GNU General Public License.
*
* This exception does not invalidate any other reasons why a work
* based on this file might be covered by the GNU General Public
* License.
*
* -------------------------------------------
* ####ECOSGPLCOPYRIGHTEND####
* =================================================================
* #####DESCRIPTIONBEGIN####
*
* Author(s): nickg@calivar.com
* Contributors: nickg@calivar.com
* Date: 2002-10-14
* Purpose:
* Description:
*
* ####DESCRIPTIONEND####
*
* =================================================================
*/
 
#include <pkgconf/system.h>
#include <pkgconf/isoinfra.h>
#include <pkgconf/net.h>
#include <pkgconf/httpd.h>
#include <pkgconf/kernel.h>
 
#include <cyg/infra/cyg_trac.h> /* tracing macros */
#include <cyg/infra/cyg_ass.h> /* assertion macros */
 
#include <cyg/httpd/httpd.h>
 
#include <cyg/kernel/kapi.h>
#ifdef CYGPKG_KERNEL_INSTRUMENT
#include <cyg/kernel/instrmnt.h>
#include <cyg/kernel/instrument_desc.h>
#endif
 
#include <unistd.h>
#include <ctype.h>
 
/* ================================================================= */
/* Include all the necessary network headers by hand. We need to do
* this so that _KERNEL is correctly defined, or not, for specific
* headers so we can use both the external API and get at internal
* kernel structures.
*/
 
#define _KERNEL
#include <sys/param.h>
#undef _KERNEL
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/errno.h>
#include <sys/time.h>
 
#define _KERNEL
 
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <net/route.h>
#include <net/if_dl.h>
 
#include <sys/protosw.h>
#include <netinet/in_pcb.h>
#include <netinet/udp.h>
#include <netinet/tcp.h>
#include <netinet/tcp_timer.h>
#include <netinet/ip_var.h>
#include <netinet/icmp_var.h>
#include <netinet/udp_var.h>
#include <netinet/tcp_var.h>
 
#include <cyg/io/eth/eth_drv_stats.h>
 
/* ================================================================= */
/* Use this when a thread appears to have no name.
*/
 
#define NULL_THREAD_NAME "----------"
 
/* ================================================================= */
/* Draw navigation bar
*
* This draws a simple table containing links to the various monitor
* pages at the current position in the HTML stream.
*/
 
static void draw_navbar( FILE *client )
{
html_para_begin( client, "" );
html_table_begin( client, "border cellpadding=\"4\"" );
{
html_table_row_begin(client, "" );
{
html_table_data_begin( client, "" );
html_image( client, "/monitor/ecos.gif", "eCos logo", "" );
html_table_data_begin( client, "" );
html_url( client, "Threads", "/monitor/threads.html");
html_table_data_begin( client, "" );
html_url( client, "Interrupts", "/monitor/interrupts.html");
html_table_data_begin( client, "" );
html_url( client, "Memory", "/monitor/memory.html");
html_table_data_begin( client, "" );
html_url( client, "Network", "/monitor/network.html");
#ifdef CYGPKG_KERNEL_INSTRUMENT
html_table_data_begin( client, "" );
html_url( client, "Instrumentation", "/monitor/instrument.html");
#endif
}
html_table_row_end( client );
}
html_table_end( client );
}
 
/* ================================================================= */
/* Index page
*
* A simple introductory page matching "/monitor" and
* "/monitor/index.html".
*/
 
static char monitor_index_blurb[] =
"<p>This is the eCos System Monitor. It presents a simple web monitor
and control interface for eCos systems.\n"
"<p>Use the navigation bar at the bottom of each page to explore."
;
 
static cyg_bool cyg_monitor_index( FILE * client, char *filename,
char *formdata, void *arg )
{
html_begin(client);
 
html_head(client,"eCos System Monitor", "");
 
html_body_begin(client,"");
{
html_heading(client, 2, "eCos System Monitor" );
 
fputs( monitor_index_blurb, client );
draw_navbar(client);
}
html_body_end(client);
 
html_end(client);
return 1;
}
 
CYG_HTTPD_TABLE_ENTRY( cyg_monitor_entry,
"/monitor",
cyg_monitor_index,
NULL );
 
CYG_HTTPD_TABLE_ENTRY( cyg_monitor_index_entry,
"/monitor/index.html",
cyg_monitor_index,
NULL );
 
/* ================================================================= */
/* Thread Monitor
*
* Uses the kapi thread info API to enumerate all the current threads
* and generate a table showing their state.
*/
 
static cyg_bool cyg_monitor_threads( FILE * client, char *filename,
char *formdata, void *arg )
{
html_begin(client);
 
/* html_head(client,"Thread Monitor", "<meta http-equiv=\"refresh\" content=\"10\">"); */
html_head(client,"eCos Thread Monitor", "");
 
html_body_begin(client,"");
{
html_heading(client, 2, "Thread Monitor" );
 
html_table_begin( client, "border" );
{
cyg_handle_t thread = 0;
cyg_uint16 id = 0;
html_table_header( client, "Id", "" );
html_table_header( client, "State", "" );
html_table_header( client, "Set<br>Priority", "" );
html_table_header( client, "Current<br>Priority", "" );
html_table_header( client, "Name", "" );
html_table_header( client, "Stack Base", "" );
html_table_header( client, "Stack Size", "" );
#ifdef CYGFUN_KERNEL_THREADS_STACK_MEASUREMENT
html_table_header( client, "Stack Used", "" );
#endif
/* Loop over the threads, and generate a table row for
* each.
*/
while( cyg_thread_get_next( &thread, &id ) )
{
cyg_thread_info info;
char *state_string;
 
cyg_thread_get_info( thread, id, &info );
if( info.name == NULL )
info.name = NULL_THREAD_NAME;
 
/* Translate the state into a string.
*/
if( info.state == 0 )
state_string = "RUN";
else if( info.state & 0x04 )
state_string = "SUSP";
else switch( info.state & 0x1b )
{
case 0x01: state_string = "SLEEP"; break;
case 0x02: state_string = "CNTSLEEP"; break;
case 0x08: state_string = "CREATE"; break;
case 0x10: state_string = "EXIT"; break;
default: state_string = "????"; break;
}
 
/* Now generate the row.
*/
html_table_row_begin(client, "" );
{
html_table_data_begin( client, "" );
fprintf( client, "<a href=\"/monitor/thread-%04x.html\">%04x</a>\n", id,id);
html_table_data_begin( client, "" );
fprintf( client, "%s", state_string);
html_table_data_begin( client, "" );
fprintf( client, "%d", info.set_pri);
html_table_data_begin( client, "" );
fprintf( client, "%d", info.cur_pri);
html_table_data_begin( client, "" );
fputs( info.name, client );
html_table_data_begin( client, "" );
fprintf( client, "%08x", info.stack_base );
html_table_data_begin( client, "" );
fprintf( client, "%d", info.stack_size );
#ifdef CYGFUN_KERNEL_THREADS_STACK_MEASUREMENT
html_table_data_begin( client, "" );
fprintf( client, "%d", info.stack_used );
#endif
}
html_table_row_end(client);
}
}
html_table_end( client );
 
draw_navbar(client);
}
html_body_end(client);
 
html_end(client);
return 1;
}
 
CYG_HTTPD_TABLE_ENTRY( cyg_monitor_show_threads,
"/monitor/threads.htm*",
cyg_monitor_threads,
NULL );
 
/* ================================================================= */
/* Thread edit page
*
* A page on which the thread's state may be edited. This tests forms
* handling.
*/
 
static char thread_edit_blurb[] =
"<p>This table contains an entry for each property of the thread
that you can edit. The properties are:\n"
"<p><b>State:</b> Change thread's state. The <em>Suspend</em> button
will suspend the thread. The <em>Run</em> button will undo any previous
suspends. The <em>Release</em> button will release the thread out of
any sleep it is currently in.\n"
"<p><b>Priority:</b> Change the thread's priority.\n"
"<p>Once the new state has been selected, press the <em>Submit</em>
button to make the change, or <em>Reset</em> to clear it."
;
 
static cyg_bool cyg_monitor_thread_edit( FILE * client, char *filename,
char *formdata, void *arg )
{
/* If any form data has been supplied, then change the thread's
* state accordingly.
*/
if( formdata != NULL )
{
char *formlist[6];
char *state;
char *pri_string;
char *id_string;
cyg_handle_t thread = 0;
cyg_uint16 id;
 
/* Parse the data */
cyg_formdata_parse( formdata, formlist, 6 );
 
/* Get the thread id from the hidden control */
id_string = cyg_formlist_find( formlist, "thread");
 
sscanf( id_string, "%04hx", &id );
 
thread = cyg_thread_find( id );
 
/* If there is a pri field, change the priority */
pri_string = cyg_formlist_find( formlist, "pri");
 
if( pri_string != NULL )
{
cyg_priority_t pri;
 
sscanf( pri_string, "%d", &pri );
 
cyg_thread_set_priority( thread, pri );
}
 
/* If there is a state field, change the thread state */
state = cyg_formlist_find( formlist, "state");
 
if( state != NULL )
{
if( strcmp( state, "run" ) == 0 )
cyg_thread_resume( thread );
if( strcmp( state, "suspend" ) == 0 )
cyg_thread_suspend( thread );
if( strcmp( state, "release" ) == 0 )
cyg_thread_release( thread );
}
}
 
/* Now generate a page showing the current thread state, and
* including form controls to change it.
*/
html_begin(client);
 
html_head(client,"eCos Thread Editor", "");
 
html_body_begin(client,"");
{
cyg_uint16 id;
cyg_thread_info info;
cyg_handle_t thread = 0;
char idbuf[16];
sscanf( filename, "/monitor/thread-%04hx.html", &id );
 
thread = cyg_thread_find( id );
cyg_thread_get_info(thread, id, &info );
html_heading(client, 2, "Thread State Editor" );
 
html_para_begin( client, "" );
fprintf( client, "Editing Thread %04x %s\n",id,
info.name?info.name:NULL_THREAD_NAME);
 
fputs( thread_edit_blurb, client );
html_form_begin( client, filename, "" );
{
html_table_begin( client, "border" );
{
html_table_header( client, "Property", "" );
html_table_header( client, "Value", "" );
 
html_table_row_begin(client, "" );
{
html_table_data_begin( client, "" );
fputs( "State", client );
 
html_table_data_begin( client, "" );
 
html_form_input_radio( client, "state", "run", (info.state&0x04)==0 );
fputs( "Run", client );
html_form_input_radio( client, "state", "suspend", (info.state&0x04)!=0 );
fputs( "Suspend", client );
html_form_input_radio( client, "state", "release", 0 );
fputs( "Release", client );
}
html_table_row_end( client );
 
html_table_row_begin(client, "" );
{
html_table_data_begin( client, "" );
fputs( "Priority", client );
 
html_table_data_begin( client, "" );
fprintf(client,"<input type=\"text\" name=\"pri\" size=\"10\" value=\"%d\">\n",
info.set_pri);
}
html_table_row_end( client );
 
}
html_table_end( client );
 
/* Add submit and reset buttons */
html_form_input(client, "submit", "submit", "Submit", "");
html_form_input(client, "reset", "reset", "Reset", "");
 
/* Pass the thread ID through to our next incarnation */
sprintf( idbuf, "%04x", id );
html_form_input_hidden(client, "thread", idbuf );
 
}
html_form_end( client );
draw_navbar(client);
}
html_body_end(client);
 
html_end(client);
return 1;
}
 
CYG_HTTPD_TABLE_ENTRY( cyg_monitor_thread_edit_entry,
"/monitor/thread-*",
cyg_monitor_thread_edit,
NULL );
 
/* ================================================================= */
/* Interrupt monitor
*
* At present this just generates a table showing which interrupts
* have an ISR attached.
*/
 
static cyg_bool cyg_monitor_interrupts( FILE * client, char *filename,
char *formdata, void *arg )
{
html_begin(client);
 
html_head(client,"eCos Interrupt Monitor", "");
 
html_body_begin(client,"");
{
html_heading(client, 2, "Interrupt Monitor" );
 
html_table_begin( client, "border" );
{
int i;
int maxint = CYGNUM_HAL_ISR_MAX;
 
#ifdef CYGPKG_HAL_I386
maxint = CYGNUM_HAL_ISR_MIN+16;
#endif
html_table_header( client, "ISR", "" );
html_table_header( client, "State", "" );
for( i = CYGNUM_HAL_ISR_MIN; i <= maxint ; i++ )
{
cyg_bool_t inuse;
HAL_INTERRUPT_IN_USE( i, inuse );
 
html_table_row_begin(client, "" );
{
html_table_data_begin( client, "" );
fprintf( client, "%d", i);
html_table_data_begin( client, "" );
fprintf( client, "%s", inuse?"In Use":"Free");
}
html_table_row_end( client );
}
}
html_table_end( client );
 
draw_navbar(client);
}
html_body_end(client);
 
html_end(client);
return 1;
}
 
CYG_HTTPD_TABLE_ENTRY( cyg_monitor_interrupts_entry,
"/monitor/interrupts.htm*",
cyg_monitor_interrupts,
NULL );
 
/* ================================================================= */
/* Memory monitor
*
* Generates a table showing a 256 byte page of memory. Form controls
* allow changes to the base address and display element size.
*/
 
static cyg_bool cyg_monitor_memory( FILE * client, char *filename,
char *formdata, void *arg )
{
char *formlist[10];
cyg_uint32 base = 0;
unsigned int datasize = 1;
int size = 256;
char *p;
cyg_formdata_parse( formdata, formlist, 10 );
 
p = cyg_formlist_find( formlist, "base" );
 
if( p != NULL )
sscanf( p, "%x", &base );
 
p = cyg_formlist_find( formlist, "datasize" );
 
if( p != NULL )
sscanf( p, "%x", &datasize );
 
if( cyg_formlist_find( formlist, "next" ) != NULL )
base += size;
 
if( cyg_formlist_find( formlist, "prev" ) != NULL )
base -= size;
html_begin(client);
 
html_head(client,"eCos Memory Monitor", "");
 
html_body_begin(client,"");
{
html_heading(client, 2, "Memory Monitor" );
 
html_form_begin( client, "/monitor/memory.html", "" );
{
 
/* Text input control for base address
*/
html_para_begin( client, "" );
fprintf(client,
"Base Address: 0x<input type=\"text\" name=\"base\" size=\"10\" value=\"%x\">\n",
base);
 
/* A little menu for the element size
*/
html_para_begin( client, "" );
 
fputs( "Element Size: ", client );
html_form_select_begin( client, "datasize", "" );
html_form_option( client, "1", "bytes", datasize==1 );
html_form_option( client, "2", "words", datasize==2 );
html_form_option( client, "4", "dwords", datasize==4 );
html_form_select_end( client );
html_para_begin( client, "" );
 
/* Submit and reset buttons
*/
html_form_input(client, "submit", "submit", "Submit", "");
html_form_input(client, "reset", "reset", "Reset", "");
 
html_para_begin( client, "" );
 
/* Previous page button */
html_form_input(client, "submit", "prev", "Prev Page", "");
 
/* Switch to monospaced font */
cyg_html_tag_begin( client, "font", "face=\"monospace\"" );
html_table_begin( client, "" );
{
cyg_addrword_t loc;
cyg_addrword_t oloc;
for( oloc = loc = base; loc <= (base+size) ; loc++ )
{
if( ( loc % 16 ) == 0 )
{
if( loc != base )
{
html_table_data_begin( client, "" );
for( ; oloc < loc; oloc++ )
{
char c = *(char *)oloc;
if( !isprint(c) )
c = '.';
putc( c, client );
}
html_table_row_end( client );
}
if( loc == (base+size) )
break;
html_table_row_begin(client, "" );
html_table_data_begin( client, "" );
fprintf( client, "%08x:",loc);
}
 
html_table_data_begin( client, "" );
 
if( (loc % datasize) == 0 )
{
switch( datasize )
{
case 1: fprintf( client, "%02x", *(cyg_uint8 *)loc ); break;
case 2: fprintf( client, "%04x", *(cyg_uint16 *)loc ); break;
case 4: fprintf( client, "%08x", *(cyg_uint32 *)loc ); break;
}
}
}
}
html_table_end( client );
cyg_html_tag_end( client, "font" );
html_form_input(client, "submit", "next", "Next Page", "");
}
html_form_end( client );
 
draw_navbar(client);
}
html_body_end(client);
 
html_end(client);
return 1;
}
 
CYG_HTTPD_TABLE_ENTRY( cyg_monitor_memory_entry,
"/monitor/memory.htm*",
cyg_monitor_memory,
NULL );
 
/* ================================================================= */
/* Network Monitor
*
* This function generates a page containing information about the
* network interfaces and the protocols.
*/
 
static cyg_bool cyg_monitor_network( FILE * client, char *filename,
char *formdata, void *arg )
{
struct ifconf ifconf;
char conf[256];
int err;
int sock;
 
/* Start by opening a socket and getting a list of all the
* interfaces present.
*/
{
memset( conf, 0, sizeof(conf) );
sock = socket( AF_INET, SOCK_DGRAM, 0 );
ifconf.ifc_len = sizeof(conf);
ifconf.ifc_buf = (caddr_t)conf;
 
err = ioctl( sock, SIOCGIFCONF, &ifconf );
}
html_begin(client);
 
html_head(client,"eCos Network Monitor", "");
 
html_body_begin(client,"");
{
html_heading(client, 2, "Network Monitor" );
 
html_heading(client, 3, "Interfaces" );
 
html_table_begin( client, "border" );
{
int i;
struct ifreq *ifrp;
struct sockaddr *sa;
html_table_header( client, "Interface", "" );
html_table_header( client, "Status", "" );
 
ifrp = ifconf.ifc_req;
while( ifconf.ifc_len && ifrp->ifr_name[0] )
{
struct ifreq ifreq = *ifrp;
 
/* For some reason we get two entries for each
* interface in the list: one with an AF_INET address
* and one with an AF_LINK address. We are currently
* only interested in the AF_INET ones.
*/
if( ifrp->ifr_addr.sa_family == AF_INET )
{
html_table_row_begin(client, "" );
{
html_table_data_begin( client, "" );
fprintf( client, "%s", ifrp->ifr_name);
 
html_table_data_begin( client, "" );
html_table_begin( client, "" );
{
struct ether_drv_stats ethstats;
 
/* Get the interface's flags and display
* the interesting ones.
*/
if( ioctl( sock, SIOCGIFFLAGS, &ifreq ) >= 0 )
{
html_table_row_begin(client, "" );
fprintf( client, "<td>Flags<td>\n" );
for( i = 0; i < 16; i++ )
{
switch( ifreq.ifr_flags & (1<<i) )
{
default: break;
case IFF_UP: fputs( " UP", client ); break;
case IFF_BROADCAST: fputs( " BROADCAST", client ); break;
case IFF_DEBUG: fputs( " DEBUG", client ); break;
case IFF_LOOPBACK: fputs( " LOOPBACK", client ); break;
case IFF_PROMISC: fputs( " PROMISCUOUS", client ); break;
case IFF_RUNNING: fputs( " RUNNING", client ); break;
case IFF_SIMPLEX: fputs( " SIMPLEX", client ); break;
case IFF_MULTICAST: fputs( " MULTICAST", client ); break;
}
}
html_table_row_end( client );
}
 
/* Get the interface's address and display it. */
if( ioctl( sock, SIOCGIFADDR, &ifreq ) >= 0 )
{
struct sockaddr_in *inaddr =
(struct sockaddr_in *)&ifreq.ifr_addr;
 
html_table_row_begin(client, "" );
fprintf( client, "<td>Address<td>%s\n",
inet_ntoa(inaddr->sin_addr));
html_table_row_end( client );
}
 
/* If there's a netmask, show that. */
if( ioctl( sock, SIOCGIFNETMASK, &ifreq ) >= 0 )
{
struct sockaddr_in *inaddr =
(struct sockaddr_in *)&ifreq.ifr_addr;
 
html_table_row_begin(client, "" );
fprintf( client, "<td>Mask<td>%s\n",
inet_ntoa(inaddr->sin_addr));
html_table_row_end( client );
}
 
/* If there's a broadcast address, show that. */
if( ioctl( sock, SIOCGIFBRDADDR, &ifreq ) >= 0 )
{
struct sockaddr_in *inaddr =
(struct sockaddr_in *)&ifreq.ifr_broadaddr;
 
html_table_row_begin(client, "" );
fprintf( client, "<td>Broadcast Address<td>%s\n",
inet_ntoa(inaddr->sin_addr));
html_table_row_end( client );
}
 
/* If the ethernet driver collects
* statistics, fetch those and show some
* of them.
*/
ethstats.ifreq = ifreq;
if( ioctl( sock, SIOCGIFSTATS, &ethstats ) >= 0 )
{
fprintf( client, "<tr><td>Hardware<td>%s</tr>\n",
ethstats.description );
fprintf( client, "<tr><td>Packets Received<td>%d</tr>\n",
ethstats.rx_count );
fprintf( client, "<tr><td>Packets Sent<td>%d</tr>\n",
ethstats.tx_count );
fprintf( client, "<tr><td>Interrupts<td>%d</tr>\n",
ethstats.interrupts );
}
}
html_table_end( client );
}
html_table_row_end( client );
 
}
 
/* Scan the addresses, even if we are not interested
* in this interface, since we must skip to the next.
*/
do
{
sa = &ifrp->ifr_addr;
if (sa->sa_len <= sizeof(*sa)) {
ifrp++;
} else {
ifrp=(struct ifreq *)(sa->sa_len + (char *)sa);
ifconf.ifc_len -= sa->sa_len - sizeof(*sa);
}
ifconf.ifc_len -= sizeof(*ifrp);
 
} while (!ifrp->ifr_name[0] && ifconf.ifc_len);
}
}
html_table_end( client );
 
/* Now the protocols. For each of the main protocols: IP,
* ICMP, UDP, TCP print a table of useful information derived
* from the in-kernel data structures. Note that this only
* works for the BSD stacks.
*/
html_para_begin( client, "" );
html_heading(client, 3, "Protocols" );
 
html_para_begin( client, "" );
html_table_begin( client, "border");
{
html_table_header( client, "IP", "" );
html_table_header( client, "ICMP", "" );
html_table_header( client, "UDP", "" );
html_table_header( client, "TCP", "" );
 
html_table_row_begin(client, "" );
{
html_table_data_begin( client, "valign=\"top\"" );
html_table_begin( client, "" );
{
 
fprintf( client, "<tr><td><b>%s:</b><td></tr>\n", "Received" );
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "Total",
ipstat.ips_total );
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "Bad",
ipstat.ips_badsum+
ipstat.ips_tooshort+
ipstat.ips_toosmall+
ipstat.ips_badhlen+
ipstat.ips_badlen+
ipstat.ips_noproto+
ipstat.ips_toolong
);
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "Reassembled",
ipstat.ips_reassembled );
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "Delivered",
ipstat.ips_delivered );
 
fprintf( client, "<tr><td><b>%s:</b><td></tr>\n", "Sent" );
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "Total",
ipstat.ips_localout );
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "Raw",
ipstat.ips_rawout );
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "Fragmented",
ipstat.ips_fragmented );
}
html_table_end( client );
 
html_table_data_begin( client, "valign=\"top\"" );
html_table_begin( client, "" );
{
 
fprintf( client, "<tr><td><b>%s:</b><td></tr>\n", "Received" );
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "ECHO",
icmpstat.icps_inhist[ICMP_ECHO] );
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "ECHO REPLY",
icmpstat.icps_inhist[ICMP_ECHOREPLY] );
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "UNREACH",
icmpstat.icps_inhist[ICMP_UNREACH] );
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "REDIRECT",
icmpstat.icps_inhist[ICMP_REDIRECT] );
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "Other",
icmpstat.icps_inhist[ICMP_SOURCEQUENCH]+
icmpstat.icps_inhist[ICMP_ROUTERADVERT]+
icmpstat.icps_inhist[ICMP_ROUTERSOLICIT]+
icmpstat.icps_inhist[ICMP_TIMXCEED]+
icmpstat.icps_inhist[ICMP_PARAMPROB]+
icmpstat.icps_inhist[ICMP_TSTAMP]+
icmpstat.icps_inhist[ICMP_TSTAMPREPLY]+
icmpstat.icps_inhist[ICMP_IREQ]+
icmpstat.icps_inhist[ICMP_IREQREPLY]+
icmpstat.icps_inhist[ICMP_MASKREQ]+
icmpstat.icps_inhist[ICMP_MASKREPLY]
);
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "Bad",
icmpstat.icps_badcode+
icmpstat.icps_tooshort+
icmpstat.icps_checksum+
icmpstat.icps_badlen+
icmpstat.icps_bmcastecho
);
 
fprintf( client, "<tr><td><b>%s:</b><td></tr>\n", "Sent" );
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "ECHO",
icmpstat.icps_outhist[ICMP_ECHO] );
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "ECHO REPLY",
icmpstat.icps_outhist[ICMP_ECHOREPLY] );
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "UNREACH",
icmpstat.icps_outhist[ICMP_UNREACH] );
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "REDIRECT",
icmpstat.icps_outhist[ICMP_REDIRECT] );
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "Other",
icmpstat.icps_inhist[ICMP_SOURCEQUENCH]+
icmpstat.icps_outhist[ICMP_ROUTERADVERT]+
icmpstat.icps_outhist[ICMP_ROUTERSOLICIT]+
icmpstat.icps_outhist[ICMP_TIMXCEED]+
icmpstat.icps_outhist[ICMP_PARAMPROB]+
icmpstat.icps_outhist[ICMP_TSTAMP]+
icmpstat.icps_outhist[ICMP_TSTAMPREPLY]+
icmpstat.icps_outhist[ICMP_IREQ]+
icmpstat.icps_outhist[ICMP_IREQREPLY]+
icmpstat.icps_outhist[ICMP_MASKREQ]+
icmpstat.icps_outhist[ICMP_MASKREPLY]
);
}
html_table_end( client );
 
html_table_data_begin( client, "valign=\"top\"" );
html_table_begin( client, "" );
{
 
fprintf( client, "<tr><td><b>%s:</b><td></tr>\n", "Received" );
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "Total",
udpstat.udps_ipackets );
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "Bad",
udpstat.udps_hdrops+
udpstat.udps_badsum+
udpstat.udps_badlen+
udpstat.udps_noport+
udpstat.udps_noportbcast+
udpstat.udps_fullsock
);
fprintf( client, "<tr><td><b>%s:</b><td></tr>\n", "Sent" );
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "Total",
udpstat.udps_opackets );
}
html_table_end( client );
 
html_table_data_begin( client, "valign=\"top\"" );
html_table_begin( client, "" );
{
 
fprintf( client, "<tr><td><b>%s:</b><td></tr>\n", "Connections" );
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "Initiated",
tcpstat.tcps_connattempt );
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "Accepted",
tcpstat.tcps_accepts );
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "Established",
tcpstat.tcps_connects );
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "Closed",
tcpstat.tcps_closed );
 
fprintf( client, "<tr><td><b>%s:</b><td></tr>\n", "Received" );
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "Packets",
tcpstat.tcps_rcvtotal );
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "Data Packets",
tcpstat.tcps_rcvpack );
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "Bytes",
tcpstat.tcps_rcvbyte );
fprintf( client, "<tr><td><b>%s:</b><td></tr>\n", "Sent" );
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "Packets",
tcpstat.tcps_sndtotal );
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "Data Packets",
tcpstat.tcps_sndpack );
fprintf( client, "<tr><td>%s<td>%ld</tr>\n", "Bytes",
tcpstat.tcps_sndbyte );
 
}
html_table_end( client );
}
html_table_row_end( client );
 
}
html_table_end( client );
 
draw_navbar(client);
}
html_body_end(client);
 
html_end(client);
 
close( sock );
return 1;
}
 
CYG_HTTPD_TABLE_ENTRY( cyg_monitor_network_entry,
"/monitor/network.htm*",
cyg_monitor_network,
NULL );
 
/* ================================================================= */
/* Instrumentation Monitor
*
* If the CYGPKG_KERNEL_INSTRUMENT option is set, we generate a table
* showing the current instrumentation buffer. If the FLAGS option is
* enabled we also print a table giving control of the flags.
*
*/
 
#ifdef CYGPKG_KERNEL_INSTRUMENT
 
/* Instrumentation record. */
struct Instrument_Record
{
CYG_WORD16 type; // record type
CYG_WORD16 thread; // current thread id
CYG_WORD timestamp; // 32 bit timestamp
CYG_WORD arg1; // first arg
CYG_WORD arg2; // second arg
};
typedef struct Instrument_Record Instrument_Record;
 
/* Instrumentation variables, these live in the
* instrumentation files in the kernel
*/
__externC Instrument_Record *instrument_buffer_pointer;
__externC Instrument_Record instrument_buffer[];
__externC cyg_uint32 instrument_buffer_size;
 
#if defined(CYGDBG_KERNEL_INSTRUMENT_FLAGS) && \
defined(CYGDBG_KERNEL_INSTRUMENT_MSGS)
 
static cyg_uint32 instrument_flags[(CYG_INSTRUMENT_CLASS_MAX>>8)+1];
 
#endif
 
static char cyg_monitor_instrument_blurb1[] =
"<p>Use the checkboxes to enable the events to be recorded. Click
the <em>Submit</em> button to start recording. Click the <em>Clear</em>
button to clear all instrumentation and to stop recording."
;
 
static cyg_bool cyg_monitor_instrument( FILE * client, char *filename,
char *formdata, void *arg )
{
 
#if defined(CYGDBG_KERNEL_INSTRUMENT_FLAGS) && \
defined(CYGDBG_KERNEL_INSTRUMENT_MSGS)
 
/* Disable all instrumentation while we generate the page.
* Otherwise we could swamp the information we are really after.
*/
cyg_scheduler_lock();
{
struct instrument_desc_s *id = instrument_desc;
CYG_WORD cl = 0, ev = 0;
 
for( ; id->msg != 0; id++ )
{
if( id->num > 0xff )
{
cl = id->num>>8;
instrument_flags[cl] = 0;
}
else
{
ev = id->num;
cyg_instrument_disable( cl<<8, ev );
}
}
}
cyg_scheduler_unlock();
 
#endif
/* If we have some form data, deal with it.
*/
if( formdata != NULL )
{
char *list[40];
cyg_formdata_parse( formdata, list, sizeof(list)/sizeof(*list) );
 
#if defined(CYGDBG_KERNEL_INSTRUMENT_FLAGS) && \
defined(CYGDBG_KERNEL_INSTRUMENT_MSGS)
if( cyg_formlist_find( list, "clear" ) != NULL )
{
/* If the clear button is set, then disable all instrumentation flags.
*/
int i;
for( i = 0; i < sizeof(instrument_flags)/sizeof(*instrument_flags); i++ )
instrument_flags[i] = 0;
}
else
{
/* Otherwise all the set checkboxes have been reported to
* us in the form of class=event inputs.
*/
char **p;
for( p = list; *p != NULL; p++ )
{
int cl,ev;
if( sscanf( *p, "%02x=%02x", &cl, &ev ) == 2 )
instrument_flags[cl] |= 1<<ev;
}
}
#endif
/* If the cleartable button has been pressed, clear all the
* table entries.
*/
if( cyg_formlist_find( list, "cleartable" ) != NULL )
{
cyg_scheduler_lock();
{
Instrument_Record *ibp = instrument_buffer_pointer;
do
{
ibp->type = 0;
ibp++;
if( ibp == &instrument_buffer[instrument_buffer_size] )
ibp = instrument_buffer;
} while( ibp != instrument_buffer_pointer );
}
cyg_scheduler_unlock();
}
}
/* Now start generating the HTML page.
*/
html_begin(client);
 
html_head(client,"eCos Instrumentation Buffer", "");
 
html_body_begin(client,"");
{
html_heading(client, 2, "Instrumentation Buffer" );
 
html_form_begin( client, "/monitor/instrument.html", "" );
#if defined(CYGDBG_KERNEL_INSTRUMENT_FLAGS) && \
defined(CYGDBG_KERNEL_INSTRUMENT_MSGS)
/* If we have the flags enabled, generate a table showing all
* the flag names with a checkbox against each.
*/
 
fputs( cyg_monitor_instrument_blurb1, client );
html_para_begin( client, "" );
/* Add submit,clear and reset buttons */
html_form_input(client, "submit", "submit", "Submit", "");
html_form_input(client, "submit", "clear", "Clear", "");
html_form_input(client, "reset", "reset", "Reset", "");
html_table_begin( client, "border width=100%" );
{
struct instrument_desc_s *id = instrument_desc;
CYG_WORD cl = 0, ev = 0;
int clc = 0;
char class[5], event[5];
 
html_table_row_begin( client, "" );
 
for( ; id->msg != 0; id++ )
{
if( id->num > 0xff )
{
cl = id->num;
sprintf( class, "%02x", cl>>8 );
clc = 0;
if( id != instrument_desc )
{
html_table_end( client );
html_table_row_end( client );
html_table_row_begin( client, "" );
}
html_table_data_begin( client, "valign=\"top\" width=100%" );
html_table_begin( client, "width=100%" );
}
else
{
ev = id->num;
sprintf( event, "%02x", ev );
 
if( (clc%4) == 0 )
{
if( clc != 0 )
html_table_row_end( client );
 
html_table_row_begin( client, "" );
}
clc++;
html_table_data_begin( client, "width=25%" );
html_form_input_checkbox( client, class, event,
instrument_flags[cl>>8] & (1<<ev) );
fputs( id->msg, client );
}
}
html_table_end( client );
html_table_row_end( client );
}
html_table_end( client );
 
/* Add submit,clear and reset buttons */
html_form_input(client, "submit", "submit", "Submit", "");
html_form_input(client, "submit", "clear", "Clear", "");
html_form_input(client, "reset", "reset", "Reset", "");
 
#endif
 
html_para_begin( client, "" );
 
html_form_input(client, "submit", "cleartable", "Clear Table", "");
 
/*
*/
html_table_begin( client, "border" );
{
Instrument_Record *ibp = instrument_buffer_pointer;
 
html_table_header( client, "TIME", "" );
html_table_header( client, "THREAD", "" );
html_table_header( client, "EVENT", "" );
html_table_header( client, "ARG1", "" );
html_table_header( client, "ARG2", "" );
 
do
{
if( ibp->type != 0 )
{
html_table_row_begin(client, "" );
{
cyg_handle_t thread = cyg_thread_find(ibp->thread);
cyg_thread_info info;
html_table_data_begin( client, "" );
fprintf( client, "%08x",ibp->timestamp);
html_table_data_begin( client, "" );
if( thread != 0 &&
cyg_thread_get_info( thread, ibp->thread, &info ) &&
info.name != NULL )
fputs( info.name, client );
else fprintf( client, "[%04x]", ibp->thread);
html_table_data_begin( client, "" );
#if defined(CYGDBG_KERNEL_INSTRUMENT_MSGS)
fprintf( client, "%s", cyg_instrument_msg(ibp->type));
#else
fprintf( client, "%04x", ibp->type );
#endif
html_table_data_begin( client, "" );
fprintf( client, "%08x", ibp->arg1);
html_table_data_begin( client, "" );
fprintf( client, "%08x", ibp->arg2);
}
html_table_row_end( client );
}
ibp++;
if( ibp == &instrument_buffer[instrument_buffer_size] )
ibp = instrument_buffer;
} while( ibp != instrument_buffer_pointer );
}
html_table_end( client );
 
html_para_begin( client, "" );
 
html_form_input(client, "submit", "cleartable", "Clear Table", "");
html_form_end( client );
draw_navbar(client);
}
html_body_end(client);
 
html_end(client);
 
 
#if defined(CYGDBG_KERNEL_INSTRUMENT_FLAGS) && \
defined(CYGDBG_KERNEL_INSTRUMENT_MSGS)
 
/*
*/
 
cyg_scheduler_lock();
{
struct instrument_desc_s *id = instrument_desc;
CYG_WORD cl = 0, ev = 0;
 
for( ; id->msg != 0; id++ )
{
if( id->num > 0xff )
cl = id->num>>8;
else
{
ev = id->num;
if( (instrument_flags[cl] & (1<<ev)) != 0 )
cyg_instrument_enable( cl<<8, ev );
}
}
}
cyg_scheduler_unlock();
#endif
return true;
}
 
CYG_HTTPD_TABLE_ENTRY( cyg_monitor_instrument_entry,
"/monitor/instrument.htm*",
cyg_monitor_instrument,
NULL );
 
#endif
 
/* ================================================================= */
/* eCos Logo
*
* Define the logo as a byte array, and then define the data structure
* and table entry to allow it to be fetched by the client.
*/
 
static cyg_uint8 ecos_logo_gif[] = {
0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x6f, 0x00, 0x23, 0x00, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xea, 0x19, 0x00, 0xcc, 0x00, 0x00, 0xfd, 0xfd, 0xfd, 0x83, 0x00, 0x00, 0xf6,
0xf6, 0xf6, 0x2f, 0x2f, 0x2f, 0xef, 0xef, 0xef, 0x19, 0x00, 0x19, 0x45, 0x45, 0x45, 0xbb, 0xbb,
0xbb, 0xe2, 0x3e, 0x3e, 0xe8, 0xbb, 0xd3, 0x3e, 0x3e, 0x3e, 0xfb, 0xfb, 0xfb, 0xbe, 0xbe, 0xbe,
0xf1, 0xed, 0xed, 0xe5, 0x7b, 0x8e, 0xe5, 0x6b, 0x7b, 0xcc, 0xcc, 0xcc, 0x98, 0x95, 0x98, 0xc6,
0xc3, 0xc6, 0x19, 0x19, 0x19, 0xf1, 0xf1, 0xf1, 0x98, 0x98, 0x98, 0xd6, 0xd3, 0xd6, 0x83, 0x83,
0x83, 0xde, 0xde, 0xde, 0xe5, 0x25, 0x25, 0x73, 0x6f, 0x73, 0xea, 0xea, 0xea, 0xe5, 0x8e, 0xa2,
0xe8, 0xe8, 0xe8, 0x7f, 0x7b, 0x7f, 0xe2, 0x56, 0x66, 0x8b, 0x8b, 0x8b, 0x19, 0x19, 0x00, 0xf8,
0xf8, 0xf8, 0x73, 0x73, 0x73, 0xd3, 0xd1, 0xd1, 0x9c, 0x9c, 0x9c, 0x50, 0x50, 0x50, 0xef, 0xce,
0xea, 0x92, 0x8e, 0x92, 0x6f, 0x6f, 0x6f, 0xe2, 0x2f, 0x2f, 0x61, 0x61, 0x61, 0xe5, 0xe5, 0xe5,
0xe8, 0x9f, 0xb8, 0x37, 0x2f, 0x37, 0x66, 0x66, 0x66, 0xe2, 0x4b, 0x50, 0x56, 0x50, 0x56, 0xa9,
0xa5, 0xa9, 0xce, 0xce, 0xce, 0x56, 0x50, 0x50, 0xd9, 0xd9, 0xd9, 0x77, 0x73, 0x77, 0x25, 0x25,
0x2f, 0x6b, 0x6b, 0x6b, 0x9f, 0x9f, 0x9f, 0x87, 0x83, 0x87, 0x3e, 0x37, 0x37, 0xf4, 0xf4, 0xf4,
0x25, 0x25, 0x25, 0xc1, 0xc1, 0xc1, 0x83, 0x7f, 0x83, 0xe5, 0xe2, 0xe2, 0x4b, 0x45, 0x4b, 0xd1,
0xce, 0xd1, 0xaf, 0xac, 0xaf, 0xcc, 0xc9, 0xcc, 0x5b, 0x56, 0x5b, 0xdb, 0xd9, 0xdb, 0x66, 0x61,
0x66, 0xe2, 0xe2, 0xe2, 0xb8, 0xb5, 0xb8, 0x2f, 0x25, 0x2f, 0xc3, 0xc1, 0xc3, 0xe0, 0xde, 0xe0,
0xd3, 0xd3, 0xd3, 0xde, 0xdb, 0xde, 0xac, 0xac, 0xac, 0xce, 0xcc, 0xce, 0x77, 0x6f, 0x73, 0x4b,
0x45, 0x45, 0xc9, 0xc6, 0xc9, 0x45, 0x3e, 0x45, 0x61, 0x5b, 0x61, 0xb5, 0xb2, 0xb5, 0x3e, 0x00,
0x00, 0x8b, 0x87, 0x87, 0x95, 0x92, 0x95, 0xa2, 0x9f, 0xa2, 0xb8, 0xb8, 0xb8, 0x7b, 0x77, 0x7b,
0x9c, 0x98, 0x9c, 0x50, 0x4b, 0x50, 0x6f, 0x6b, 0x6f, 0x6b, 0x66, 0x6b, 0xac, 0xa9, 0xac, 0x8e,
0x8b, 0x8e, 0x8e, 0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xed, 0xed, 0xed, 0x50, 0x4b, 0x4b, 0x3e, 0x37,
0x3e, 0x95, 0x95, 0x95, 0xa5, 0xa2, 0xa5, 0x9f, 0x9c, 0x9f, 0xc1, 0xbe, 0xbe, 0x2f, 0x25, 0x25,
0xd3, 0xd1, 0xd3, 0xf4, 0xf1, 0xf4, 0xc6, 0xc6, 0xc6, 0x8e, 0x8e, 0x8e, 0x25, 0x19, 0x19, 0x66,
0x61, 0x61, 0xb2, 0xaf, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00,
0x00, 0x00, 0x6f, 0x00, 0x23, 0x00, 0x40, 0x08, 0xff, 0x00, 0x03, 0x08, 0x1c, 0x28, 0x10, 0x41,
0x8a, 0x17, 0x0e, 0x1c, 0x00, 0x58, 0xc8, 0xb0, 0xa1, 0xc3, 0x87, 0x10, 0x21, 0x12, 0x14, 0x28,
0xa0, 0xa2, 0xc5, 0x8b, 0x18, 0x33, 0x6a, 0xdc, 0xb8, 0x91, 0x01, 0x83, 0x11, 0x31, 0x26, 0x12,
0x44, 0x10, 0x91, 0xe1, 0x09, 0x91, 0x28, 0x03, 0x4c, 0xb9, 0x50, 0x72, 0xa1, 0x0a, 0x04, 0x29,
0x09, 0x72, 0x6c, 0x10, 0x73, 0xe2, 0x88, 0x8d, 0x2e, 0x0c, 0xd4, 0x0c, 0x70, 0x73, 0x63, 0x80,
0x88, 0x10, 0x76, 0x0a, 0x6d, 0x18, 0x94, 0x60, 0x03, 0x8e, 0x1a, 0x27, 0x4a, 0x40, 0x5a, 0x51,
0xa9, 0xc5, 0x0e, 0x3b, 0x0d, 0x30, 0x40, 0xca, 0x40, 0x45, 0xc9, 0x14, 0x42, 0x45, 0x72, 0x60,
0xf9, 0xf0, 0x64, 0xd6, 0x00, 0x19, 0x3b, 0xe8, 0xfc, 0x3a, 0x70, 0xe9, 0x45, 0x10, 0x59, 0x0d,
0x70, 0x9c, 0x30, 0xf1, 0x44, 0xcb, 0xb7, 0x70, 0x4b, 0x8a, 0x64, 0x4a, 0xb7, 0xae, 0x5d, 0x01,
0x6c, 0x51, 0xbe, 0x88, 0xcb, 0xb7, 0xef, 0xc2, 0xb9, 0x77, 0x03, 0x0b, 0xbe, 0x98, 0x37, 0xc0,
0x81, 0x88, 0x58, 0x09, 0xde, 0xe0, 0xea, 0xf0, 0xc5, 0x44, 0x0e, 0x0f, 0x13, 0x13, 0x34, 0x30,
0x21, 0x23, 0xdb, 0x8c, 0x63, 0x07, 0x4a, 0xcd, 0x88, 0xd6, 0xa9, 0x45, 0x9a, 0x04, 0x69, 0x60,
0xec, 0xc0, 0x94, 0x41, 0x44, 0xaf, 0x03, 0x53, 0xf8, 0xdd, 0xd1, 0x10, 0xf5, 0xc0, 0xa9, 0x76,
0x41, 0x0f, 0x24, 0xcd, 0xb1, 0xf3, 0xc0, 0x9e, 0x1c, 0x25, 0x88, 0xac, 0xac, 0x91, 0x41, 0x00,
0xc8, 0x6f, 0x77, 0x48, 0x9e, 0x78, 0xc3, 0xaa, 0xdf, 0x03, 0x27, 0xa6, 0x40, 0x28, 0x2a, 0x13,
0xe9, 0x08, 0xd9, 0x93, 0x41, 0xd0, 0xe6, 0xd8, 0x41, 0x42, 0x83, 0x15, 0x02, 0x0d, 0x34, 0xe0,
0x8d, 0x34, 0x73, 0x6a, 0xc6, 0x7e, 0xc3, 0x3b, 0xff, 0x04, 0x3c, 0xb8, 0x3c, 0x5d, 0xdb, 0x03,
0xb7, 0xc2, 0x7d, 0x91, 0x02, 0xa6, 0xe2, 0x13, 0xe0, 0xf9, 0x22, 0x3f, 0xe1, 0x9a, 0x22, 0xd3,
0x09, 0xd0, 0x03, 0x18, 0x00, 0x01, 0x9b, 0x2e, 0x48, 0xec, 0x01, 0x34, 0x10, 0xc3, 0x04, 0xd3,
0x69, 0xa4, 0xd3, 0x5e, 0x11, 0x39, 0x46, 0x96, 0x40, 0x53, 0x44, 0xa4, 0x02, 0x59, 0x1a, 0xe5,
0x97, 0x95, 0x68, 0x17, 0xd1, 0x80, 0x92, 0x77, 0xfd, 0x69, 0x34, 0x81, 0x83, 0x6d, 0x25, 0xe4,
0xe1, 0x87, 0x0e, 0x3c, 0x48, 0x90, 0x6a, 0x0c, 0x89, 0x48, 0x10, 0x77, 0x74, 0x85, 0x44, 0x10,
0x6e, 0x11, 0x4e, 0xd4, 0x9f, 0x84, 0x2b, 0x10, 0x68, 0x97, 0x69, 0x10, 0x31, 0x27, 0xd0, 0x72,
0x38, 0xe6, 0xa8, 0x63, 0x8e, 0x44, 0x4d, 0x74, 0xd4, 0x5d, 0x13, 0xa1, 0xe8, 0x13, 0x41, 0x31,
0x60, 0xe4, 0x02, 0x7a, 0x22, 0xa9, 0xd5, 0xd1, 0x61, 0x35, 0x4e, 0x84, 0x80, 0x42, 0x0e, 0x5d,
0x70, 0x83, 0x48, 0xac, 0xf5, 0xe8, 0xa3, 0x46, 0x2e, 0xac, 0x30, 0x9a, 0x48, 0x45, 0x66, 0xc4,
0x80, 0x77, 0x01, 0x74, 0x69, 0x91, 0x75, 0x05, 0x0a, 0x80, 0xa4, 0x59, 0x5e, 0x92, 0x54, 0x92,
0x94, 0x5f, 0x3d, 0xf9, 0x16, 0x09, 0x59, 0x6d, 0x44, 0x03, 0x98, 0x31, 0xfd, 0x48, 0x58, 0x56,
0x20, 0x20, 0x45, 0x90, 0x71, 0xe2, 0xf5, 0x39, 0xde, 0x44, 0xe6, 0x05, 0xea, 0xdf, 0x4e, 0x1c,
0x90, 0xe0, 0x40, 0x95, 0x7e, 0xf2, 0x45, 0x9e, 0xa0, 0xe6, 0x75, 0xc0, 0x80, 0x04, 0x00, 0x0a,
0x85, 0x00, 0x82, 0x89, 0x86, 0xb7, 0x28, 0xa3, 0x82, 0x4e, 0x40, 0x27, 0x41, 0x94, 0x56, 0x2a,
0xde, 0xa5, 0x98, 0x32, 0x5a, 0x58, 0x6a, 0x7d, 0xed, 0x90, 0x10, 0x93, 0x9e, 0x02, 0x00, 0x2a,
0x47, 0x2e, 0x78, 0x14, 0x2a, 0x53, 0xb6, 0x75, 0xff, 0x0a, 0x91, 0x03, 0x53, 0xc6, 0x84, 0x00,
0x09, 0x7c, 0x5d, 0x70, 0x82, 0x7b, 0x29, 0x21, 0x25, 0xc1, 0xa6, 0x03, 0x35, 0x90, 0x61, 0x46,
0x2e, 0x48, 0x18, 0xec, 0xb0, 0x16, 0xb1, 0x45, 0x62, 0x44, 0x70, 0x92, 0xb5, 0x58, 0x49, 0x0a,
0x0a, 0xb5, 0x91, 0xb1, 0x31, 0xa1, 0x79, 0x11, 0xb5, 0x03, 0x69, 0xc9, 0x51, 0x0c, 0x50, 0x3e,
0x74, 0x01, 0xaf, 0x05, 0x9d, 0x80, 0xaa, 0x0a, 0x36, 0x0a, 0x24, 0x2b, 0x00, 0xdf, 0xa2, 0xb4,
0x82, 0x04, 0x13, 0x4c, 0x00, 0x02, 0x80, 0x96, 0xa1, 0xb4, 0x5d, 0xbb, 0x20, 0xd0, 0xa9, 0xe4,
0x98, 0x3e, 0xd2, 0x46, 0x43, 0x03, 0x76, 0x76, 0x24, 0x17, 0x41, 0xea, 0x31, 0x3b, 0x11, 0x9f,
0xe8, 0xa2, 0xe4, 0xc2, 0x46, 0x2c, 0x0a, 0x30, 0xc2, 0x44, 0x06, 0x1c, 0xac, 0x21, 0xc3, 0xd7,
0x4e, 0x24, 0xe6, 0x8c, 0x02, 0x2f, 0xe8, 0x64, 0x43, 0xcd, 0x36, 0x67, 0xd7, 0x44, 0xda, 0x72,
0x64, 0x21, 0x41, 0x68, 0xea, 0x96, 0xd2, 0x76, 0x74, 0xd1, 0xf8, 0x50, 0xb9, 0x16, 0xff, 0xc4,
0x50, 0xb9, 0xfd, 0x32, 0xe5, 0x42, 0x90, 0x74, 0x5d, 0x69, 0xd1, 0xc2, 0x3b, 0x21, 0x6b, 0x91,
0xc9, 0x0e, 0x65, 0x2c, 0x10, 0xaa, 0xe2, 0x4d, 0xc1, 0x71, 0x60, 0x32, 0xb3, 0xea, 0x59, 0x46,
0x20, 0x6d, 0x6a, 0xb3, 0x00, 0x38, 0x37, 0xb4, 0x83, 0x48, 0xdd, 0x46, 0x09, 0x62, 0x42, 0x4a,
0x8b, 0xd4, 0x31, 0xb1, 0x18, 0x89, 0x1c, 0x2c, 0x47, 0xbe, 0x01, 0x7a, 0xde, 0xd0, 0x18, 0x31,
0xd0, 0x74, 0x43, 0x0e, 0xa0, 0x34, 0x85, 0x0a, 0x87, 0x39, 0x40, 0x02, 0xb8, 0x02, 0xe1, 0xea,
0x50, 0xd8, 0x49, 0x4a, 0x00, 0x1b, 0x0d, 0x9d, 0x71, 0x96, 0xe4, 0x04, 0x53, 0x75, 0x00, 0x37,
0x4a, 0x05, 0x42, 0xa5, 0x9f, 0xdb, 0x15, 0x8d, 0x61, 0x2a, 0xd0, 0xd1, 0x0c, 0x2c, 0x0b, 0x51,
0xad, 0x6d, 0xf2, 0xec, 0xd0, 0x70, 0x35, 0x61, 0x69, 0x71, 0xcb, 0x7a, 0x0b, 0x65, 0x2d, 0x46,
0x21, 0x11, 0x0c, 0x91, 0xce, 0x29, 0x41, 0x80, 0x68, 0x4b, 0x0e, 0xa0, 0xac, 0x35, 0x96, 0xd8,
0x96, 0xd5, 0x51, 0xe7, 0x8f, 0x63, 0x44, 0x73, 0x00, 0x6e, 0xc5, 0xa5, 0x02, 0x09, 0xa8, 0x93,
0xf0, 0xc2, 0xe5, 0x7e, 0xae, 0x1a, 0xd6, 0x08, 0x12, 0xc4, 0x2e, 0x01, 0x85, 0xaf, 0x66, 0x64,
0x75, 0x41, 0x5f, 0xa7, 0xaa, 0xe8, 0xe6, 0xb5, 0x0b, 0x3a, 0x3a, 0x4a, 0x37, 0xe4, 0xae, 0xfb,
0xbf, 0x1a, 0xf7, 0x3e, 0x18, 0x0d, 0x91, 0x0e, 0x14, 0x10, 0x00, 0x3b
};
 
CYG_HTTPD_DATA( cyg_monitor_ecos_logo_data,
"image/gif",
sizeof(ecos_logo_gif), ecos_logo_gif );
 
CYG_HTTPD_TABLE_ENTRY( cyg_monitor_ecos_logo,
"/monitor/ecos.gif",
cyg_httpd_send_data,
&cyg_monitor_ecos_logo_data );
 
/*------------------------------------------------------------------ */
/* end of monitor.c */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.