ulxr_http_server.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                 ulxr_http_server.cpp  -  a simple http server
00003                              -------------------
00004     begin                : Sam Apr 20 2002
00005     copyright            : (C) 2002-2007 by Ewald Arnold
00006     email                : ulxmlrpcpp@ewald-arnold.de
00007 
00008     $Id: ulxr_http_server.cpp 1050 2007-08-06 17:21:20Z ewald-arnold $
00009 
00010  ***************************************************************************/
00011 
00012 /**************************************************************************
00013  *
00014  * This program is free software; you can redistribute it and/or modify
00015  * it under the terms of the GNU Lesser General Public License as
00016  * published by the Free Software Foundation; either version 2 of the License,
00017  * or (at your option) any later version.
00018  *
00019  * This program is distributed in the hope that it will be useful,
00020  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022  * GNU General Public License for more details.
00023  *
00024  * You should have received a copy of the GNU Lesser General Public License
00025  * along with this program; if not, write to the Free Software
00026  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00027  *
00028  ***************************************************************************/
00029 
00030 // #define ULXR_SHOW_TRACE
00031 // #define ULXR_DEBUG_OUTPUT
00032 // #define ULXR_SHOW_READ
00033 // #define ULXR_SHOW_WRITE
00034 // #define ULXR_SHOW_XML
00035 
00036 #ifndef ULXR_OMIT_TCP_STUFF
00037 
00038 #define ULXR_NEED_EXPORTS
00039 #include <ulxmlrpcpp/ulxmlrpcpp.h>  // always first header
00040 
00041 #include <sys/stat.h>
00042 #include <csignal>
00043 
00044 #include <fstream>
00045 #include <iostream>
00046 #include <cctype>
00047 #include <memory>
00048 
00049 #include <ulxmlrpcpp/ulxr_http_server.h>
00050 #include <ulxmlrpcpp/ulxr_except.h>
00051 #include <ulxmlrpcpp/ulxr_dispatcher.h>
00052 #include <ulxmlrpcpp/ulxr_http_protocol.h>
00053 #include <ulxmlrpcpp/ulxr_callparse.h>
00054 #include <ulxmlrpcpp/ulxr_callparse_wb.h>
00055 #include <ulxmlrpcpp/ulxr_file_resource.h>
00056 
00057 #ifdef __WIN32__
00058 #include <process.h>
00059 #include <Winsock2.h>
00060 //#include <windows.h>
00061 #endif
00062 
00063 #ifdef __unix__
00064 #include <sys/socket.h>
00065 #endif
00066 
00067 #ifdef ULXR_MULTITHREADED
00068 
00069 #ifdef __unix__
00070 #include <pthread.h>
00071 #endif
00072 
00073 #endif
00074 
00075 
00076 namespace ulxr {
00077 
00078 
00079 #ifdef ULXR_MULTITHREADED
00080 
00081 /* Helper class for thread handling
00082  */
00083 class HttpServer::ThreadData
00084 {
00085  public:
00086 
00087 #ifdef __unix__
00088   typedef pthread_t  handle_t;
00089 #elif defined(__WIN32__)
00090   typedef HANDLE     handle_t;
00091 #else
00092 #error unsupported platform here
00093 #endif
00094 
00095  /* Constucts the thread data
00096   * @param  server  pointer to the server object
00097   * @param  prot    pointer to the private connection
00098   */
00099   ThreadData (HttpServer *server, HttpProtocol *prot);
00100 
00101  /* Gets info, if thread should continue to run.
00102   * @return true: thread should continue
00103   */
00104   bool shouldRun() const;
00105 
00106  /* Signals thread to terminate
00107   */
00108   void requestTermination();
00109 
00110  /* Gets the thread handle.
00111   * @return handle from operation system
00112   */
00113   handle_t getHandle() const;
00114 
00115  /* Sets the thread handle.
00116   * @param  handle   handle from operation system
00117   */
00118   void setHandle(handle_t hd);
00119 
00120  /* Gets the connection.
00121   * @return connection
00122   */
00123   HttpProtocol *getProtocol() const;
00124 
00125  /* Increments invocation counter.
00126   */
00127   void incInvoked();
00128 
00129  /* Returns the invocation counter.
00130   * @return number of processed requests
00131   */
00132   unsigned numInvoked() const;
00133 
00134  /* Gets the server object.
00135   * @return server object
00136   */
00137   HttpServer *getServer() const;
00138 
00139  private:
00140 
00141   bool             run;
00142   handle_t         handle;
00143   unsigned         ctrInvoked;
00144   HttpProtocol    *protocol;
00145   HttpServer      *server;
00146 };
00147 
00148 #endif //  ULXR_MULTITHREADED
00149 
00150 
00151 ULXR_API_IMPL0 HttpServer::HttpServer (HttpProtocol* prot, bool wbxml)
00152 {
00153   init();
00154   wbxml_mode = wbxml;
00155   base_protocol = prot;
00156   base_protocol->setChunkedTransfer(false);
00157 }
00158 
00159 
00160 #ifdef ULXR_MULTITHREADED
00161 
00162 ULXR_API_IMPL0 HttpServer::HttpServer (HttpProtocol* prot, unsigned num_threads, bool wbxml)
00163 {
00164   prot->setChunkedTransfer(false);
00165   init();
00166   wbxml_mode = wbxml;
00167   for (unsigned i = 0; i < num_threads; ++i)
00168 #ifdef _MSC_VER
00169     threads.push_back(new ThreadData(this, (HttpProtocol*)(prot->detach())));
00170 #else
00171     threads.push_back(new ThreadData(this, dynamic_cast<HttpProtocol*>(prot->detach())));
00172 #endif
00173   base_protocol = 0;
00174 }
00175 
00176 #endif // ULXR_MULTITHREADED
00177 
00178 
00179 ULXR_API_IMPL(void) HttpServer::init()
00180 {
00181   http_root_dir = ULXR_GET_STRING(ULXR_DATADIR)
00182                 + ULXR_DIRSEP
00183                 + ULXR_GET_STRING(ULXR_PACKAGE)
00184                 + ULXR_DIRSEP
00185                 + ULXR_PCHAR("http");
00186 //  ULXR_TRACE(ULXR_PCHAR("http-root is ") << http_root_dir);
00187   rpc_resource_root = ULXR_PCHAR("/RPC2");
00188   rpc_dispatcher = 0;
00189   pico_shall_run = true;
00190   wbxml_mode = false;
00191 }
00192 
00193 
00194 ULXR_API_IMPL(void) HttpServer::releaseHandlers(std::vector<MethodHandler*> &handlers)
00195 {
00196    for (unsigned i = 0; i < handlers.size(); ++i)
00197      delete handlers[i];
00198    handlers.clear();
00199 }
00200 
00201 
00202 ULXR_API_IMPL0 HttpServer::~HttpServer ()
00203 {
00204 #ifdef ULXR_MULTITHREADED
00205 
00206   waitAsync(true);
00207 
00208   // don't delete base_protocol!!
00209   releaseThreads();
00210 
00211 #endif
00212 
00213   for (unsigned i = 0; i < resources.size(); ++i)
00214   {
00215     resources[i]->close();
00216     delete resources[i];
00217   }
00218 
00219   releaseHandlers(getHandlers);
00220   releaseHandlers(putHandlers);
00221   releaseHandlers(deleteHandlers);
00222   releaseHandlers(postHandlers);
00223 }
00224 
00225 
00226 ULXR_API_IMPL(void) HttpServer::setRpcDispatcher(Dispatcher *disp)
00227 {
00228   ULXR_TRACE(ULXR_PCHAR("setRpcDispatcher"));
00229   rpc_dispatcher = disp;
00230   rpc_dispatcher->setProtocol(0); // don't use internal protocol data
00231 }
00232 
00233 
00234 ULXR_API_IMPL(void) HttpServer::interpreteHttpHeader(
00235     HttpProtocol *protocol,
00236     CppString &head_resource,
00237     CppString &head_method,
00238     CppString &head_version)
00239 {
00240   ULXR_TRACE(ULXR_PCHAR("interpreteHttpHeader"));
00241   head_method = ULXR_PCHAR("");
00242   head_resource = ULXR_PCHAR("");
00243   head_version = ULXR_PCHAR("");
00244 
00245   CppString s = ulxr::stripWS(protocol->getFirstHeaderLine());
00246   std::size_t pos = s.find(' ');
00247   if (pos != CppString::npos)
00248   {
00249     head_method = s.substr(0, pos);
00250     s.erase(0, pos+1);
00251   }
00252   else
00253   {
00254     head_method = s;
00255     s = ULXR_PCHAR("");
00256   }
00257   makeUpper(head_method);
00258 
00259   s = stripWS(s);
00260   pos = s.find(' ');
00261   if (pos != CppString::npos)
00262   {
00263     head_resource = s.substr(0, pos);
00264     s.erase(0, pos+1);
00265   }
00266   else
00267   {
00268     head_resource = s;
00269     s = ULXR_PCHAR("");
00270   }
00271 
00272   s = stripWS(s);
00273   head_version = s;
00274   pos = head_version.find('/');
00275   if (pos != CppString::npos)
00276     head_version.erase(0, pos+1);
00277 
00278   protocol->setPersistent(!protocol->determineClosing(head_version));
00279 }
00280 
00281 
00282 ULXR_API_IMPL(void) HttpServer::setHttpRoot(const CppString &rt)
00283 {
00284   ULXR_TRACE(ULXR_PCHAR("setHttpRoot"));
00285   http_root_dir = rt;
00286   int rl = rt.length();
00287   if (rl != 0 && http_root_dir[rl-1] == ULXR_DIRSEP[0])
00288     http_root_dir.erase(rl-1);
00289 }
00290 
00291 
00292 ULXR_API_IMPL(void) HttpServer::checkValidPath(const CppString &resource)
00293 {
00294   ULXR_TRACE(ULXR_PCHAR("checkValidPath"));
00295   if (resource.find(ULXR_PCHAR("..")) != CppString::npos)
00296     throw ConnectionException(ApplicationError,
00297                         ulxr_i18n(ULXR_PCHAR("Bad request to resource")), 400);
00298 }
00299 
00300 
00301 ULXR_API_IMPL(CppString) HttpServer::stripResource(const CppString &in_resource)
00302 {
00303   ULXR_TRACE(ULXR_PCHAR("stripResource ") << in_resource);
00304   CppString resource = in_resource;
00305   CppString s = ULXR_PCHAR("http:");
00306   if (resource.substr(0, s.length()) == s)
00307     resource.erase(0, s.length());
00308 
00309   s = ULXR_PCHAR("https:");
00310   if (resource.substr(0, s.length()) == s)
00311     resource.erase(0, s.length());
00312 
00313   s = ULXR_PCHAR("//");
00314   if (resource.substr(0, s.length()) == s)
00315     resource.erase(0, s.length());
00316 
00317 #ifdef _MSC_VER
00318   size_t pos = 0;
00319 #else
00320   std::size_t pos = 0;
00321 #endif
00322   if ((pos = resource.find(ULXR_PCHAR("/"))) != CppString::npos)
00323     resource.erase(0, pos);
00324   else
00325     resource = ULXR_PCHAR("");
00326 
00327   return resource;
00328 }
00329 
00330 
00331 ULXR_API_IMPL(void)
00332   HttpServer::executeHttpMethod(HttpProtocol *protocol,
00333                                 Cpp8BitString &conn_pending_data,
00334                                 const CppString& name,
00335                                 const CppString& in_resource)
00336 {
00337    ULXR_TRACE(ULXR_PCHAR("executeHttpMethod ") << ULXR_PCHAR(" ")
00338               << name << ULXR_PCHAR(" ") << in_resource);
00339    CppString resource = stripResource(in_resource);
00340    checkValidPath(resource);
00341    ULXR_TRACE(ULXR_PCHAR("executeHttpMethod resource: ") << resource);
00342 
00343    if (name == ULXR_PCHAR("GET"))
00344    {
00345       for (unsigned int i = 0; i < getHandlers.size(); ++i)
00346         if (getHandlers[i]->handle(protocol, name, resource, conn_pending_data))
00347           return;
00348 
00349       executeHttpGET(protocol, resource);
00350    }
00351 
00352    else if (name == ULXR_PCHAR("POST"))
00353    {
00354       for (unsigned int i = 0; i < postHandlers.size(); ++i)
00355         if (postHandlers[i]->handle(protocol, name, resource, conn_pending_data))
00356           return;
00357 
00358       executeHttpPOST(protocol, conn_pending_data, resource);
00359    }
00360 
00361    else if (name == ULXR_PCHAR("PUT"))
00362    {
00363       for (unsigned int i = 0; i < putHandlers.size(); ++i)
00364         if (putHandlers[i]->handle(protocol, name, resource, conn_pending_data))
00365           return;
00366 
00367       executeHttpPUT(protocol, conn_pending_data, resource);
00368    }
00369 
00370    else if (name == ULXR_PCHAR("DELETE"))
00371    {
00372       for (unsigned int i = 0; i < deleteHandlers.size(); ++i)
00373         if (deleteHandlers[i]->handle(protocol, name, resource, conn_pending_data))
00374           return;
00375 
00376       executeHttpDELETE(protocol, resource);
00377    }
00378 
00379    else
00380      executeUnknownHttpMethod(protocol, conn_pending_data, name, resource);
00381 
00382    return;
00383 }
00384 
00385 
00386 ULXR_API_IMPL(void)
00387   HttpServer::executeUnknownHttpMethod(HttpProtocol * /* protocol */,
00388                                        Cpp8BitString & /* conn_pending_data */,
00389                                        const CppString& name,
00390                                        const CppString& /* resource */)
00391 {
00392      throw ConnectionException(NotConformingError,
00393                          ulxr_i18n(ULXR_PCHAR("Unimplemented http method: "))+name, 501);
00394 }
00395 
00396 
00397 ULXR_API_IMPL(CppString) HttpServer::createLocalName(const CppString &resource)
00398 {
00399   ULXR_TRACE(ULXR_PCHAR("createLocalName ")  << resource);
00400   ULXR_TRACE(ULXR_PCHAR("  http-root: ")  << http_root_dir);
00401   CppString filename = http_root_dir;
00402   if (resource.length() == 0 || resource[0] != ULXR_DIRSEP[0])
00403     filename += ULXR_DIRSEP[0];
00404 
00405   CppString fullname = filename + resource;
00406 
00407 #ifndef __unix__
00408   std::size_t pos = fullname.find (ULXR_CHAR('/'));
00409   while (pos != CppString::npos)
00410   {
00411     fullname[pos] = ULXR_DIRSEP[0];
00412     pos = fullname.find (ULXR_CHAR('/'), pos+1);
00413   }
00414 #else
00415   std::size_t pos = fullname.find (ULXR_CHAR('\\'));
00416   while (pos != CppString::npos)
00417   {
00418     fullname[pos] = ULXR_DIRSEP[0];
00419     pos = fullname.find (ULXR_CHAR('\\'), pos+1);
00420   }
00421 #endif
00422 
00423   return fullname;
00424 }
00425 
00426 
00427 CppString /*ULXR_API_IMPL0*/
00428   HttpServer::guessMimeType(const CppString &name) const
00429 {
00430   // simply guess from extension for now
00431   std::size_t pos = name.rfind('.');
00432   const ulxr::Char *mime = ULXR_PCHAR("");
00433   if (pos != CppString::npos)
00434   {
00435     CppString ext = name.substr(pos+1);
00436     makeLower(ext);
00437     if (   ext == ULXR_PCHAR("html")
00438         || ext == ULXR_PCHAR("htm"))
00439       mime = ULXR_PCHAR("text/html");
00440 
00441     else if (ext == ULXR_PCHAR("txt"))
00442       mime = ULXR_PCHAR("text/plain");
00443 
00444     else if (ext == ULXR_PCHAR("xml"))
00445       mime = ULXR_PCHAR("text/xml");
00446 
00447     else if (   ext == ULXR_PCHAR("jpeg")
00448              || ext == ULXR_PCHAR("jpg"))
00449       mime = ULXR_PCHAR("image/jpg");
00450 
00451     else if (ext == ULXR_PCHAR("png"))
00452       mime = ULXR_PCHAR("image/png");
00453 
00454     else if (ext == ULXR_PCHAR("gif"))
00455       mime = ULXR_PCHAR("image/gif");
00456   }
00457 
00458   return (CppString) mime;
00459 }
00460 
00461 
00462 ULXR_API_IMPL(void) HttpServer::addResource(CachedResource *cache)
00463 {
00464   ULXR_TRACE(ULXR_PCHAR("addResource ") << (cache ? cache->getResourceName() : ULXR_PCHAR("")));
00465   if (0 == getResource(cache->getResourceName()))
00466     resources.push_back(cache);
00467 }
00468 
00469 
00470 ULXR_API_IMPL(CachedResource *) HttpServer::getResource(const CppString& resource)
00471 {
00472   ULXR_TRACE(ULXR_PCHAR("getResource ") << resource);
00473   for (unsigned i = 0; i < resources.size(); ++i)
00474     if (resources[i]->getResourceName() == resource)
00475     {
00476       ULXR_TRACE(ULXR_PCHAR("getResource: true"));
00477       return resources[i];
00478     }
00479 
00480   ULXR_TRACE(ULXR_PCHAR("getResource: false"));
00481   return 0;
00482 }
00483 
00484 
00485 ULXR_API_IMPL(void) HttpServer::executeHttpGET(HttpProtocol *protocol,
00486                                             const CppString& in_resource)
00487 {
00488   ULXR_TRACE(ULXR_PCHAR("executeHttpGET"));
00489 
00490   CppString filename;
00491   CppString resource = in_resource;
00492   if (resource == ULXR_PCHAR("/"))
00493   {
00494     filename = createLocalName(ULXR_DIRSEP ULXR_PCHAR("index.html")); // common assumption
00495     resource = ULXR_PCHAR("index.html");
00496   }
00497   else
00498     filename = createLocalName(resource);
00499 
00500   CachedResource *cache = getResource(resource);
00501   if (cache == 0)
00502   {
00503     cache = new FileResource(resource, filename);
00504     addResource(cache);
00505     cache->open();
00506   }
00507   else
00508     cache->reset();
00509 
00510   if (!cache->good())
00511     throw ConnectionException(SystemError,
00512                               ulxr_i18n(ULXR_PCHAR("Cannot open local input resource: "))+resource, 500);
00513 
00514   std::string s = cache->data();
00515   ULXR_TRACE(ULXR_PCHAR("executeHttpGET cachesize ") << s.length());
00516   protocol->sendResponseHeader(200, ULXR_PCHAR("OK"), guessMimeType(filename), s.length());
00517   protocol->writeBody(s.data(), s.length());
00518 }
00519 
00520 
00521 ULXR_API_IMPL(void) HttpServer::executeHttpRPC(HttpProtocol *protocol,
00522                                             Cpp8BitString &conn_pending_data)
00523 {
00524   ULXR_TRACE(ULXR_PCHAR("executeHttpRPC"));
00525 
00526 #ifdef ULXR_ENFORCE_NON_PERSISTENT
00527   protocol->setPersistent(false);
00528 #endif
00529 
00530   if (!protocol->hasHttpProperty(ULXR_PCHAR("content-length")))
00531   {
00532 #ifdef ULXR_SHOW_READ
00533     char buffer [ULXR_RECV_BUFFER_SIZE];
00534     unsigned readed;
00535     Cpp8BitString super_data;
00536     while ((readed = protocol->readRaw(buffer, sizeof(buffer))) > 0)
00537       super_data.append(buffer, readed);
00538     ULXR_DOUT_READ(ULXR_PCHAR("superdata 2 start:\n")
00539                    << ULXR_GET_STRING(super_data)
00540                    << ULXR_PCHAR("superdata 2 end:\n"));
00541 #endif
00542     throw ConnectionException(NotConformingError,
00543                         ulxr_i18n(ULXR_PCHAR("Content-Length of message not available")), 411);
00544   }
00545 
00546   else if (  !protocol->hasHttpProperty(ULXR_PCHAR("content-type"))
00547            || (   (protocol->getHttpProperty(ULXR_PCHAR("content-type")).find(ULXR_PCHAR("text/xml")) == CppString::npos)
00548                && (protocol->getHttpProperty(ULXR_PCHAR("content-type")).find(ULXR_PCHAR("wbxml")) == CppString::npos)
00549               )
00550           )
00551     throw ConnectionException(NotConformingError,
00552                         ulxr_i18n(ULXR_PCHAR("Bad request, mime type not 'text/xml'")), 400);
00553 
00554   Cpp8BitString xml_data = conn_pending_data;
00555 
00556   char conn_buffer [ULXR_RECV_BUFFER_SIZE];
00557   long conn_readed;
00558   bool done = false;
00560   while (!done && ((conn_readed = protocol->readRaw(conn_buffer, sizeof(conn_buffer))) > 0) )
00561   {
00562     if (!protocol->hasBytesToRead())
00563       done = true;
00564     xml_data.append(conn_buffer, conn_readed);
00565   }
00566 
00567   std::auto_ptr<XmlParserBase> parser;
00568   MethodCallParserBase *cpb = 0;
00569   if (wbxml_mode)
00570   {
00571     ULXR_TRACE(ULXR_PCHAR("waitForResponse in WBXML"));
00572     MethodCallParserWb *cp = new MethodCallParserWb();
00573     cpb = cp;
00574 #ifdef _MSC_VER
00575   std::auto_ptr<XmlParserBase> temp(cp);
00576   parser = temp;
00577 #else
00578     parser.reset(cp);
00579 #endif
00580   }
00581   else
00582   {
00583     ULXR_TRACE(ULXR_PCHAR("waitForResponse in XML"));
00584     MethodCallParser *cp = new MethodCallParser();
00585     cpb = cp;
00586 #ifdef _MSC_VER
00587   std::auto_ptr<XmlParserBase> temp(cp);
00588   parser = temp;
00589 #else
00590     parser.reset(cp);
00591 #endif
00592   }
00593 
00594   ULXR_DOUT_XML(ULXR_GET_STRING(std::string(xml_data.data(), xml_data.length())));
00595   if (!parser->parse(xml_data.data(), xml_data.length(), true))
00596   {
00597     throw XmlException(parser->mapToFaultCode(parser->getErrorCode()),
00598                        ulxr_i18n(ULXR_PCHAR("Problem while parsing xml request")),
00599                        parser->getCurrentLineNumber(),
00600                        ULXR_GET_STRING(parser->getErrorString(parser->getErrorCode())));
00601   }
00602   MethodCall call = cpb->getMethodCall();
00603   MethodResponse resp = rpc_dispatcher->dispatchCall(call);
00604   if (!protocol->isTransmitOnly())
00605     protocol->sendRpcResponse(resp, wbxml_mode);
00606 }
00607 
00608 
00609 ULXR_API_IMPL(void)
00610   HttpServer::executeHttpPOST(HttpProtocol *protocol,
00611                               Cpp8BitString &conn_pending_data,
00612                               const CppString& resource)
00613 {
00614   ULXR_TRACE(ULXR_PCHAR("executeHttpPOST"));
00615 
00616   if (resource == rpc_resource_root && rpc_dispatcher != 0)
00617     executeHttpRPC(protocol, conn_pending_data);
00618   else
00619   {
00620     if (rpc_dispatcher == 0)
00621       throw ConnectionException(ApplicationError,
00622                           ulxr_i18n(ULXR_PCHAR("No RPC-Dispatcher set")), 500);
00623     else
00624       throw ConnectionException(ApplicationError,
00625                           ulxr_i18n(ULXR_PCHAR("Method POST not allowed for this resource (Bad RPC-Request to \""))
00626                                + rpc_resource_root + ULXR_PCHAR("\" ?): ")+resource, 501);
00627   }
00628 //  if (!protocol->hasHttpProperty("content-length"))
00629 //    throw HttpException(411, ulxr_i18n("Content-Length of message not available"));
00630 }
00631 
00632 
00633 ULXR_API_IMPL(void) HttpServer::executeHttpPUT(HttpProtocol *protocol,
00634                                             Cpp8BitString &conn_pending_data,
00635                                             const CppString& in_resource)
00636 {
00637   ULXR_TRACE(ULXR_PCHAR("executeHttpPUT"));
00638 
00639   CppString filename;
00640   CppString resource = in_resource;
00641   if (resource == ULXR_PCHAR("/"))
00642   {
00643     filename = createLocalName(ULXR_DIRSEP ULXR_PCHAR("index.html")); // common assumption
00644     resource = ULXR_PCHAR("index.html");
00645   }
00646   else
00647     filename = createLocalName(resource);
00648 
00649   CachedResource *cache = getResource(resource);
00650   if (cache == 0)
00651   {
00652     cache = new FileResource(resource, filename, false);
00653     addResource(cache);
00654   }
00655   cache->clear();
00656 
00657 /*
00658   if (!protocol->hasHttpProperty("content-length"))
00659     throw HttpException(NotConformingError,
00660                         411, ulxr_i18n("Content-Length of message not not available"));
00661 */
00662   if (!cache->good() )
00663     throw ConnectionException(SystemError,
00664                         ulxr_i18n(ULXR_PCHAR("Cannot create local resource: "))+resource, 500);
00665 
00666 #ifdef ULXR_USE_WXSTRING
00667   cache->write(conn_pending_data.c_str(), conn_pending_data.length());
00668 #else
00669   cache->write(conn_pending_data.data(), conn_pending_data.length());
00670 #endif
00671 
00672   char conn_buffer [ULXR_RECV_BUFFER_SIZE];
00673   long conn_readed;
00674   bool done = false;
00676   while (!done && ((conn_readed = protocol->readRaw(conn_buffer, sizeof(conn_buffer))) > 0) )
00677   {
00678     if (!protocol->hasBytesToRead())
00679       done = true;
00680     cache->write(conn_buffer, conn_readed);
00681   }
00682 
00683   if (!cache->good() )
00684     throw ConnectionException(SystemError,
00685                         ulxr_i18n(ULXR_PCHAR("Cannot write to local resource: "))+resource, 500);
00686 
00687   protocol->sendResponseHeader(200, ULXR_PCHAR("OK"), ULXR_PCHAR(""), 0);
00688   return;
00689 }
00690 
00691 
00692 ULXR_API_IMPL(void)
00693   HttpServer::executeHttpDELETE(HttpProtocol *protocol,
00694                                 const CppString& in_resource)
00695 {
00696   ULXR_TRACE(ULXR_PCHAR("executeHttpDELETE"));
00697   CppString filename;
00698   CppString resource = in_resource;
00699   if (resource == ULXR_PCHAR("/"))
00700   {
00701     filename = createLocalName(ULXR_DIRSEP ULXR_PCHAR("index.html")); // common assumption
00702     resource = ULXR_PCHAR("index.html");
00703   }
00704   else
00705     filename = createLocalName(resource);
00706 
00707   CachedResource *cache = getResource(resource);
00708   if (cache == 0)
00709   {
00710     cache = new FileResource(resource, filename, false);
00711     addResource(cache);
00712   }
00713   cache->clear();
00714 
00715   if (!cache->good())
00716     throw ConnectionException(SystemError,
00717                         ulxr_i18n(ULXR_PCHAR("Cannot remove local resource: "))+resource, 500);
00718 
00719   protocol->sendResponseHeader(200, ULXR_PCHAR("OK"), ULXR_PCHAR(""), 0);
00720 }
00721 
00722 /*
00723 
00724 extern "C" void installhandler(int sig, void *context);
00725 extern "C" void handlesigaction(int sig, siginfo_t *info, void *context);
00726 
00727 
00728 void handlesigaction(int sig, siginfo_t *info,void *context)
00729 {
00730   fprintf(stderr,"Signal %d von Proze�%d/User %d empfangen ...\n",
00731                  sig,info->si_pid,info->si_uid);
00732   switch(sig)
00733   {
00734     case SIGINT:  // fallthrough
00735     case SIGTERM:
00736 //    beende=1;
00737     break;
00738   }
00739 }
00740 
00741 
00742 void installhandler(int sig)
00743 {
00744   struct sigaction action;
00745   action.sa_flags = SA_SIGINFO;
00746   action.sa_sigaction = handlesigaction;
00747   sigemptyset(&action.sa_mask);
00748   sigaction(sig,&action,NULL);
00749 }
00750 */
00751 
00752 
00753 ULXR_API_IMPL(void) HttpServer::requestTermination()
00754 {
00755   pico_shall_run = false;
00756 }
00757 
00758 
00759 ULXR_API_IMPL(std::size_t) HttpServer::runPicoHttpd()
00760 {
00761   ULXR_TRACE(ULXR_PCHAR("runPicoHttpd"));
00762 #ifdef ULXR_MULTITHREADED
00763   if (threads.size() != 0)
00764     return dispatchAsync();
00765   else
00766 #endif
00767     return runPicoHttpd(base_protocol, 0);
00768 }
00769 
00770 
00771 ULXR_API_IMPL(void) HttpServer::beforeHttpTransaction()
00772 {
00773 }
00774 
00775 
00776 ULXR_API_IMPL(void) HttpServer::afterHttpTransaction()
00777 {
00778 }
00779 
00780 
00781 ULXR_API_IMPL(std::size_t)
00782   HttpServer::runPicoHttpd(HttpProtocol *protocol,
00783 #ifdef ULXR_MULTITHREADED
00784                            ThreadData *td)
00785 #else
00786                            ThreadData *)
00787 #endif
00788 {
00789   ULXR_TRACE(ULXR_PCHAR("runPicoHttpd(HttpProtocol) ")
00790              << std::hex << (void*) protocol
00791              << std::dec);
00792 
00793   pico_shall_run = true;
00794 //  installhandler(SIGTERM);
00795 
00796   rpc_dispatcher->setProtocol(0);
00797 
00798   while (pico_shall_run
00799 #ifdef ULXR_MULTITHREADED
00800          && td->shouldRun()
00801 #endif
00802         )
00803   {
00804     ULXR_TRACE(ULXR_PCHAR("runPicoHttpd 0"));
00805     try
00806     {
00807 
00808 #ifdef ULXR_MULTITHREADED
00809       if (td != 0)
00810         td->incInvoked();
00811 #endif // ULXR_MULTITHREADED
00812 
00813       beforeHttpTransaction();
00814       ULXR_TRACE(ULXR_PCHAR("runPicoHttpd 1"));
00815       performHttpTransaction(protocol);
00816       ULXR_TRACE(ULXR_PCHAR("runPicoHttpd 2"));
00817       afterHttpTransaction();
00818     }
00819 
00820     catch(ConnectionException &ex)
00821     {
00822       forwardThreadedError(ex);
00823       try
00824       {
00825         if (protocol->isOpen())
00826           protocol->sendNegativeResponse(ex.getStatusCode(), ex.why());  // try to return error
00827         protocol->close();
00828       }
00829       catch(...)
00830       {
00831         ULXR_TRACE(ULXR_PCHAR("nested exception"));
00832         protocol->close();
00833       }
00834       ULXR_TRACE(ULXR_PCHAR("Transportation error occured: ") << ULXR_GET_STRING(ex.why()));
00835     }
00836 
00837     catch(Exception &ex)
00838     {
00839       forwardThreadedError(ex);
00840 
00841       try
00842       {
00843         if (protocol->isOpen())
00844           protocol->sendNegativeResponse(500, ex.why()); // try to return error
00845         protocol->close();
00846       }
00847       catch(...)
00848       {
00849         ULXR_TRACE(ULXR_PCHAR("nested exception"));
00850         protocol->close();
00851       }
00852       ULXR_TRACE(ULXR_PCHAR("Error occured: ") << ULXR_GET_STRING(ex.why()));
00853     }
00854 
00855     catch(std::exception &ex)
00856     {
00857       forwardThreadedError(Exception(ApplicationError, ULXR_GET_STRING(ex.what())));
00858 
00859       try
00860       {
00861         if (protocol->isOpen())
00862           protocol->sendNegativeResponse(500, ULXR_GET_STRING(ex.what())); // try to return error
00863         protocol->close();
00864       }
00865       catch(...)
00866       {
00867         ULXR_TRACE(ULXR_PCHAR("nested exception"));
00868         protocol->close();
00869       }
00870       ULXR_TRACE(ULXR_PCHAR("Error occured: ") << ULXR_GET_STRING(ex.what()));
00871     }
00872 
00873     catch(...)
00874     {
00875       ULXR_TRACE(ULXR_PCHAR("runPicoHttpd unknown exception"));
00876       RuntimeException ex (SystemError, ULXR_PCHAR("Unknown error occured"));
00877       forwardThreadedError(ex);
00878 
00879       try
00880       {
00881         if (protocol->isOpen())
00882           protocol->sendNegativeResponse(500, ex.why());  // try to return error
00883         protocol->close();
00884       }
00885       catch(...)
00886       {
00887         ULXR_TRACE(ULXR_PCHAR("runPicoHttpd nested exception"));
00888         protocol->close();
00889       }
00890       ULXR_TRACE(ULXR_PCHAR("Error occured: ") << ULXR_GET_STRING(ex.why()));
00891     }
00892   }
00893   ULXR_TRACE(ULXR_PCHAR("runPicoHttpd return 0, remaining Threads: ") << numThreads());
00894   return 0;
00895 }
00896 
00897 
00898 #ifdef ULXR_SHOW_TRACE
00899 ULXR_API_IMPL(void) HttpServer::forwardThreadedError(const Exception &ex) const
00900 #else
00901 ULXR_API_IMPL(void) HttpServer::forwardThreadedError(const Exception &) const
00902 #endif
00903 {
00904    ULXR_TRACE(ULXR_CHAR("Threaded error occured: ") << ex.why());
00905 }
00906 
00907 
00908 ULXR_API_IMPL(void) HttpServer::performHttpTransaction(HttpProtocol *protocol)
00909 {
00910   ULXR_TRACE(ULXR_PCHAR("performHttpTransaction ")
00911              << std::hex << (void*) protocol
00912              << std::dec);
00913   if (!protocol->isOpen())
00914   {
00915     if (!protocol->accept())
00916       return;
00917   }
00918   else
00919     protocol->resetConnection();
00920 
00921   CppString head_resource;
00922   CppString head_method;
00923   CppString head_version;
00924 
00925   ULXR_TRACE(ULXR_PCHAR("pHT 1"));
00926   Cpp8BitString conn_pending_data;
00927   char  conn_buffer [ULXR_RECV_BUFFER_SIZE];
00928   long  conn_readed = 0;
00929   char *buff_ptr;
00930   bool  done = false;
00931 
00932   ULXR_TRACE(ULXR_PCHAR("pHT 2 ") << done << ULXR_PCHAR(" ") << conn_readed);
00933   while (!done && ((conn_readed = protocol->readRaw(conn_buffer, sizeof(conn_buffer))) > 0) )
00934   {
00935     buff_ptr = conn_buffer;
00936 
00937     ULXR_TRACE(ULXR_PCHAR("pHT 3 ") << conn_readed);
00938     while (conn_readed > 0)
00939     {
00940       Protocol::State state = protocol->connectionMachine(buff_ptr, conn_readed);
00941       if (state == Protocol::ConnError)
00942         throw ConnectionException(TransportError,
00943                                   ulxr_i18n(ULXR_PCHAR("Network problem occured")), 500);
00944 
00945       // switch to appropriate method when header is completely read
00946       else if (   state == Protocol::ConnSwitchToBody
00947                || state == Protocol::ConnBody)
00948       {
00949         interpreteHttpHeader(protocol, head_resource, head_method, head_version);
00950         ULXR_TRACE(   ULXR_PCHAR("head_resource ") << head_resource << std::endl
00951                    << ULXR_PCHAR("head_method ") << head_method << std::endl
00952                    << ULXR_PCHAR("head_version ") << head_version);
00953         try
00954         {
00955           conn_pending_data.assign(buff_ptr, conn_readed);
00956           conn_readed = 0;
00957 
00958 #ifdef ULXR_ENFORCE_NON_PERSISTENT
00959           protocol->setPersistent(false);
00960 #endif
00961 
00962           CppString realm = getRealm(head_resource);
00963           if (protocol->checkAuthentication(realm))
00964             executeHttpMethod(protocol,
00965                               conn_pending_data,
00966                               head_method,
00967                               head_resource);
00968           else
00969             protocol->rejectAuthentication(realm);
00970 
00971           done = true;
00972           conn_readed = 0;
00973           if (protocol->isOpen() && !protocol->isPersistent())
00974             protocol->close();
00975         }
00976 
00977         catch(ConnectionException &ex)
00978         {
00979           if (protocol->isOpen())
00980             protocol->sendNegativeResponse(500, ex.why());
00981           protocol->close();
00982           throw;
00983         }
00984       }
00985     }
00986   }
00987 }
00988 
00989 
00990 ULXR_API_IMPL(void)
00991   HttpServer::addHttpHandler(const CppString &in_name, MethodHandler *handler)
00992 {
00993   ULXR_TRACE(ULXR_PCHAR("addHttpHandler"));
00994   CppString name = in_name;
00995   makeUpper(name);
00996   if (name == ULXR_PCHAR("GET"))
00997      getHandlers.push_back(handler);
00998 
00999   else if (name == ULXR_PCHAR("POST"))
01000      postHandlers.push_back(handler);
01001 
01002   else if (name == ULXR_PCHAR("PUT"))
01003      putHandlers.push_back(handler);
01004 
01005   else if (name == ULXR_PCHAR("DELETE"))
01006      deleteHandlers.push_back(handler);
01007 
01008   else
01009      throw RuntimeException(ApplicationError,
01010                             ULXR_PCHAR("Attempt to register a handler for")
01011                             ULXR_PCHAR(" an unknown method"));
01012 }
01013 
01014 /*
01015 ULXR_API_IMPL(void)
01016   HttpServer::removeHttpHandler(const CppString &in_name,
01017                                 MethodHandler handler)
01018 {
01019   ULXR_TRACE(ULXR_PCHAR("removeHttpHandler"));
01020   makeUpper(name);
01021   std::vector<MethodHandler> *handlers;
01022   if (name == ULXR_PCHAR("GET"))
01023      handlers = &getHandlers;
01024 
01025   else if (name == ULXR_PCHAR("POST"))
01026      handlers = &postHandlers;
01027 
01028   else if (name == ULXR_PCHAR("PUT"))
01029      handlers = &putHandlers;
01030 
01031   else if (name == ULXR_PCHAR("DELETE"))
01032      handlers = &deleteHandlers;
01033 
01034   else
01035      throw RuntimeException(ApplicationError,
01036                             ULXR_PCHAR("Attempt to remove a handler for")
01037                             ULXR_PCHAR(" an unknown method"));
01038 
01039   for (int i = handlers->size()-1; i >= 0; --i)
01040     if ((*handlers)[i] == handler)
01041        handlers->erase(handlers->begin()+i);
01042 }
01043 */
01044 
01045 ULXR_API_IMPL(CppString) HttpServer::getRealm(const CppString &i_path) const
01046 {
01047    ULXR_TRACE(ULXR_PCHAR("getRealm ") << i_path);
01048 
01049    if (i_path.length() == 0)
01050      return ULXR_PCHAR("");
01051 
01052    std::map<CppString, CppString>::const_iterator it = realmXrefs.find(i_path);
01053    if (it != realmXrefs.end())
01054      return (*it).second;  // exact match
01055 
01056    ULXR_TRACE(ULXR_PCHAR("getRealm 1"));
01057    CppString rsrc;
01058    CppString longest_path;
01059    for (it = realmXrefs.begin(); it != realmXrefs.end(); ++it)
01060    {
01061      ULXR_TRACE(ULXR_PCHAR("find ") << (*it).first << ULXR_PCHAR(" ")  << (*it).second);
01062      if (i_path.find((*it).first) != CppString::npos) // longest partial match from beginning
01063        if ((*it).first.length() > longest_path.length())
01064        {
01065          rsrc = (*it).second;
01066          longest_path = (*it).first;
01067        }
01068    }
01069 
01070    if (rsrc.length() != 0)
01071      return rsrc;
01072 
01073    ULXR_TRACE(ULXR_PCHAR("getRealm 3"));
01074    // second try: add trailing slash to requested resource
01075    CppString path2 = i_path + ULXR_PCHAR("/");
01076    for (it = realmXrefs.begin(); it != realmXrefs.end(); ++it)
01077    {
01078      ULXR_TRACE(ULXR_PCHAR("find ") << (*it).first << ULXR_PCHAR(" ")  << (*it).second);
01079      if (path2.find((*it).first) != CppString::npos) // longest partial match from beginning
01080        if ((*it).first.length() > longest_path.length())
01081        {
01082          rsrc = (*it).second;
01083          longest_path = (*it).first;
01084        }
01085    }
01086 
01087    if (rsrc.length() != 0)
01088      return rsrc;
01089 
01090    ULXR_TRACE(ULXR_PCHAR("getRealm 4"));
01091    return ULXR_PCHAR("");
01092 }
01093 
01094 
01095 ULXR_API_IMPL(void) HttpServer::addRealm(const CppString &path, const CppString &realm)
01096 {
01097    ULXR_TRACE(ULXR_PCHAR("addRealm: ") + realm + ULXR_PCHAR(" at ") + path);
01098    realmXrefs[path] = realm;
01099 }
01100 
01101 
01102 ULXR_API_IMPL(void)
01103   HttpServer::addAuthentication(const CppString &user,
01104                                 const CppString &pass,
01105                                 const CppString &realm)
01106 {
01107    ULXR_TRACE(ULXR_PCHAR("addAuthentication"));
01108 #ifdef ULXR_MULTITHREADED
01109    for (unsigned i = 0; i < threads.size(); ++i)
01110      threads[i]->getProtocol()->addAuthentication(user, pass, realm);
01111 #endif
01112 
01113    if (base_protocol != 0)
01114      base_protocol->addAuthentication(user, pass, realm);
01115 }
01116 
01117 
01118 #ifdef ULXR_MULTITHREADED
01119 
01120 ULXR_API_IMPL(void *) HttpServer::startThread(ThreadData *td)
01121 {
01122   ULXR_TRACE(ULXR_PCHAR("startThread ")
01123              << std::hex << (void*) td
01124              << std::dec);
01125    void *ptr = (void*) (td->getServer())->runPicoHttpd(td->getProtocol(), td);
01126    ULXR_TRACE(ULXR_PCHAR("/startThread "));
01127 //   sleep(1);
01128    return ptr;
01129 }
01130 
01131 
01132 ULXR_API_IMPL(unsigned) HttpServer::dispatchAsync()
01133 {
01134   ULXR_TRACE(ULXR_PCHAR("dispatchAsync()"));
01135   unsigned num_started = 0;
01136 
01137   for (unsigned i = 0; i < threads.size(); ++i)
01138   {
01139     ThreadData::handle_t tdh;
01140 #ifdef __unix__
01141     typedef void* (*pthread_sig)(void*);
01142     int result = pthread_create(&tdh, 0, (pthread_sig)startThread, threads[i]);
01143     if (result == 0)
01144       ++num_started;
01145 #elif defined(__WIN32__)
01146     unsigned tid;
01147     typedef unsigned int (__stdcall *thread_sig)(void*);
01148     tdh = (HANDLE)_beginthreadex(0, 16*1024, (thread_sig)startThread,
01149                                  threads[i], CREATE_SUSPENDED,
01150                                  &tid );
01151     int resume = ResumeThread(tdh);
01152     if (tdh >= 0 && resume >= 0)
01153       ++num_started;
01154 #else
01155 #error unsupported platform here
01156 #endif
01157     threads[i]->setHandle(tdh);
01158   }
01159   ULXR_TRACE(ULXR_PCHAR("/dispatchAsync()"));
01160   return num_started;
01161 }
01162 
01163 
01164 ULXR_API_IMPL(unsigned) HttpServer::numThreads() const
01165 {
01166   return threads.size();
01167 }
01168 
01169 
01170 ULXR_API_IMPL(void) HttpServer::terminateAllThreads(unsigned /*time*/)
01171 {
01172   ULXR_TRACE(ULXR_PCHAR("Request to terminate all threads."));
01173   requestTermination();
01174   for (unsigned i1 = 0; i1 < threads.size(); ++i1)
01175   {
01176 #ifdef ULXR_MULTITHREADED
01177     threads[i1]->requestTermination();
01178 #endif
01179   }
01180 }
01181 
01182 
01183 ULXR_API_IMPL(void) HttpServer::shutdownAllThreads(unsigned /*time*/)
01184 {
01185   ULXR_TRACE(ULXR_PCHAR("Request to shutdown all threads."));
01186   requestTermination();
01187   for (unsigned i1 = 0; i1 < threads.size(); ++i1)
01188   {
01189 #ifdef ULXR_MULTITHREADED
01190     threads[i1]->requestTermination();
01191     try
01192     {
01193 #ifdef __WIN32__
01194       threads[i1]->getProtocol()->shutdown(SD_BOTH);
01195 #else
01196       threads[i1]->getProtocol()->shutdown(SHUT_RDWR);
01197 #endif
01198     }
01199     catch(...)  // ignore expected errors
01200     {
01201     }
01202 #endif
01203   }
01204 }
01205 
01206 
01207 ULXR_API_IMPL(void) HttpServer::waitAsync(bool term, bool stat)
01208 {
01209    ULXR_TRACE(ULXR_PCHAR("waitAsync"));
01210 
01211    if (threads.size() == 0)
01212      return;
01213 
01214    if (term)
01215      terminateAllThreads(1000);
01216 
01217    ULXR_TRACE(ULXR_PCHAR("waitAsync: join"));
01218    for (unsigned i = 0; i < threads.size(); ++i)
01219    {
01220      ULXR_TRACE(ULXR_PCHAR(" join " << i));
01221 #ifdef __unix__
01222      void *status;
01223      pthread_join(threads[i]->getHandle(), &status);
01224 #elif defined(__WIN32__)
01225      WaitForSingleObject(threads[i]->getHandle(), INFINITE);
01226      CloseHandle(threads[i]->getHandle());
01227 #else
01228 #error unsupported platform here
01229 #endif
01230      ULXR_TRACE(ULXR_PCHAR("waitAsync: joined ") << i);
01231      // maybe check (*status != 0) here
01232    }
01233 
01234    if (stat)
01235      printStatistics();
01236 
01237    releaseThreads();
01238    ULXR_TRACE(ULXR_PCHAR("/waitAsync"));
01239 }
01240 
01241 
01242 ULXR_API_IMPL(void) HttpServer::releaseThreads()
01243 {
01244    ULXR_TRACE(ULXR_PCHAR("releaseThreads()"));
01245    for (unsigned i = 0; i < threads.size(); ++i)
01246    {
01247      delete threads[i]->getProtocol();
01248      delete threads[i];
01249    }
01250 
01251    threads.clear();
01252 }
01253 
01254 
01255 ULXR_API_IMPL(void) HttpServer::printStatistics() const
01256 {
01257    for (unsigned i = 0; i < threads.size(); ++i)
01258      ULXR_COUT << ULXR_PCHAR("Thread ")
01259                << std::dec << i
01260                << ULXR_PCHAR(" invoked ")
01261                << threads[i]->numInvoked()
01262                << ULXR_PCHAR(" times.\n");
01263 }
01264 
01265 
01266 #endif // ULXR_MULTITHREADED
01267 
01268 
01270 
01271 
01272 #ifdef ULXR_MULTITHREADED
01273 
01274 HttpServer::ThreadData::ThreadData (HttpServer *serv, HttpProtocol *prot)
01275 {
01276   run = true;
01277   handle = 0;
01278   ctrInvoked = 0;
01279   protocol = prot;
01280   server = serv;
01281 }
01282 
01283 
01284 bool HttpServer::ThreadData::shouldRun() const
01285 {
01286   return run;
01287 }
01288 
01289 
01290 void HttpServer::ThreadData::requestTermination()
01291 {
01292   ULXR_TRACE(ULXR_PCHAR("Request to terminate a single thread."));
01293   run = false;
01294 }
01295 
01296 
01297 HttpServer::ThreadData::handle_t
01298   HttpServer::ThreadData::getHandle() const
01299 {
01300   ULXR_TRACE(ULXR_PCHAR("HttpServer::ThreadData::getHandle ") << handle);
01301   return handle;
01302 }
01303 
01304 
01305 void HttpServer::ThreadData::setHandle(handle_t hd)
01306 {
01307   ULXR_TRACE(ULXR_PCHAR("HttpServer::ThreadData::setHandle ") << hd);
01308   handle = hd;
01309 }
01310 
01311 
01312 HttpProtocol *HttpServer::ThreadData::getProtocol() const
01313 {
01314   return protocol;
01315 }
01316 
01317 
01318 HttpServer *HttpServer::ThreadData::getServer() const
01319 {
01320   return server;
01321 }
01322 
01323 
01324 void HttpServer::ThreadData::incInvoked()
01325 {
01326   ctrInvoked++;
01327 }
01328 
01329 
01330 unsigned HttpServer::ThreadData::numInvoked() const
01331 {
01332   return ctrInvoked;
01333 }
01334 
01335 #endif // ULXR_MULTITHREADED
01336 
01337 
01339 //
01340 
01341 
01342 ULXR_API_IMPL0 MethodHandler::MethodHandler(hidden::StaticMethodHandler handler)
01343  : static_handler(handler),
01344    dynamic_handler(0)
01345 {
01346 }
01347 
01348 
01349 ULXR_API_IMPL0 MethodHandler::MethodHandler(hidden::DynamicMethodHandler handler)
01350  : static_handler(0),
01351    dynamic_handler(handler)
01352 {
01353 }
01354 
01355 
01356 ULXR_API_IMPL0 MethodHandler::~MethodHandler()
01357 {
01358   delete dynamic_handler;
01359 }
01360 
01361 
01362 ULXR_API_IMPL(bool) MethodHandler::handle(HttpProtocol *conn,
01363                                        const CppString &method,
01364                                        const CppString &resource,
01365                                        const Cpp8BitString &conn_data)
01366 {
01367   ULXR_TRACE(ULXR_PCHAR("MethodHandler::handle"));
01368 
01369   if (0 != dynamic_handler)
01370   {
01371     return dynamic_handler->handle(conn, method, resource, conn_data);
01372   }
01373 
01374   else if (0 != static_handler)
01375   {
01376     return static_handler(conn, method, resource, conn_data);
01377   }
01378 
01379   return false;
01380 }
01381 
01382 
01383 }  // namespace ulxr
01384 
01385 
01386 #endif // ULXR_OMIT_TCP_STUFF
01387 

Generated on Sun Aug 19 20:08:57 2007 for ulxmlrpcpp by  doxygen 1.5.1