1 |
786 |
skrzyp |
|
2 |
|
|
|
3 |
|
|
|
4 |
|
|
|
5 |
|
|
|
6 |
|
|
|
7 |
|
|
|
8 |
|
|
|
9 |
|
|
|
10 |
|
|
|
11 |
|
|
|
12 |
|
|
|
13 |
|
|
|
14 |
|
|
|
15 |
|
|
|
16 |
|
|
|
17 |
|
|
|
18 |
|
|
|
19 |
|
|
|
20 |
|
|
|
21 |
|
|
|
22 |
|
|
|
23 |
|
|
|
24 |
|
|
|
25 |
|
|
|
26 |
|
|
|
27 |
|
|
|
28 |
|
|
|
29 |
|
|
|
30 |
|
|
|
31 |
|
|
Another Tiny HTTP Server for eCos
|
32 |
|
|
|
33 |
|
|
|
34 |
|
|
|
35 |
|
|
This package provides an extensible, small footprint, full featured HTTP
|
36 |
|
|
server for eCos. Many of these features can be
|
37 |
|
|
disabled via the configuration tool, thus reducing the footprint of the server.
|
38 |
|
|
The server has been written for the FreeBSD network stack.
|
39 |
|
|
|
40 |
|
|
|
41 |
|
|
|
42 |
|
|
|
43 |
|
|
The ATHTTP Server
|
44 |
|
|
|
45 |
|
|
Features
|
46 |
|
|
This ATHTTP implementation provides the following features:
|
47 |
|
|
|
48 |
|
|
GET, POST and HEAD Methods
|
49 |
|
|
File system Access
|
50 |
|
|
Callbacks to C functions
|
51 |
|
|
MIME type support
|
52 |
|
|
CGI mechanism through the OBJLOADER package or through a
|
53 |
|
|
simple tcl interpreter
|
54 |
|
|
Basic and Digest (MD5) Authentication
|
55 |
|
|
Directory Listing
|
56 |
|
|
Extendable Internal Resources
|
57 |
|
|
|
58 |
|
|
|
59 |
|
|
|
60 |
|
|
Ecos tables are used extensively throught the server to provide a high degree
|
61 |
|
|
of customization.
|
62 |
|
|
|
63 |
|
|
|
64 |
|
|
|
65 |
|
|
Starting the server
|
66 |
|
|
|
67 |
|
|
In order to start the web server, the user needs to call the function:
|
68 |
|
|
|
69 |
|
|
|
70 |
|
|
cyg_httpd_start();
|
71 |
|
|
|
72 |
|
|
|
73 |
|
|
in the application code. The server initialization code spawns a new
|
74 |
|
|
thread which calls init_all_network_interfaces() to
|
75 |
|
|
initialize the TCP/IP stack and then starts the deamon. The function is safe
|
76 |
|
|
to call multiple times.
|
77 |
|
|
|
78 |
|
|
|
79 |
|
|
|
80 |
|
|
|
81 |
|
|
MIME types
|
82 |
|
|
|
83 |
|
|
The server has an internal table with all the recognized mime types. Each time
|
84 |
|
|
a file or an internal resource is sent out by the server, its extension is
|
85 |
|
|
searched in this table and if a match is found, the associated MIME type is
|
86 |
|
|
then sent out in the header.
|
87 |
|
|
|
88 |
|
|
The server already provides entries for the following standard file extensions:
|
89 |
|
|
|
90 |
|
|
'html', 'htm', 'gif', 'jpg', 'css', 'js', 'png'
|
91 |
|
|
|
92 |
|
|
and the user is responsible for adding any further entry. The syntax for
|
93 |
|
|
adding an entry is the following:
|
94 |
|
|
|
95 |
|
|
|
96 |
|
|
CYG_HTTPD_MIME_TABLE_ENTRY(entry_label, extension_string, mime_tipe_sting);
|
97 |
|
|
|
98 |
|
|
entry table : an identifier unique to this entry
|
99 |
|
|
extension string : a string containing the extension for this entry
|
100 |
|
|
type_string : the mime string. The strings for many more mime types
|
101 |
|
|
is included in a file in the "doc" directory.
|
102 |
|
|
|
103 |
|
|
|
104 |
|
|
|
105 |
|
|
The following is an example of how to add the Adobe Portable Document Format
|
106 |
|
|
pdf MIME type to the table:
|
107 |
|
|
|
108 |
|
|
|
109 |
|
|
CYG_HTTPD_MIME_TABLE_ENTRY(hal_pdf_entry, "pdf", "application/pdf");
|
110 |
|
|
|
111 |
|
|
|
112 |
|
|
|
113 |
|
|
MIME Types for Chunked Frames
|
114 |
|
|
|
115 |
|
|
For chunked frames, which are generally used inside c language callbacks, there
|
116 |
|
|
is no file name to match an extension to, and thus the extension to be used
|
117 |
|
|
must be passed in the cyg_httpd_start_chunked() call. The
|
118 |
|
|
server will then scan the MIME table to find a MIME type to match the extension.
|
119 |
|
|
|
120 |
|
|
For example, to start a chunked transfer of an html file,
|
121 |
|
|
the following call is used:
|
122 |
|
|
|
123 |
|
|
|
124 |
|
|
cyg_httpd_start_chunked("html");
|
125 |
|
|
|
126 |
|
|
|
127 |
|
|
|
128 |
|
|
In any event, it is the responsibility of the user to make sure that a match to
|
129 |
|
|
all used extensions is found in the table search. Failing this,
|
130 |
|
|
the default MIME type specified in the CYGDAT_NET_ATHTTPD_DEFAULT_MIME_TYPE
|
131 |
|
|
string is returned.
|
132 |
|
|
|
133 |
|
|
|
134 |
|
|
|
135 |
|
|
|
136 |
|
|
C language callback functions
|
137 |
|
|
|
138 |
|
|
The server allows the association of particular URLs to C language callback
|
139 |
|
|
functions. eCos tables are used to define the association between a URL and its
|
140 |
|
|
corresponding callback. The syntax of the macro to add callback entries to
|
141 |
|
|
the table is:
|
142 |
|
|
|
143 |
|
|
|
144 |
|
|
|
145 |
|
|
CYG_HTTPD_HANDLER_TABLE_ENTRY(entry_label, url_string, callback);
|
146 |
|
|
|
147 |
|
|
entry table : an identifier unique to this entry.
|
148 |
|
|
url_string : a string with the extension url that will be appended to the
|
149 |
|
|
default directory.
|
150 |
|
|
callback : a function with a prototype:
|
151 |
|
|
cyg_int32 callback_function(CYG_HTTPD_STATE*);
|
152 |
|
|
Return value is ignored - just return 0.
|
153 |
|
|
|
154 |
|
|
|
155 |
|
|
|
156 |
|
|
CYG_HTTPD_STATE* is a pointer to a structure that
|
157 |
|
|
contains, among others, a buffer (outbuffer) that can be used to send data
|
158 |
|
|
out. The definitions of the structure is in http.h.
|
159 |
|
|
|
160 |
|
|
|
161 |
|
|
The following is an example of how to add a callback to a function myForm()
|
162 |
|
|
whenever the URL /myform.cgi is requested:
|
163 |
|
|
|
164 |
|
|
|
165 |
|
|
|
166 |
|
|
CYG_HTTPD_HANDLER_TABLE_ENTRY(hal_cb_entry, "/myform.cgi", myForm);
|
167 |
|
|
|
168 |
|
|
|
169 |
|
|
|
170 |
|
|
and somewhere in the source tree there is a function:
|
171 |
|
|
|
172 |
|
|
|
173 |
|
|
cyg_int32 myForm(CYG_HTTPD_STATE* p)
|
174 |
|
|
{
|
175 |
|
|
cyg_httpd_start_chunked("html");
|
176 |
|
|
strcpy(p->outbuffer, "eCos Web Server");
|
177 |
|
|
cyg_httpd_write_chunked(p->outbuffer, strlen(p->outbuffer))
|
178 |
|
|
cyg_httpd_end_chunked();
|
179 |
|
|
}
|
180 |
|
|
|
181 |
|
|
|
182 |
|
|
This function also shows the correct method of using the chunked frames
|
183 |
|
|
API inside a c language callback and also shows the use of outbuffer to
|
184 |
|
|
collect data to send out.
|
185 |
|
|
|
186 |
|
|
Chunked frames are useful when the size of the frame is not known upfront.
|
187 |
|
|
In this case it possible to send a response in chunks of various sizes, and
|
188 |
|
|
terminate it with a null chunk (See RFC 2616 for details). To use chunked
|
189 |
|
|
frames, the cyg_httpd_start_chunked() function is used.
|
190 |
|
|
The prototype is the following:
|
191 |
|
|
|
192 |
|
|
|
193 |
|
|
ssize_t cyg_httpd_start_chunked(char *);
|
194 |
|
|
|
195 |
|
|
|
196 |
|
|
The only parameter is the extension to use in the
|
197 |
|
|
search for the MIME type. For most files this will be "html" or "htm" and
|
198 |
|
|
it will be searched in the MIME table for an approriate MIME type that will
|
199 |
|
|
be sent along in the header. The function returns the number of bytes sent
|
200 |
|
|
out.
|
201 |
|
|
|
202 |
|
|
The chunked frame must be terminated by a call to
|
203 |
|
|
cyg_httpd_end_chunked():
|
204 |
|
|
|
205 |
|
|
|
206 |
|
|
void cyg_httpd_end_chunked()(void);
|
207 |
|
|
|
208 |
|
|
|
209 |
|
|
In between these two calls, the user can call the function
|
210 |
|
|
cyg_httpd_write_chunked() to send out data any number of
|
211 |
|
|
times. It is important that cyg_httpd_write_chunked() be
|
212 |
|
|
the only function used to send data out for chunked frames. This
|
213 |
|
|
guarantees that proper formatting of the response is respected.
|
214 |
|
|
The prototype for the function is:
|
215 |
|
|
|
216 |
|
|
|
217 |
|
|
ssize_t cyg_httpd_write_chunked(char* p, int len);
|
218 |
|
|
|
219 |
|
|
|
220 |
|
|
The 'char*' points to the data to send out, the 'int' is the length of the
|
221 |
|
|
data to send.
|
222 |
|
|
|
223 |
|
|
In the case in which the size of the data is known upfront, the
|
224 |
|
|
callback can instead create the header with a call to
|
225 |
|
|
cyg_httpd_create_std_header() with the following
|
226 |
|
|
prototype:
|
227 |
|
|
|
228 |
|
|
|
229 |
|
|
void cyg_httpd_create_std_header(char *ext, int len);
|
230 |
|
|
|
231 |
|
|
extension : the extension used in the search of the MIME type
|
232 |
|
|
len : length of the data to send out
|
233 |
|
|
|
234 |
|
|
|
235 |
|
|
and use
|
236 |
|
|
cyg_httpd_write() to send data out to the client. The
|
237 |
|
|
prototype of cyg_httpd_write() is the same as
|
238 |
|
|
cyg_httpd_write_chunked()
|
239 |
|
|
|
240 |
|
|
|
241 |
|
|
CGI
|
242 |
|
|
|
243 |
|
|
The web server allows writing of pseudo-CGI programs. This is helpful in order
|
244 |
|
|
to modify the functionality of the server without having to recompile it and
|
245 |
|
|
reflash it.
|
246 |
|
|
|
247 |
|
|
One way to implement CGI is, of course, the C language callback mechanism
|
248 |
|
|
described above: This assumes, of course, that all the callbacks are written
|
249 |
|
|
by compile time and cannot be modified later on. Another way to perform the
|
250 |
|
|
same functionality is the use of a library in the form of an object file.
|
251 |
|
|
These object files reside in the file system and are loaded, executed and
|
252 |
|
|
unloaded on demand.
|
253 |
|
|
|
254 |
|
|
Yet a third way is the use of a scripting language. Since full fledged
|
255 |
|
|
implementation of the most popular scripting languages such as Python or Perl
|
256 |
|
|
are too large for most embedded systems, a slim down implementation of tcl
|
257 |
|
|
was chosen for this server. Most of the tcl functionality is still there,
|
258 |
|
|
and makes writing cgi a lot easier.
|
259 |
|
|
|
260 |
|
|
In order to limit the footprint of the operating system support for both
|
261 |
|
|
the objloader and the tcl script for dealing with cgi files can be
|
262 |
|
|
independently selected out. Tcl support in particular increases the memory
|
263 |
|
|
requirements considerably.
|
264 |
|
|
|
265 |
|
|
|
266 |
|
|
|
267 |
|
|
CGI via objloader
|
268 |
|
|
|
269 |
|
|
In order to use the cgi mechanism the CYGPKG_OBJLOADER must be included
|
270 |
|
|
when building the operating system. This will enable the proper option in the
|
271 |
|
|
configuration tool and if selected, the necessary code will be compiled
|
272 |
|
|
in the eCos kernel. The user will then have to compile the necessary libraries
|
273 |
|
|
and place them in the file system under a directory defined by
|
274 |
|
|
CYGDAT_NET_ATHTTPD_SERVEROPT_CGIDIR.
|
275 |
|
|
When a request is made, the web server checks if the root directory of the
|
276 |
|
|
requested URL is inside the CYGDAT_NET_ATHTTPD_SERVEROPT_CGIDIR directory.
|
277 |
|
|
If so, the server assumes that the user requested a cgi file and looks into the
|
278 |
|
|
directory to see if a library by the same name is present, and if so load it
|
279 |
|
|
and tries to execute a function inside the library with the following prototype:
|
280 |
|
|
|
281 |
|
|
|
282 |
|
|
void exec_cgi(CYG_HTTPD_STATE *)
|
283 |
|
|
|
284 |
|
|
|
285 |
|
|
|
286 |
|
|
The pointer CYG_HTTPD_STATE* gives access to the socket
|
287 |
|
|
data: The user will use this pointer to access the 'outbuffer' and use it to
|
288 |
|
|
copy data to send data out.
|
289 |
|
|
|
290 |
|
|
|
291 |
|
|
|
292 |
|
|
When using the OBJLOADER package within the HTTP server a number of functions
|
293 |
|
|
are automatically added to the externals table of the OBJLOADER package. These
|
294 |
|
|
functions are likely to be used inside the library and the relocator need to
|
295 |
|
|
have a pointer to them. In order to add more functions, see the OBJLOADER
|
296 |
|
|
documentation. The complete list of the functions automatically added is:
|
297 |
|
|
|
298 |
|
|
|
299 |
|
|
|
300 |
|
|
cyg_httpd_start_chunked()
|
301 |
|
|
cyg_httpd_write_chunked()
|
302 |
|
|
cyg_httpd_end_chunked()
|
303 |
|
|
cyg_httpd_write()
|
304 |
|
|
cyg_httpd_find_form_variable()
|
305 |
|
|
cyg_httpd_find_ires()
|
306 |
|
|
cyg_httpd_send_ires()
|
307 |
|
|
diag_printf()
|
308 |
|
|
cyg_httpd_format_header()
|
309 |
|
|
cyg_httpd_find_mime_string()
|
310 |
|
|
|
311 |
|
|
|
312 |
|
|
Every time the web client issues a GET or POST request for a file with an
|
313 |
|
|
extension of '.o'in the /cgi-bin directory (or whatever path the user chooses
|
314 |
|
|
to hold the libraries) then the library by that name is loaded, run and
|
315 |
|
|
when the execution is over, it is dumped from memory.
|
316 |
|
|
|
317 |
|
|
The library must be compiled separately, using the same toolchain used to
|
318 |
|
|
compile the server and then added to the file system.
|
319 |
|
|
|
320 |
|
|
In order to reduce the footprint of the server, CGI through OBJLOADER
|
321 |
|
|
can be compiled out by unchecking CYGOPT_NET_ATHTTPD_USE_CGIBIN_OBJLOADER
|
322 |
|
|
in the configuration tool.
|
323 |
|
|
|
324 |
|
|
|
325 |
|
|
|
326 |
|
|
CGI via the simple tcl interpreter
|
327 |
|
|
A small tcl interpreter has been added to the web server, and it can
|
328 |
|
|
be used to write simple cgi scripts. The interpreter is admittedly very
|
329 |
|
|
minimal, and it is only useful for very simple applications, but it is an
|
330 |
|
|
excellent starting point for further development.
|
331 |
|
|
|
332 |
|
|
In order for the scripting language to be useful, it has to access
|
333 |
|
|
the form variables passed on during the GET or POST request. Because of
|
334 |
|
|
this, all form variables registered with the CYG_HTTPD_FVAR_TABLE_ENTRY()
|
335 |
|
|
macro are accessible via tcl. For example, if we have registered a
|
336 |
|
|
form variable called foo, and during the GET request we are defining foo
|
337 |
|
|
as being "1":
|
338 |
|
|
|
339 |
|
|
GET /myForm.cgi?foo=1
|
340 |
|
|
|
341 |
|
|
then tcl will be able to access the variable foo as $foo. The data
|
342 |
|
|
in the body of a POST request is also accessible through the use of the variable
|
343 |
|
|
$post_data. This is useful if the data is not in "multipart/form-data"
|
344 |
|
|
and tcl has to perform any type of processing on the data itself.
|
345 |
|
|
|
346 |
|
|
In order to send back a response to the client a few functions have been
|
347 |
|
|
added to the interpreter. These functions are:
|
348 |
|
|
|
349 |
|
|
|
350 |
|
|
start_chunked
|
351 |
|
|
start_chunked "extension";
|
352 |
|
|
"extension" is a string used to search the
|
353 |
|
|
table of the mime types. For example, to send back to the client an HTML file,
|
354 |
|
|
we can use: start_chunked "html";
|
355 |
|
|
|
356 |
|
|
|
357 |
|
|
|
358 |
|
|
|
359 |
|
|
write_chunked
|
360 |
|
|
write_chunked content;
|
361 |
|
|
content is a string to send back to the client.
|
362 |
|
|
|
363 |
|
|
|
364 |
|
|
|
365 |
|
|
|
366 |
|
|
end_chunked
|
367 |
|
|
end_chunked;
|
368 |
|
|
No parameters. Send back an end of frame to the client.
|
369 |
|
|
|
370 |
|
|
|
371 |
|
|
|
372 |
|
|
tcl hello world example
|
373 |
|
|
|
374 |
|
|
The following example demonstrates how to send a log file in the file
|
375 |
|
|
/ram/log to a web client. It replaces
|
376 |
|
|
newline characters with <br> so that it is formatted on the
|
377 |
|
|
browser correctly.
|
378 |
|
|
|
379 |
|
|
start_chunked "html";
|
380 |
|
|
|
381 |
|
|
set fp [aio.open "/ram/log" r];
|
382 |
|
|
$fp seek 0 end;
|
383 |
|
|
set fsize [$fp tell];
|
384 |
|
|
$fp seek 0 start;
|
385 |
|
|
set data "abcxxx";
|
386 |
|
|
set data [$fp read $fsize];
|
387 |
|
|
$fp close;
|
388 |
|
|
set data [string map {\n <br>} $data];
|
389 |
|
|
|
390 |
|
|
set datax "";
|
391 |
|
|
append datax "<html><body>" $data "</body></html>";
|
392 |
|
|
|
393 |
|
|
write_chunked $datax;
|
394 |
|
|
end_chunked;
|
395 |
|
|
|
396 |
|
|
|
397 |
|
|
|
398 |
|
|
The above file should exist on a filesystem
|
399 |
|
|
on the embedded target within its cgi-bin
|
400 |
|
|
directory, for example as /cgi-bin/hello.tcl. Thereafter
|
401 |
|
|
it may be accessed at the URL
|
402 |
|
|
http://TARGET_NAME/cgi-bin/hello.tcl.
|
403 |
|
|
|
404 |
|
|
|
405 |
|
|
|
406 |
|
|
|
407 |
|
|
|
408 |
|
|
|
409 |
|
|
Authentication
|
410 |
|
|
|
411 |
|
|
The server supports both Basic (base64) and Digest (MD5) authentication,
|
412 |
|
|
although they have not been tested with all clients. In this implementation,
|
413 |
|
|
the contents of certain directories of the file system can be protected, such
|
414 |
|
|
that the user will be required to issue a username/password to access the
|
415 |
|
|
content of the directory.
|
416 |
|
|
|
417 |
|
|
To protect a directory with a basic authentication, there is a
|
418 |
|
|
specific macro:
|
419 |
|
|
|
420 |
|
|
|
421 |
|
|
CYG_HTTPD_AUTH_TABLE_ENTRY(entry, path, domain, un, pw, mode)
|
422 |
|
|
|
423 |
|
|
entry : an identifier unique to this entry.
|
424 |
|
|
path : the path to the directory whose content must be
|
425 |
|
|
authenticated before it is sent out
|
426 |
|
|
domain : a domain identifier for this directory.
|
427 |
|
|
un : username for authentication
|
428 |
|
|
pw : password for authentication
|
429 |
|
|
mode : CYG_HTTPD_AUTH_BASIC for base64 encoding or
|
430 |
|
|
CYG_HTTPD_AUTH_DIGEST for MD5 encoding
|
431 |
|
|
|
432 |
|
|
|
433 |
|
|
for example, to require basic authentication of the content of directory
|
434 |
|
|
"/ecos/" with a username of "foo" and password "bar", the following is used:
|
435 |
|
|
|
436 |
|
|
|
437 |
|
|
|
438 |
|
|
CYG_HTTPD_AUTH_TABLE_ENTRY(hal_domain1_entry, \
|
439 |
|
|
"/ecos/", "ecos_domain", \
|
440 |
|
|
"foo", "bar", \
|
441 |
|
|
CYG_HTTPD_AUTH_BASIC);
|
442 |
|
|
|
443 |
|
|
|
444 |
|
|
Any request for a file in the directory /ecos/ will now trigger a
|
445 |
|
|
credential check. These credentials, once provided, are automatically sent by
|
446 |
|
|
the client for every request within the particular domain.
|
447 |
|
|
|
448 |
|
|
It must be noticed that the path name set in the macro is relative to the
|
449 |
|
|
HTML document directory, CYGDAT_NET_HTTPD_SERVEROPT_HTMLDIR and it is the
|
450 |
|
|
first part of the path provided by the client request (including the leading
|
451 |
|
|
slash).
|
452 |
|
|
|
453 |
|
|
In order to reduce the footprint of the server, authentication
|
454 |
|
|
is not enabled by default, and so the option CYGOPT_NET_ATHTTPD_USE_AUTH must
|
455 |
|
|
be used to enable support for basic and digest authentication.
|
456 |
|
|
|
457 |
|
|
The MD5 digest authentication support is implemented using the RSA
|
458 |
|
|
Data Security, Inc. MD5 Message-Digest Algorithm. Derivative works with
|
459 |
|
|
MD5 digest authentication included must be identified as "derived from the
|
460 |
|
|
RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material
|
461 |
|
|
mentioning or referencing the derived work. See the file md5.c within this
|
462 |
|
|
package for license details.
|
463 |
|
|
|
464 |
|
|
|
465 |
|
|
|
466 |
|
|
Directory Listing
|
467 |
|
|
|
468 |
|
|
If the user issues a "GET" request with a URL terminating in a slash, the
|
469 |
|
|
server will try to locate one of the following index files in the directory,
|
470 |
|
|
choosing one in the following order:
|
471 |
|
|
|
472 |
|
|
|
473 |
|
|
index.html
|
474 |
|
|
index.htm
|
475 |
|
|
default.html
|
476 |
|
|
home.html
|
477 |
|
|
|
478 |
|
|
|
479 |
|
|
If any of these files is found, its contents are sent back
|
480 |
|
|
to the client. If no such file is found the server uses the user-provided
|
481 |
|
|
index file name (if any is specified with the CYGDAT_NET_ATHTTPD_ALTERNATE_HOME
|
482 |
|
|
setting. Failing all this a directory listing is sent.
|
483 |
|
|
|
484 |
|
|
Trailing slash redirection for directory names is supported.
|
485 |
|
|
|
486 |
|
|
In order to reduce the footprint of the server, directory listing can
|
487 |
|
|
be disabled by unchecking CYGOPT_NET_ATHTTPD_USE_DIRLIST. The savings are
|
488 |
|
|
substantial since directory listing also makes use of a few internal
|
489 |
|
|
resources (gif files) which are also compiled out.
|
490 |
|
|
|
491 |
|
|
|
492 |
|
|
|
493 |
|
|
Form Variables
|
494 |
|
|
|
495 |
|
|
The server will automatically try to parse form variables when a form is
|
496 |
|
|
submitted in the following cases:
|
497 |
|
|
|
498 |
|
|
|
499 |
|
|
In a GET request, when the URL is followed by a question
|
500 |
|
|
mark sign
|
501 |
|
|
In a POST request, when the the 'Content-Type' header line
|
502 |
|
|
is set to 'application/x-www-form-urlencoded'
|
503 |
|
|
|
504 |
|
|
|
505 |
|
|
The variable names to look for during the parsing are held in
|
506 |
|
|
an eCos table. In order to take advantage of this feature, the user first
|
507 |
|
|
adds the variable names to the table, which also requires providing a buffer
|
508 |
|
|
where the parsed value will eventually be stored. The values will then be
|
509 |
|
|
available in the buffers during the processing of the request, presumably in
|
510 |
|
|
the body of a c language callback or CGI script.
|
511 |
|
|
|
512 |
|
|
For example, if the user wants two form variables, "foo" and "bar", to
|
513 |
|
|
be parsed automatically, those variable names must be added to the table
|
514 |
|
|
with the following macro:
|
515 |
|
|
|
516 |
|
|
|
517 |
|
|
CYG_HTTPD_FVAR_TABLE_ENTRY(entry, name, buffp, bufflen)
|
518 |
|
|
|
519 |
|
|
entry : an identifier unique to this entry.
|
520 |
|
|
name : name of the form variable
|
521 |
|
|
buffp : a pointer to a buffer of characters where to store the value
|
522 |
|
|
of the form variable.
|
523 |
|
|
bufflen : The length of the buffer. Must include a trailing string
|
524 |
|
|
terminator.
|
525 |
|
|
|
526 |
|
|
|
527 |
|
|
or, in the specific instance mentioned above:
|
528 |
|
|
|
529 |
|
|
|
530 |
|
|
#define HTML_VAR_LEN 20
|
531 |
|
|
char var_foo[HTML_VAR_LEN];
|
532 |
|
|
char var_bar[HTML_VAR_LEN];
|
533 |
|
|
CYG_HTTPD_FVAR_TABLE_ENTRY(hal_form_entry_foo, "foo", var_foo, HTML_VAR_LEN);
|
534 |
|
|
CYG_HTTPD_FVAR_TABLE_ENTRY(hal_form_entry_bar, "bar", var_bar, HTML_VAR_LEN);
|
535 |
|
|
|
536 |
|
|
|
537 |
|
|
and after the GET or POST submissions, the list will contain the value
|
538 |
|
|
for "foo" and "bar" (if they were found in the form data.) It is the
|
539 |
|
|
responsability of the user to make sure that the buffer is large enough
|
540 |
|
|
to hold all the data parsed (including the string terminator). The parser will
|
541 |
|
|
write only up to the length of the buffer minus one (the last being the
|
542 |
|
|
terminator) and discard any additional data.
|
543 |
|
|
|
544 |
|
|
The values parsed are likely going to be used in c language callback, or
|
545 |
|
|
in CGI files. In a c language callback the user can directly access the pointers
|
546 |
|
|
of individual variables for further processing, keeping in mind that the parsing
|
547 |
|
|
always result in a string of characters to be produced, and any conversion
|
548 |
|
|
(e.g. from strings to integer) must be performed within the callback. In
|
549 |
|
|
a TCL script the user can just access a variable by its name. For example,
|
550 |
|
|
in the case of the variables 'foo' and 'bar' shown above, it is possible
|
551 |
|
|
to do something like 'write_chunked "You wrote $foo". The data that was sent in
|
552 |
|
|
the body of a POST request is accessible in through a variable called
|
553 |
|
|
'post_data'. In CGI functions
|
554 |
|
|
implemented using the objloader the pointers to the
|
555 |
|
|
variables cannot be accessed directly, since the library will likely not
|
556 |
|
|
know their location in memory. The proper way to access them is by using the
|
557 |
|
|
cyg_httpd_find_form_variable() function from within the library:
|
558 |
|
|
|
559 |
|
|
|
560 |
|
|
char* cyg_httpd_find_form_variable(char* name)
|
561 |
|
|
|
562 |
|
|
name : name of the form variable to look up
|
563 |
|
|
|
564 |
|
|
returns a pointer to the buffer, or 0 if the variable was not found.
|
565 |
|
|
|
566 |
|
|
|
567 |
|
|
When using the OBJLOADER package within the web server, an entry
|
568 |
|
|
for the cyg_httpd_find_form_variable() function is automatically added to the
|
569 |
|
|
externals table the OBJLOADER for relocation. See the OBLOADER paragraph of
|
570 |
|
|
the ATHTTP user's guide for the full list of the exported functions.
|
571 |
|
|
|
572 |
|
|
In order to avoid stale data, all the buffers in the table are cleared
|
573 |
|
|
before running the parser and thus any variable in the list that was not
|
574 |
|
|
assigned a new value dureing the request will be an empty string.
|
575 |
|
|
|
576 |
|
|
|
577 |
|
|
|
578 |
|
|
Internal Resources
|
579 |
|
|
|
580 |
|
|
When the server does not use a file system the user must be responsible
|
581 |
|
|
to provide a C language callback function for each URL that will be
|
582 |
|
|
requested by the client. This means locating the data and sending it out
|
583 |
|
|
using either cyg_httpd_write() or
|
584 |
|
|
cyg_httpd_write_chunked().
|
585 |
|
|
|
586 |
|
|
In order to simplify this process the server allows registering
|
587 |
|
|
any number of URLs as internal resources, by providing the URL name, the
|
588 |
|
|
pointer to the resource data and its size. When a URL is requested the
|
589 |
|
|
server will look it up among all internal resources, and if found, it
|
590 |
|
|
will send out the resource.
|
591 |
|
|
|
592 |
|
|
Internal resource can also be used along with a file system. In this
|
593 |
|
|
case the file system is searched first, and if a file is found, it it
|
594 |
|
|
sent. If a file is not found, the internal resources are searched and
|
595 |
|
|
if a match if found it is sent.
|
596 |
|
|
|
597 |
|
|
The drawback of this approach is, of course, that all these
|
598 |
|
|
resources are going to add to the size of the operating system image, and thus
|
599 |
|
|
it should be used only when memory is not a major constraint of the
|
600 |
|
|
design.
|
601 |
|
|
|
602 |
|
|
As always, to provide this type of customization, ecos tables are used.
|
603 |
|
|
The format for adding a new resource to the internal table is the following:
|
604 |
|
|
|
605 |
|
|
|
606 |
|
|
|
607 |
|
|
CYG_HTTPD_IRES_TABLE_ENTRY(entry, name, buffp, len)
|
608 |
|
|
|
609 |
|
|
entry : an identifier unique to this entry.
|
610 |
|
|
name : name of the URL including leading '/'
|
611 |
|
|
buffp : a pointer to a buffer of characters where to store the value
|
612 |
|
|
of the form variable.
|
613 |
|
|
len : size of the array
|
614 |
|
|
|
615 |
|
|
|
616 |
|
|
As an example, if the user wants to provide his own web page by
|
617 |
|
|
hardcoding it in the application code, here is how he would do it:
|
618 |
|
|
|
619 |
|
|
|
620 |
|
|
#define MY_OWN_HOME_PAGE "eCos RTOS"
|
621 |
|
|
CYG_HTTPD_IRES_TABLE_ENTRY(cyg_httpd_ires_home, \
|
622 |
|
|
"/index.html", \
|
623 |
|
|
MY_OWN_HOME_PAGE, \
|
624 |
|
|
9);
|
625 |
|
|
|
626 |
|
|
|
627 |
|
|
The extension of the file name determines the MIME type to be used for
|
628 |
|
|
internal resources.
|
629 |
|
|
|
630 |
|
|
When using directory listing you are implicitly making use of internal
|
631 |
|
|
resources. The small icons that appear to the left of file names and
|
632 |
|
|
directories are internal resources. Unchecking CYGOPT_NET_HTTP_USE_DIRLIST
|
633 |
|
|
will prevent the addition of these files.
|
634 |
|
|
|
635 |
|
|
In order to use internal resources, a generic file must first be
|
636 |
|
|
turned into a c language array, which is then compiled in the application
|
637 |
|
|
code. To create this array you can use the tcl script that comes with the
|
638 |
|
|
ecos distribution at packages/fs/rom/current/support/file2.tcl.
|
639 |
|
|
|
640 |
|
|
|
641 |
|
|
|