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

4.104.114.84.95
Last change on this file since c1cdaa0 was c1cdaa0, checked in by Joel Sherrill <joel.sherrill@…>, on 10/27/99 at 12:50:33

Patch from Emmanuel Raguet <raguet@…> and Eric Valette
<valette@…> to add a port of the GoAhead? web server
(httpd) to the RTEMS build tree. They have successfully used
this BSP on i386/pc386 and PowerPC/mcp750.

Mark and Joel spoke with Nick Berliner <nickb@…> on
26 Oct 1999 about this port and got verbal approval to include
it in RTEMS distributions.

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