miniserv...
"Paul Ingram" <[email protected]>
| Newsgroups | gmane.comp.lib.libwww |
|---|---|
| Message-ID | <[email protected]> |
Hello, I am trying to put together a fast and flexible XML-RPC server. I am basing my application on the libwww, Epinions XML-RPC libraries. and the expat XML parser. It has been a steep learning curve and I am not there yet. So far I have:- built a static library of libwww libraries - I can now listen using this library. picked up and built the latest expat release built the Epinions work into a static library. This is (sadly) under Windows and (thankfully) Borland C++ Builder 5. I would find a recent port of the old miniserv program to the current release of libwww extremely helpful, especially if some kind soul has taken it to Windows aswell. It seems a lot has changed since the 4.0D release of MiniServe. 4.0D bits attached... Best Regards, Paul. Paul Ingram Group Ltd email: [email protected] 140A High Street tel: +44 1483 862860 Godalming fax: +44 1483 862801 Surrey, www.ig.co.uk GU7 1AB United Kingdom www.sitedirector.org
HTServer.h
(application/octet-stream, 928 B)
/* W3C Mini Server
W3C MINI SERVER
*/
/*
** (c) COPYRIGHT MIT 1995.
** Please first read the full copyright statement in the file COPYRIGH.
*/
/*
The W3C Mini Server is a very simple cross platform, non-forking server. It is
developed as a test tool for the W3C Reference Library.
The module is implemented by HTServer.c, and it is a part of the W3C Mini Server.
*/
#ifndef HTSERVER_H
#define HTSERVER_H
/*
*/
typedef WORD SockOps;
#if WWWTRACE_MODE == WWWTRACE_TTY
#define STDOUT 1
#define OUTPUT 2 /* used in TTYPrint's switch for output multiplexing */
#else
#define STDOUT stdout
#define OUTPUT stdout /* output is a global target for output redirection */
#endif
/*
*/
#endif /* HTSERVER_H */
/* End of Declaration */
HTServer.c
(application/octet-stream, 12.1 KB)
/* HTServer.c ** MINI SERVER ** ** (c) COPRIGHT MIT 1995. ** Please first read the full copyright statement in the file COPYRIGH. ** ** Authors: ** HFN Henrik Frystyk Nielsen ([email protected]) ** ** History: ** Nov 24 95 First version */ #include "WWWLib.h" /* Global Library Include file */ #include "WWWApp.h" #include "WWWMIME.h" #include "WWWHTTP.h" #include "WWWFile.h" #include "WWWRules.h" #include "HTBInit.h" #include "HTServer.h" /* Implemented here */ #ifndef VS #define VS "unspecified" #endif #define APP_NAME "W3CMiniServer" #define APP_VERSION VS /* Default page for "-help" command line option */ #define HELP "http://www.w3.org/pub/WWW/MiniServ/User/CommandLine.html" #define DEFAULT_OUTPUT_FILE "web.out" #define DEFAULT_RULE_FILE "web.conf" #define DEFAULT_LOG_FILE "web.log" #define DEFAULT_PORT 80 #define DEFAULT_TIMEOUT 120 /* timeout in seconds */ #define DEFAULT_FORMAT WWW_SOURCE #define DEFAULT_BACKLOG HT_BACKLOG #define DEFAULT_ACCEPT -1 #if defined(__svr4__) #define CATCH_SIG #endif typedef enum _MSFlags { MS_PREEMPTIVE=0x1 } MSFlags; typedef struct _MiniServ { HTRequest * request; HTParentAnchor * anchor; HTList * active; /* List of active requests */ SOCKET port; struct timeval * tv; /* Timeout on socket */ HTList * converters; int backlog; /* Backlog for listen */ int accept; /* Total accepted connections served */ char * cwd; /* Current dir URL */ char * rules; char * logfile; MSFlags flags; } MiniServ; /* ------------------------------------------------------------------------- */ /* Create a Mini Server Object ** --------------------------- */ PRIVATE MiniServ * MiniServ_new (void) { MiniServ * me; if ((me = (MiniServ *) calloc(1, sizeof(MiniServ))) == NULL || (me->tv = (struct timeval*) calloc(1, sizeof(struct timeval))) == NULL) outofmem(__FILE__, "MiniServ_new"); me->tv->tv_sec = DEFAULT_TIMEOUT; me->cwd = HTFindRelatedName(); /* Bind the MiniServ object together with the Request Object */ me->request = HTRequest_new(); me->active = HTList_new(); HTList_addObject(me->active, me->request); me->port = DEFAULT_PORT; me->backlog = DEFAULT_BACKLOG; me->accept = DEFAULT_ACCEPT; /* Set default values in request object */ HTRequest_setGnHd(me->request, HT_G_DATE); HTRequest_setOutputFormat(me->request, DEFAULT_FORMAT); HTRequest_setContext(me->request, me); return me; } /* Delete a Mini Server Object ** --------------------------- */ PRIVATE BOOL MiniServ_delete (MiniServ * me) { if (me) { HTRequest_delete(me->request); if (me->logfile) HTLog_close(); HTList_delete(me->active); HT_FREE(me->cwd); HT_FREE(me->tv); HT_FREE(me); return YES; } return NO; } PRIVATE void Cleanup (MiniServ * me, int status) { HTNet_killAll(); MiniServ_delete(me); HTLibTerminate(); #ifdef VMS exit(status ? status : 1); #else exit(status ? status : 0); #endif } #ifdef CATCH_SIG #include <signal.h> /* SetSignal ** This function sets up signal handlers. This might not be necessary to ** call if the application has its own handlers. */ PRIVATE void SetSignal (void) { /* On some systems (SYSV) it is necessary to catch the SIGPIPE signal ** when attemting to connect to a remote host where you normally should ** get `connection refused' back */ if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { if (WWWTRACE) TTYPrint(TDEST, "HTSignal.... Can't catch SIGPIPE\n"); } else { if (WWWTRACE) TTYPrint(TDEST, "HTSignal.... Ignoring SIGPIPE\n"); } } #endif /* CATCH_SIG */ PRIVATE void VersionInfo (void) { TTYPrint(OUTPUT,"\n\nW3C Reference Software\n\n"); TTYPrint(OUTPUT,"\tW3C W3C Mini Server (%s) version %s.\n", APP_NAME, APP_VERSION); TTYPrint(OUTPUT,"\tW3C Reference Library version %s.\n\n",HTLib_version()); TTYPrint(OUTPUT,"Please send feedback to <[email protected]>\n"); } /* timeout_handler ** --------------- ** This function is registered to handle timeout in select eventloop */ PRIVATE int timeout_handler (HTRequest * request) { TTYPrint(TDEST, "Request timeout... We don't know how tow handle this yet :-(\n"); HTRequest_kill(request); return 0; } /* header_handler ** --------------- ** This function is registered to handle unknown MIME headers */ PRIVATE int header_handler (HTRequest * request, CONST char * token) { if (WWWTRACE) TTYPrint(TDEST, "Parsing unknown header `%s\'\n", token); return HT_OK; } /* server_handler ** --------------- ** Is called if we get a read notification on server port */ PRIVATE int server_handler (SOCKET master, HTRequest * request, SockOps ops) { MiniServ * ms = (MiniServ *) HTRequest_context(request); if (WWWTRACE) TTYPrint(TDEST, "Accepting... socket %d\n", master); if (ms->accept>0) ms->accept--; if (ops == FD_READ) { HTRequest * server = HTRequest_dup(request); HTList_addObject(ms->active, server); HTNet_newServer(server, master, "http"); return HT_OK; } return HT_ERROR; } /* terminate_handler ** ----------------- ** Is called whenever a request has terminated */ PRIVATE int terminate_handler (HTRequest * request, int status) { MiniServ * ms = (MiniServ *) HTRequest_context(request); if (WWWTRACE) TTYPrint(TDEST, "SERVER...... %p ended with status %d\n", request, status); if (HTLog_isOpen()) HTLog_add(request, status); HTRequest_delete(request); if (!ms->accept) { TTYPrint(TDEST,"SERVER...... Done - stopping\n"); Cleanup(ms, 0); } return HT_OK; } /* ------------------------------------------------------------------------- */ /* MAIN PROGRAM */ /* ------------------------------------------------------------------------- */ int main (int argc, char ** argv) { int arg; MiniServ * ms = MiniServ_new(); /* Starts Mac GUSI socket library */ #ifdef GUSI /* Starts Mac GUSI socket library */ GUSISetup(GUSIwithSIOUXSockets); GUSISetup(GUSIwithInternetSockets); #endif /* Initiate W3C Reference Library */ HTLibInit(APP_NAME, APP_VERSION); /* Initialize the protocol modules */ HTProtocol_add("http", NO, HTLoadHTTP, HTServHTTP); #if 0 HTProtocol_add("file", NO, HTLoadFile, NULL); #endif /* Initialize set of converters */ ms->converters = HTList_new(); HTConversion_add(ms->converters, "message/x-rfc822-head", "*/*", HTMIMEHeader, 1.0, 0.0, 0.0); HTConversion_add(ms->converters, "message/rfc822", "*/*", HTMIMEConvert, 1.0, 0.0, 0.0); HTConversion_add(ms->converters, "multipart/*", "*/*", HTBoundary, 1.0, 0.0, 0.0); HTFormat_setConversion(ms->converters); /* Initialize bindings between file suffixes and media types */ HTFileInit(); /* Get any proxy or gateway environment variables */ HTProxy_getEnvVar(); /* Register call back functions for the Net Manager */ HTNetCall_addBefore(HTLoadStart, 0); /* Scan command Line for parameters */ for (arg=1; arg<argc ; arg++) { if (*argv[arg] == '-') { /* -? or -help: show the command line help page */ if (!strcmp(argv[arg],"-?") || !strcmp(argv[arg],"-help")) { ms->anchor = (HTParentAnchor *) HTAnchor_findAddress(HELP); /* log file */ } else if (!strcmp(argv[arg], "-l")) { ms->logfile = (arg+1 < argc && *argv[arg+1] != '-') ? argv[++arg] : DEFAULT_LOG_FILE; /* rule file */ } else if (!strcmp(argv[arg], "-r")) { ms->rules = (arg+1 < argc && *argv[arg+1] != '-') ? argv[++arg] : DEFAULT_RULE_FILE; /* preemptive or non-preemptive access */ } else if (!strcmp(argv[arg], "-single")) { HTRequest_setPreemptive(ms->request, YES); ms->flags |= MS_PREEMPTIVE; /* timeout -- Change the default request timeout */ } else if (!strcmp(argv[arg], "-timeout")) { int timeout = (arg+1 < argc && *argv[arg+1] != '-') ? atoi(argv[++arg]) : DEFAULT_TIMEOUT; if (timeout > 0) ms->tv->tv_sec = timeout; /* server port */ } else if (!strncmp(argv[arg], "-p", 2)) { ms->port = (arg+1 < argc && *argv[arg+1] != '-') ? atoi(argv[++arg]) : DEFAULT_PORT; /* backlog for listen() */ } else if (!strcmp(argv[arg], "-backlog")) { ms->backlog = (arg+1 < argc && *argv[arg+1] != '-') ? atoi(argv[++arg]) : DEFAULT_BACKLOG; /* Total number of accepted connections to be served */ } else if (!strcmp(argv[arg], "-accept")) { ms->accept = (arg+1 < argc && *argv[arg+1] != '-') ? atoi(argv[++arg]) : DEFAULT_ACCEPT; /* directory listings */ } else if (!strncmp(argv[arg], "-d", 2)) { char *p = argv[arg]+2; for(;*p;p++) { switch (argv[arg][2]) { case 'r':HTFile_setDirReadme(HT_DIR_README_NONE); break; case 't':HTFile_setDirReadme(HT_DIR_README_TOP); break; case 'b':HTFile_setDirReadme(HT_DIR_README_BOTTOM);break; case 'n':HTFile_setDirAccess(HT_DIR_FORBID); break; case 's':HTFile_setDirAccess(HT_DIR_SELECTIVE); break; case 'y':HTFile_setDirAccess(HT_DIR_OK); break; default: if (WWWTRACE) TTYPrint(TDEST,"Bad parameter (%s) in -d option\n", argv[arg]); } } /* Print version and exit */ } else if (!strcmp(argv[arg], "-version")) { VersionInfo(); Cleanup(ms, 0); #ifdef WWWTRACE /* trace flags */ } else if (!strncmp(argv[arg], "-v", 2)) { char *p = argv[arg]+2; WWWTRACE = 0; for(; *p; p++) { switch (*p) { case 'a': WWWTRACE |= SHOW_ANCHOR_TRACE; break; case 'b': WWWTRACE |= SHOW_BIND_TRACE; break; case 'c': WWWTRACE |= SHOW_CACHE_TRACE; break; case 'g': WWWTRACE |= SHOW_SGML_TRACE; break; case 'p': WWWTRACE |= SHOW_PROTOCOL_TRACE; break; case 's': WWWTRACE |= SHOW_STREAM_TRACE; break; case 't': WWWTRACE |= SHOW_THREAD_TRACE; break; case 'u': WWWTRACE |= SHOW_URI_TRACE; break; default: if (WWWTRACE) TTYPrint(TDEST,"Bad parameter (%s) in -v option\n", argv[arg]); } } if (!WWWTRACE) WWWTRACE = SHOW_ALL_TRACE; #endif } else { if (WWWTRACE) TTYPrint(TDEST, "Bad Argument (%s)\n",argv[arg]); } } else { if (WWWTRACE) TTYPrint(TDEST, "Bad Argument (%s)\n",argv[arg]); } } #ifdef CATCH_SIG SetSignal(); #endif /* Register our User Prompts etc in the Alert Manager */ HTAlert_add(HTError_response, HT_A_MESSAGE); /* Register a call back function for the Net Manager */ HTNetCall_addAfter(terminate_handler, HT_ALL); /* Register our own MIME header handler for extra headers */ HTHeader_addParser("*", NO, header_handler); /* Set timeout on sockets */ HTEvent_registerTimeout(ms->tv, ms->request, timeout_handler, NO); /* Set max number of sockets we want open simultanously */ HTNet_setMaxSocket(32); /* Rule file specified? */ if (ms->rules) { HTList * list = HTList_new(); HTRequest * rr = HTRequest_new(); char * rules = HTParse(ms->rules, ms->cwd, PARSE_ALL); HTParentAnchor * ra = (HTParentAnchor *) HTAnchor_findAddress(rules); HTRequest_setPreemptive(rr, YES); HTConversion_add(list, "application/x-www-rules", "*/*", HTRules, 1.0, 0.0, 0.0); HTRequest_setConversion(rr, list, YES); if (HTLoadAnchor((HTAnchor *) ra, rr) != YES) if (WWWTRACE) TTYPrint(TDEST, "Can't access rules\n"); HTConversion_deleteAll(list); HTRequest_delete(rr); HT_FREE(rules); } /* Log file specifed? */ if (ms->logfile) HTLog_open(ms->logfile, YES, YES); /* Set up a server to listen on this port */ if (ms->port >= 0) { HTNet * net = HTNet_new(ms->request, ms->port); /* Start listening on the socket */ if (net && HTDoListen(net, ms->port, INVSOC, ms->backlog) == HT_OK) { /* Register a callback function for handling a request */ HTEvent_Register(HTNet_socket(net), ms->request, (SockOps) FD_READ, server_handler, HT_PRIORITY_MAX); } else { if (WWWTRACE) TTYPrint(TDEST,"Can't listen on port %d\n",ms->port); Cleanup(ms, -1); } } /* Go into the event loop... */ HTEvent_Loop(ms->request); /* Only gets here if event loop fails */ Cleanup(ms, 0); return 0; }