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

4.104.114.84.95
Last change on this file since dc2a1750 was 5432fc4, checked in by Joel Sherrill <joel.sherrill@…>, on 08/31/02 at 14:44:15

2002-08-31 Joel Sherrill <joel@…>

  • rtems_webserver/webmain.c: Commented out rootWeb to eliminate warning.
  • 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;
44/* static 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], webdir[128];
180        char_t                  wbuf[128];
181
182/*
183 *      Initialize the socket subsystem
184 */
185        socketOpen();
186
187/*
188 *      Define the local Ip address, host name, default home page and the
189 *      root web directory.
190 */
191        if (gethostname(host, sizeof(host)) < 0) {
192                error(E_L, E_LOG, T("Can't get hostname"));
193                return -1;
194                }
195       
196/*      intaddr.s_addr = (unsigned long) hostGetByName(host); */
197        if ((hp = gethostbyname(host)) == NULL) {
198                error(E_L, E_LOG, T("Can't get host address"));
199                return -1;
200        }
201        memcpy((char *) &intaddr, (char *) hp->h_addr_list[0],
202                (size_t) hp->h_length);
203
204#if 0
205/*
206 *      Set /TFTP/x.y.z.w/goahead as the root web. Modify to suit your needs
207 */
208        sprintf(webdir, "/TFTP/%s/%s", tftpServer, rootWeb);
209#else
210        sprintf(webdir, "/");
211#endif
212/*
213 *      Configure the web server options before opening the web server
214 */
215        websSetDefaultDir(webdir);
216        ascToUni(wbuf, inet_ntoa(intaddr), sizeof(wbuf));
217        websSetIpaddr(wbuf);
218        ascToUni(wbuf, host, sizeof(wbuf));
219        websSetHost(wbuf);
220
221/*
222 *      Configure the web server options before opening the web server
223 */
224#if 0
225        websSetDefaultPage(T("default.asp"));
226#else
227        websSetDefaultPage(T("index.html"));
228#endif
229        websSetPassword(password);
230
231/*
232 *      Open the web server on the given port. If that port is taken, try
233 *      the next sequential port for up to "retries" attempts.
234 */
235        websOpenServer(port, retries);
236
237/*
238 *      First create the URL handlers. Note: handlers are called in sorted order
239 *      with the longest path handler examined first. Here we define the security
240 *      handler, forms handler and the default web page handler.
241 */
242        websUrlHandlerDefine(T(""), NULL, 0, websSecurityHandler,
243                WEBS_HANDLER_FIRST);
244        websUrlHandlerDefine(T("/goform"), NULL, 0, websFormHandler, 0);
245        websUrlHandlerDefine(T(""), NULL, 0, websDefaultHandler,
246                WEBS_HANDLER_LAST);
247
248/*
249 *      Now define two test procedures. Replace these with your application
250 *      relevant ASP script procedures and form functions.
251 */
252        websAspDefine(T("aspTest"), aspTest);
253        websFormDefine(T("formTest"), formTest);
254
255/*
256 *      Create a handler for the default home page
257 */
258        websUrlHandlerDefine(T("/"), NULL, 0, websHomePageHandler, 0);
259        return 0;
260}
261
262/******************************************************************************/
263/*
264 *      Test Javascript binding for ASP. This will be invoked when "aspTest" is
265 *      embedded in an ASP page. See web/asp.asp for usage. Set browser to
266 *      "localhost/asp.asp" to test.
267 */
268
269static int aspTest(int eid, webs_t wp, int argc, char_t **argv)
270{
271        char_t  *name, *address;
272
273        if (ejArgs(argc, argv, T("%s %s"), &name, &address) < 2) {
274                websError(wp, 400, T("Insufficient args\n"));
275                return -1;
276        }
277        return websWrite(wp, T("Name: %s, Address %s"), name, address);
278}
279/******************************************************************************/
280/*
281 *      Test form for posted data (in-memory CGI). This will be called when the
282 *      form in web/asp.asp is invoked. Set browser to "localhost/asp.asp" to test.
283 */
284
285static void formTest(webs_t wp, char_t *path, char_t *query)
286{
287        char_t  *name, *address;
288
289        name = websGetVar(wp, T("name"), T("Joe Smith"));
290        address = websGetVar(wp, T("address"), T("1212 Milky Way Ave."));
291
292        websHeader(wp);
293        websWrite(wp, T("<body><h2>Name: %s, Address: %s</h2>\n"), name, address);
294        websFooter(wp);
295        websDone(wp, 200);
296}
297
298/******************************************************************************/
299/*
300 *      Create a timer to invoke the routine in "delay" milliseconds.
301 */
302
303void *emfCreateTimer(int delay, void (*routine)(long arg),      long arg)
304{
305/* this variable is only used in the if'ed 0 section below */
306#if 0
307        struct sigaction        act;
308#endif
309        struct itimerspec its = { {0,0}, {0,0} };
310        struct sigevent se;
311        int     status;
312
313        if ((tp = balloc(B_L, sizeof(websTimer_t)))) {
314                tp->routine = routine;
315                tp->arg = arg;
316        }
317        else {
318                return NULL;
319        }
320
321        se.sigev_notify = SIGEV_THREAD;
322        se.sigev_value.sival_ptr = tp;
323        se.sigev_notify_function = (void (*)(union sigval)) timerProc;
324
325        /*
326         * NOT POSIX?
327         * se.sigev_notify_attributes = NULL;
328         */
329
330
331        status = timer_create(CLOCK_REALTIME, &se, &timer_id);
332        if (status != 0) {
333                bfree(B_L, tp);
334                return NULL;
335        }
336        /* convert delay millisecs to secs and usecs required by struct */
337        its.it_value.tv_sec = delay / 1000;
338        its.it_value.tv_nsec = (delay % 1000) * 1000000;
339
340        status = timer_settime(timer_id, 0, &its, 0);
341        if (status != 0) {
342                bfree(B_L, tp);
343                return NULL;
344        }
345       
346#if 0
347        act.sa_flags = 0;
348        sigemptyset(&act.sa_mask);
349        act.sa_handler = timerProc;
350        sigaction(SIGALRM, &act, NULL);
351
352        /* convert delay millisecs to secs and usecs required by struct */
353        its.it_value.tv_sec = delay / 1000;
354        its.it_value.tv_usec = (delay % 1000) * 1000;
355
356        if (setitimer(ITIMER_REAL, &its, NULL) ==  -1) {
357                bfree(B_L, tp);
358                return NULL;
359        }
360#endif
361        return tp;
362}
363
364/******************************************************************************/
365/*
366 *      Delete a timer
367 */
368
369void emfDeleteTimer(void * id)
370{
371        websTimer_t *wtp;
372        /*struct itimerval its = { {0,0}, {0,0} };*/
373
374        wtp = (websTimer_t *)id;
375        /*      setitimer(ITIMER_REAL, &its, NULL);*/
376        timer_delete(timer_id);
377        bfree(B_L, wtp);
378}
379
380/******************************************************************************/
381/*
382 *      Timer handler
383 */
384
385static void timerProc(int signo)
386{
387        websTimer_t wtp = *tp;
388
389/* Copy the timer structure to a local first and delete it before calling
390 * the function, since the function could create another timer.  In this
391 * implementation, only one timer can be allocated at a time.
392 */
393
394        bfree(B_L, tp);
395        (wtp.routine)(wtp.arg);
396}
397
398/******************************************************************************/
399/*
400 *      Home page handler
401 */
402
403static int websHomePageHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
404        int arg, char_t* url, char_t* path, char_t* query)
405{
406/*
407 *      If the empty or "/" URL is invoked, redirect default URLs to the home page
408 */
409        if (*url == '\0' || gstrcmp(url, T("/")) == 0) {
410#if 0
411                websRedirect(wp, T("home.asp"));
412#else
413                websRedirect(wp, T("index.html"));
414#endif
415                return 1;
416        }
417        return 0;
418}
419
420/******************************************************************************/
421
422#if B_STATS
423static void memLeaks()
424{
425        int             fd=1;
426
427        /* if ((fd = gopen(T("leak.txt"), O_CREAT | O_TRUNC | O_WRONLY)) >= 0) { */
428                bstats(fd, printMemStats);
429                /*
430                close(fd);
431        }
432                */
433}
434
435/******************************************************************************/
436/*
437 *      Print memory usage / leaks
438 */
439
440static void printMemStats(int handle, char_t *fmt, ...)
441{
442        va_list         args;
443        char_t          buf[256];
444
445        va_start(args, fmt);
446        vsprintf(buf, fmt, args);
447        va_end(args);
448        write(handle, buf, strlen(buf));
449}
450#endif
451
452/*****************************************************************************/
453
454/*****************************************************************************/
455/*
456 *      Default error handler.  The developer should insert code to handle
457 *      error messages in the desired manner.
458 */
459
460void defaultErrorHandler(int etype, char_t *msg)
461{
462#if 1
463        write(1, msg, gstrlen(msg));
464#endif
465}
466
467/*****************************************************************************/
468/*
469 *      Trace log. Customize this function to log trace output
470 */
471
472void defaultTraceHandler(int level, char_t *buf)
473{
474/*
475 *      The following code would write all trace regardless of level
476 *      to stdout.
477 */
478#if 1
479        if (buf) {
480                write(1, buf, gstrlen(buf));
481        }
482#endif
483}
484
485/*****************************************************************************/
486/*
487 *      Returns a pointer to an allocated qualified unique temporary file name.
488 *      This filename must eventually be deleted with bfree();
489 */
490
491char_t *websGetCgiCommName()
492{
493        char_t  *pname1, *pname2;
494
495        pname1 = tempnam(NULL, T("cgi"));
496        pname2 = bstrdup(B_L, pname1);
497        free(pname1);
498        return pname2;
499}
Note: See TracBrowser for help on using the repository browser.