URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
Compare Revisions
- This comparison shows the changes necessary to convert path
/openrisc/trunk/rtos/ecos-2.0/packages/net/httpd/v2_0
- from Rev 27 to Rev 174
- ↔ Reverse comparison
Rev 27 → Rev 174
/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 |
/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 */ |
/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 <cyg/httpd/httpd.h> |
|
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 |
"/monitor/threads.html" will only match that exact filename, |
but the pattern "/monitor/thread-*" will match |
"/monitor/thread-0040.html", |
"/monitor/thread-0100.html" and any other filename starting |
with "/monitor/thread-". |
</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 |
"Server:" 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 "Server" field, and the |
values of <parameter>content_type</parameter> and |
<parameter>content_length</parameter> in the "Content-type" |
and "Content-length" 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 "text/html" content type followed by an opening |
"<html>" tag. <literal>html_end()</literal> generates |
a closing "</html>" 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 |
"name=value" 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[] = "<head><title>Welcome</title></head>\n" |
"<body><h2>Welcome to my Web Page</h2></body>\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, |
&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> |
/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. |
|
/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 */ |
/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 */ |
/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, ðstats ) >= 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 */ |