source: rtems/cpukit/httpd/webmain.c @ c55df85

4.104.114.84.95
Last change on this file since c55df85 was 4b60bd3, checked in by Joel Sherrill <joel.sherrill@…>, on 09/22/00 at 20:38:57

2000-09-22 Joel Sherrill <joel@…>

  • machine/types.h, pppd/pppd.h, rtems/rtems_bsdnet_internal.h, rtems_webserver/webmain.c: machine/types.h should not have included rtems.h. It is now including precisely the least amount of low level, yet portable .h files to get the basic RTEMS types defined. This rippled into other files since rtems_bsdnet_internal.h used machine/types.h to include rtems.h.
  • Property mode set to 100644
File size: 11.7 KB
Line 
1/*
2 * main.c -- Main program for the GoAhead WebServer (RTEMS version)
3 *
4 * Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
5 *
6 * See the file "license.txt" for usage and redistribution license requirements
7 *
8 *  $Id$
9 */
10
11/******************************** Description *********************************/
12
13/*
14 *      Main program for for the GoAhead WebServer. This is a demonstration
15 *      main program to initialize and configure the web server.
16 */
17
18/********************************* Includes ***********************************/
19
20#include        "uemf.h"
21#include        "wsIntrn.h"
22#include        <signal.h>
23#include        <sys/time.h>
24#include        <pthread.h>
25
26#include        <rtems.h>
27#include        <rtems/error.h>
28
29#ifdef WEBS_SSL_SUPPORT
30#include        "websSSL.h"
31#endif
32
33#ifdef USER_MANAGEMENT_SUPPORT
34#include        "um.h"
35void    formDefineUserMgmt(void);
36#endif
37
38/*********************************** Locals ***********************************/
39/*
40 *      Change configuration here
41 */
42
43extern const char *tftpServer;
44static char_t           *rootWeb = T("goahead");                        /* Root web directory */
45static char_t           *password = T("");                              /* Security password */
46static int                      port = 80;                                              /* Server port */
47static int                      retries = 5;                                    /* Server port retries */
48static int                      finished;                                               /* Finished flag */
49
50/*
51 *      Structure to hold timer events
52 */
53typedef struct {
54        void    (*routine)(long arg);   /* Timer routine */
55        long    arg;                                    /* Argument to routine */
56} websTimer_t;
57
58/* The following holds the pointer to an allocated websTimer_t structure .
59 * Using this method only one timer can be active at a time, but
60 * for the WebServer, this should be OK.
61 */
62websTimer_t *tp;
63
64/****************************** Forward Declarations **************************/
65
66static int      initWebs();
67static int      aspTest(int eid, webs_t wp, int argc, char_t **argv);
68static void formTest(webs_t wp, char_t *path, char_t *query);
69static int  websHomePageHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
70                                int arg, char_t* url, char_t* path, char_t* query);
71static void timerProc(int signo);
72#if B_STATS
73static void printMemStats(int handle, char_t *fmt, ...);
74static void memLeaks();
75#endif
76static timer_t timer_id;
77static void rtems_httpd_daemon();
78 
79/*********************************** Code *************************************/
80/*
81 *      Main -- entry point from RTEMS
82 */
83int rtems_initialize_webserver()
84{
85  rtems_status_code   sc;
86  rtems_id            tid;
87  int                 priority;
88
89  /***********************************************************************
90   * Default HTTPD priority.
91   **********************************************************************/
92  priority = 40;
93 
94  sc = rtems_task_create(rtems_build_name('H', 'T', 'P', 'D'),
95                         priority, 8*1024,
96                         RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR |
97                         RTEMS_INTERRUPT_LEVEL(0),
98                         RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,
99                         &tid);
100   if (sc != RTEMS_SUCCESSFUL)
101   {
102      return(RTEMS_UNSATISFIED);
103   }
104
105   sc = rtems_task_start(tid, rtems_httpd_daemon, 0);
106   if (sc != RTEMS_SUCCESSFUL)
107   {
108      return(RTEMS_UNSATISFIED);
109   }   
110
111   return(RTEMS_SUCCESSFUL);
112
113}
114
115static void
116rtems_httpd_daemon()
117{
118/*
119 *      Initialize the memory allocator. Allow use of malloc and start with a
120 *      10K heap.
121 */
122        bopen(NULL, (10 * 1024), B_USE_MALLOC);
123
124/*
125 *      Initialize the web server
126 */
127        if (initWebs() < 0) {
128          rtems_panic("Unable to initialize Web server !!\n");
129        }
130
131#ifdef WEBS_SSL_SUPPORT
132        websSSLOpen();
133#endif
134
135/*
136 *      Basic event loop. SocketReady returns true when a socket is ready for
137 *      service. SocketSelect will block until an event occurs. SocketProcess
138 *      will actually do the servicing.
139 */
140        while (!finished) {
141          if (socketReady(-1) || socketSelect(-1, 2000)) {
142                        socketProcess(-1);
143          }
144          /*websCgiCleanup();*/
145          emfSchedProcess();
146        }
147
148#ifdef WEBS_SSL_SUPPORT
149        websSSLClose();
150#endif
151
152#ifdef USER_MANAGEMENT_SUPPORT
153        umClose();
154#endif
155
156/*
157 *      Close the socket module, report memory leaks and close the memory allocator
158 */
159        websCloseServer();
160        websDefaultClose();
161        socketClose();
162        symSubClose();
163#if B_STATS
164        memLeaks();
165#endif
166        bclose();
167        rtems_task_delete( RTEMS_SELF );
168}
169
170/******************************************************************************/
171/*
172 *      Initialize the web server.
173 */
174
175static int initWebs()
176{
177        struct hostent* hp;
178        struct in_addr  intaddr;
179        char                    host[128], dir[128], webdir[128];
180        char                    *cp;
181        char_t                  wbuf[128];
182
183/*
184 *      Initialize the socket subsystem
185 */
186        socketOpen();
187
188/*
189 *      Define the local Ip address, host name, default home page and the
190 *      root web directory.
191 */
192        if (gethostname(host, sizeof(host)) < 0) {
193                error(E_L, E_LOG, T("Can't get hostname"));
194                return -1;
195                }
196       
197/*      intaddr.s_addr = (unsigned long) hostGetByName(host); */
198        if ((hp = gethostbyname(host)) == NULL) {
199                error(E_L, E_LOG, T("Can't get host address"));
200                return -1;
201        }
202        memcpy((char *) &intaddr, (char *) hp->h_addr_list[0],
203                (size_t) hp->h_length);
204
205#if 0
206/*
207 *      Set /TFTP/x.y.z.w/goahead as the root web. Modify to suit your needs
208 */
209        sprintf(webdir, "/TFTP/%s/%s", tftpServer, rootWeb);
210#else
211        sprintf(webdir, "/");
212#endif
213/*
214 *      Configure the web server options before opening the web server
215 */
216        websSetDefaultDir(webdir);
217        ascToUni(wbuf, inet_ntoa(intaddr), sizeof(wbuf));
218        websSetIpaddr(wbuf);
219        ascToUni(wbuf, host, sizeof(wbuf));
220        websSetHost(wbuf);
221
222/*
223 *      Configure the web server options before opening the web server
224 */
225#if 0
226        websSetDefaultPage(T("default.asp"));
227#else
228        websSetDefaultPage(T("index.html"));
229#endif
230        websSetPassword(password);
231
232/*
233 *      Open the web server on the given port. If that port is taken, try
234 *      the next sequential port for up to "retries" attempts.
235 */
236        websOpenServer(port, retries);
237
238/*
239 *      First create the URL handlers. Note: handlers are called in sorted order
240 *      with the longest path handler examined first. Here we define the security
241 *      handler, forms handler and the default web page handler.
242 */
243        websUrlHandlerDefine(T(""), NULL, 0, websSecurityHandler,
244                WEBS_HANDLER_FIRST);
245        websUrlHandlerDefine(T("/goform"), NULL, 0, websFormHandler, 0);
246        websUrlHandlerDefine(T(""), NULL, 0, websDefaultHandler,
247                WEBS_HANDLER_LAST);
248
249/*
250 *      Now define two test procedures. Replace these with your application
251 *      relevant ASP script procedures and form functions.
252 */
253        websAspDefine(T("aspTest"), aspTest);
254        websFormDefine(T("formTest"), formTest);
255
256/*
257 *      Create a handler for the default home page
258 */
259        websUrlHandlerDefine(T("/"), NULL, 0, websHomePageHandler, 0);
260        return 0;
261}
262
263/******************************************************************************/
264/*
265 *      Test Javascript binding for ASP. This will be invoked when "aspTest" is
266 *      embedded in an ASP page. See web/asp.asp for usage. Set browser to
267 *      "localhost/asp.asp" to test.
268 */
269
270static int aspTest(int eid, webs_t wp, int argc, char_t **argv)
271{
272        char_t  *name, *address;
273
274        if (ejArgs(argc, argv, T("%s %s"), &name, &address) < 2) {
275                websError(wp, 400, T("Insufficient args\n"));
276                return -1;
277        }
278        return websWrite(wp, T("Name: %s, Address %s"), name, address);
279}
280/******************************************************************************/
281/*
282 *      Test form for posted data (in-memory CGI). This will be called when the
283 *      form in web/asp.asp is invoked. Set browser to "localhost/asp.asp" to test.
284 */
285
286static void formTest(webs_t wp, char_t *path, char_t *query)
287{
288        char_t  *name, *address;
289
290        name = websGetVar(wp, T("name"), T("Joe Smith"));
291        address = websGetVar(wp, T("address"), T("1212 Milky Way Ave."));
292
293        websHeader(wp);
294        websWrite(wp, T("<body><h2>Name: %s, Address: %s</h2>\n"), name, address);
295        websFooter(wp);
296        websDone(wp, 200);
297}
298
299/******************************************************************************/
300/*
301 *      Create a timer to invoke the routine in "delay" milliseconds.
302 */
303
304void *emfCreateTimer(int delay, void (*routine)(long arg),      long arg)
305{
306/* this variable is only used in the if'ed 0 section below */
307#if 0
308        struct sigaction        act;
309#endif
310        struct itimerspec its = { {0,0}, {0,0} };
311        struct sigevent se;
312        int     status;
313
314        if ((tp = balloc(B_L, sizeof(websTimer_t)))) {
315                tp->routine = routine;
316                tp->arg = arg;
317        }
318        else {
319                return NULL;
320        }
321
322        se.sigev_notify = SIGEV_THREAD;
323        se.sigev_value.sival_ptr = tp;
324        se.sigev_notify_function = (void (*)(union sigval)) timerProc;
325
326        /*
327         * NOT POSIX?
328         * se.sigev_notify_attributes = NULL;
329         */
330
331
332        status = timer_create(CLOCK_REALTIME, &se, &timer_id);
333        if (status != 0) {
334                bfree(B_L, tp);
335                return NULL;
336        }
337        /* convert delay millisecs to secs and usecs required by struct */
338        its.it_value.tv_sec = delay / 1000;
339        its.it_value.tv_nsec = (delay % 1000) * 1000000;
340
341        status = timer_settime(timer_id, 0, &its, 0);
342        if (status != 0) {
343                bfree(B_L, tp);
344                return NULL;
345        }
346       
347#if 0
348        act.sa_flags = 0;
349        sigemptyset(&act.sa_mask);
350        act.sa_handler = timerProc;
351        sigaction(SIGALRM, &act, NULL);
352
353        /* convert delay millisecs to secs and usecs required by struct */
354        its.it_value.tv_sec = delay / 1000;
355        its.it_value.tv_usec = (delay % 1000) * 1000;
356
357        if (setitimer(ITIMER_REAL, &its, NULL) ==  -1) {
358                bfree(B_L, tp);
359                return NULL;
360        }
361#endif
362        return tp;
363}
364
365/******************************************************************************/
366/*
367 *      Delete a timer
368 */
369
370void emfDeleteTimer(void * id)
371{
372        websTimer_t *wtp;
373        /*struct itimerval its = { {0,0}, {0,0} };*/
374
375        wtp = (websTimer_t *)id;
376        /*      setitimer(ITIMER_REAL, &its, NULL);*/
377        timer_delete(timer_id);
378        bfree(B_L, wtp);
379}
380
381/******************************************************************************/
382/*
383 *      Timer handler
384 */
385
386static void timerProc(int signo)
387{
388        websTimer_t wtp = *tp;
389
390/* Copy the timer structure to a local first and delete it before calling
391 * the function, since the function could create another timer.  In this
392 * implementation, only one timer can be allocated at a time.
393 */
394
395        bfree(B_L, tp);
396        (wtp.routine)(wtp.arg);
397}
398
399/******************************************************************************/
400/*
401 *      Home page handler
402 */
403
404static int websHomePageHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
405        int arg, char_t* url, char_t* path, char_t* query)
406{
407/*
408 *      If the empty or "/" URL is invoked, redirect default URLs to the home page
409 */
410        if (*url == '\0' || gstrcmp(url, T("/")) == 0) {
411#if 0
412                websRedirect(wp, T("home.asp"));
413#else
414                websRedirect(wp, T("index.html"));
415#endif
416                return 1;
417        }
418        return 0;
419}
420
421/******************************************************************************/
422
423#if B_STATS
424static void memLeaks()
425{
426        int             fd=1;
427
428        /* if ((fd = gopen(T("leak.txt"), O_CREAT | O_TRUNC | O_WRONLY)) >= 0) { */
429                bstats(fd, printMemStats);
430                /*
431                close(fd);
432        }
433                */
434}
435
436/******************************************************************************/
437/*
438 *      Print memory usage / leaks
439 */
440
441static void printMemStats(int handle, char_t *fmt, ...)
442{
443        va_list         args;
444        char_t          buf[256];
445
446        va_start(args, fmt);
447        vsprintf(buf, fmt, args);
448        va_end(args);
449        write(handle, buf, strlen(buf));
450}
451#endif
452
453/*****************************************************************************/
454
455/*****************************************************************************/
456/*
457 *      Default error handler.  The developer should insert code to handle
458 *      error messages in the desired manner.
459 */
460
461void defaultErrorHandler(int etype, char_t *msg)
462{
463#if 1
464        write(1, msg, gstrlen(msg));
465#endif
466}
467
468/*****************************************************************************/
469/*
470 *      Trace log. Customize this function to log trace output
471 */
472
473void defaultTraceHandler(int level, char_t *buf)
474{
475/*
476 *      The following code would write all trace regardless of level
477 *      to stdout.
478 */
479#if 1
480        if (buf) {
481                write(1, buf, gstrlen(buf));
482        }
483#endif
484}
485
486/*****************************************************************************/
487/*
488 *      Returns a pointer to an allocated qualified unique temporary file name.
489 *      This filename must eventually be deleted with bfree();
490 */
491
492char_t *websGetCgiCommName()
493{
494        char_t  *pname1, *pname2;
495
496        pname1 = tempnam(NULL, T("cgi"));
497        pname2 = bstrdup(B_L, pname1);
498        free(pname1);
499        return pname2;
500}
Note: See TracBrowser for help on using the repository browser.