soap-server.c

Go to the documentation of this file.
00001 /******************************************************************
00002 *  $Id: soap-server.c,v 1.36 2006/12/31 17:24:22 m0gg Exp $
00003 *
00004 * CSOAP Project:  A SOAP client/server library in C
00005 * Copyright (C) 2003  Ferhat Ayaz
00006 *
00007 * This library is free software; you can redistribute it and/or
00008 * modify it under the terms of the GNU Library General Public
00009 * License as published by the Free Software Foundation; either
00010 * version 2 of the License, or (at your option) any later version.
00011 *
00012 * This library is distributed in the hope that it will be useful,
00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015 * Library General Public License for more details.
00016 *
00017 * You should have received a copy of the GNU Library General Public
00018 * License along with this library; if not, write to the
00019 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00020 * Boston, MA  02111-1307, USA.
00021 * 
00022 * Email: ayaz@jprogrammer.net
00023 ******************************************************************/
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027 
00028 #ifdef HAVE_STDIO_H
00029 #include <stdio.h>
00030 #endif
00031 
00032 #ifdef HAVE_STRING_H
00033 #include <string.h>
00034 #endif
00035 
00036 #ifdef HAVE_ERRNO_H
00037 #include <errno.h>
00038 #endif
00039 
00040 #include <libxml/tree.h>
00041 #include <libxml/uri.h>
00042 
00043 #include <nanohttp/nanohttp-error.h>
00044 #include <nanohttp/nanohttp-logging.h>
00045 
00046 #include "soap-fault.h"
00047 #include "soap-env.h"
00048 #include "soap-ctx.h"
00049 #include "soap-service.h"
00050 #include "soap-router.h"
00051 #include "soap-addressing.h"
00052 #include "soap-transport.h"
00053 #ifdef HAVE_XMLSEC1
00054 #include "soap-xmlsec.h"
00055 #endif
00056 #include "soap-server.h"
00057 
00058 static SoapRouterNode *head = NULL;
00059 static SoapRouterNode *tail = NULL;
00060 
00061 static SoapRouterNode *
00062 router_node_new(struct SoapRouter * router, const char *context, SoapRouterNode * next)
00063 {
00064   const char *noname = "/lost_found";
00065   SoapRouterNode *node;
00066 
00067   if (!(node = (SoapRouterNode *) malloc(sizeof(SoapRouterNode))))
00068   {
00069     log_error2("malloc failed (%s)", strerror(errno));
00070     return NULL;
00071   }
00072 
00073   if (context)
00074   {
00075     node->context = strdup(context);
00076   }
00077   else
00078   {
00079     log_warn2("context is null, using '%s'", noname);
00080     node->context = strdup(noname);
00081   }
00082 
00083   node->router = router;
00084   node->next = next;
00085 
00086   return node;
00087 }
00088 
00089 static herror_t
00090 _soap_server_env_new_with_fault(const char *fault_string, const char *detail, struct SoapEnv **out)
00091 {
00092   return soap_env_new_with_fault(SOAP_FAULT_RECEIVER, fault_string, soap_server_get_name(), detail, out);
00093 }
00094 
00095 static void
00096 _soap_server_fillup_header(struct SoapEnv *envelope)
00097 {
00098   xmlURI *uri;
00099 
00100   log_verbose1(__FUNCTION__);
00101 
00102   if (!(uri = soap_addressing_get_message_id(envelope)))
00103     soap_addressing_set_message_id_string(envelope, NULL);
00104   else
00105     xmlFreeURI(uri);
00106 
00107   if (!(uri = soap_addressing_get_from_address(envelope)))
00108     soap_addressing_set_from_address_string(envelope, soap_server_get_name());
00109   else
00110     xmlFreeURI(uri);
00111 
00112   return;
00113 }
00114 
00115 struct SoapRouter *
00116 soap_server_find_router(const char *context)
00117 {
00118   SoapRouterNode *node;
00119 
00120   for (node = head; node; node = node->next)
00121   {
00122     if (!strcmp(node->context, context))
00123       return node->router;
00124   }
00125 
00126   return NULL;
00127 }
00128 
00129 /* XXX: rewrite this function */
00130 
00131 herror_t
00132 soap_server_process(struct SoapCtx *request, struct SoapCtx **response)
00133 {
00134   char buffer[1054];
00135   const char *urn;
00136   xmlURI *uri;
00137   const char *method;
00138   struct SoapRouter *router;
00139   SoapService *service;
00140   herror_t err;
00141 
00142   log_verbose1("**** processing ****");
00143   xmlDocDump(stdout, request->env->root->doc);
00144   log_verbose1("********************");
00145 
00146   *response = soap_ctx_new(NULL);
00147 
00148 #ifdef HAVE_XMLSEC1
00149   if ((err = soap_xmlsec_verify(request)) != H_OK)
00150   {
00151     log_error2("soap_xmlsec_verify failed (%s)", herror_message(err));
00152     sprintf(buffer, "Verification of message signature failed (%s)", herror_message(err));
00153 
00154     _soap_server_env_new_with_fault("Internal server error", buffer, &((*response)->env));
00155     return H_OK;
00156   }
00157 
00158   if ((err = soap_xmlsec_decrypt(request)) != H_OK)
00159   {
00160     log_error2("soap_xmlsec_decrypt failed (%s)", herror_message(err));
00161     sprintf(buffer, "Decryption of message body failed (%s)", herror_message(err));
00162     _soap_server_env_new_with_fault("Internal server error", buffer, &((*response)->env));
00163     return H_OK;
00164   }
00165 #endif 
00166 
00167   if ((method = soap_env_find_methodname(request->env)))
00168   {
00169     log_verbose2("method: \"%s\"", method);
00170     if ((urn = soap_env_find_urn(request->env)))
00171     {
00172       log_verbose2("urn: \"%s\"", urn);
00173       if ((uri = soap_addressing_get_to_address(request->env)))
00174       {
00175         log_verbose2("searching router for \"%s\"", uri->path);
00176         if ((router = soap_server_find_router(uri->path)))
00177         {
00178           log_verbose2("router: %p", router);
00179           if ((service = soap_router_find_service(router, urn, method)))
00180           {
00181             log_verbose3("service (%p) found, function (%p)", service, service->func);
00182             switch (service->status)
00183             {
00184               case CSOAP_SERVICE_UP:
00185  
00186                 if ((err = service->func(request, *response)) == H_OK)
00187                 {
00188                   if ((*response)->env == NULL)
00189                   {
00190                     sprintf(buffer, "Service for \"%s\" returned no envelope", urn);
00191                     _soap_server_env_new_with_fault("Internal service error", buffer, &((*response)->env));
00192                   }
00193                 }
00194                 else
00195                 {
00196                   sprintf(buffer, "Service returned following error message: \"%s\"", herror_message(err));
00197                   herror_release(err);
00198                   _soap_server_env_new_with_fault("Internal service error", buffer, &((*response)->env));
00199                 }
00200                 break;
00201               case CSOAP_SERVICE_DOWN:
00202               default:
00203                 sprintf(buffer, "Service for \"%s\" is down", urn);
00204                 _soap_server_env_new_with_fault("Internal service error", buffer, &((*response)->env));
00205                 break;
00206             }
00207           }
00208           else
00209           {
00210             sprintf(buffer, "no service for URN \"%s\" found", urn);
00211             _soap_server_env_new_with_fault(buffer, "The URN is not known by the server", &((*response)->env));
00212           }
00213         }
00214         else
00215         {
00216           sprintf(buffer, "no router for context \"%s\" found", uri->path);
00217           _soap_server_env_new_with_fault(buffer, "The method is unknown by the server", &((*response)->env));
00218         }
00219         xmlFreeURI(uri);
00220       }
00221       else
00222       {
00223         _soap_server_env_new_with_fault(buffer, "The destination address is missing", &((*response)->env));
00224       }
00225     }
00226     else
00227     {
00228       _soap_server_env_new_with_fault("No method found", "The method is missing in the SOAP envelope", &((*response)->env));
00229     }
00230   }
00231   else
00232   {
00233     _soap_server_env_new_with_fault("No URN found", "The URN is missing in the SOAP envelope", &((*response)->env));
00234   }
00235 
00236   _soap_server_fillup_header((*response)->env);
00237 
00238 #ifdef HAVE_XMLSEC1
00239   soap_xmlsec_encrypt(*response);
00240 
00241   soap_xmlsec_sign(*response);
00242 #endif
00243 
00244   return H_OK;
00245 }
00246 
00247 herror_t
00248 soap_server_init_args(int argc, char **argv)
00249 {
00250   herror_t status;
00251 
00252   if ((status = soap_transport_server_init_args(argc, argv)) != H_OK)
00253   {
00254     log_error2("soap_transport_server_init_args failed (%s)", herror_message(status));
00255     return status;
00256   }
00257 
00258 #ifdef HAVE_XMLSEC1
00259   if ((status = soap_xmlsec_server_init_args(argc, argv)) != H_OK)
00260   {
00261     log_error2("soap_xmlsec_server_init_args failed (%s)", herror_message(status));
00262     return status;
00263   }
00264 #endif
00265 
00266   return H_OK;
00267 }
00268 
00269 const char *
00270 soap_server_get_name(void)
00271 {
00272   return soap_transport_get_name();
00273 }
00274 
00275 herror_t
00276 soap_server_register_router(struct SoapRouter *router, const char *context)
00277 {
00278   herror_t status;
00279 
00280   if ((status = soap_transport_register(context)) != H_OK)
00281   {
00282     log_error2("soap_transport_register failed (%s)", herror_message(status));
00283     return status;
00284   }
00285 
00286   if (tail == NULL)
00287   {
00288     head = tail = router_node_new(router, context, NULL);
00289   }
00290   else
00291   {
00292     tail->next = router_node_new(router, context, NULL);
00293     tail = tail->next;
00294   }
00295 
00296   return H_OK;
00297 }
00298 
00299 SoapRouterNode *
00300 soap_server_get_routers(void)
00301 {
00302   return head;
00303 }
00304 
00305 herror_t
00306 soap_server_run(void)
00307 {
00308   herror_t status;
00309 
00310   if ((status = soap_transport_server_run()) != H_OK)
00311     return status;
00312 
00313   return H_OK;
00314 }
00315 
00316 void
00317 soap_server_destroy(void)
00318 {
00319   SoapRouterNode *node = head;
00320   SoapRouterNode *tmp;
00321 
00322   while (node != NULL)
00323   {
00324     tmp = node->next;
00325     log_verbose2("soap_router_free(%p)", node->router);
00326     soap_router_free(node->router);
00327     free(node->context);
00328     free(node);
00329     node = tmp;
00330   }
00331   
00332   soap_transport_server_destroy();
00333 
00334   return;
00335 }

Generated on Thu Jan 25 23:36:03 2007 for csoap by  doxygen 1.4.6