/****************************************************************** * $Id: soap-server.c,v 1.4 2004/08/30 13:22:04 snowdrop Exp $ * * CSOAP Project: A SOAP client/server library in C * Copyright (C) 2003 Ferhat Ayaz * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * Email: ayaz@jprogrammer.net ******************************************************************/ #include #include #include typedef struct _SoapRouterNode { char *context; SoapRouter *router; struct _SoapRouterNode *next; }SoapRouterNode; SoapRouterNode *head = NULL; SoapRouterNode *tail = NULL; static SoapRouterNode *router_node_new(SoapRouter *router, const char *context, SoapRouterNode *next); static SoapRouter *router_find(const char *context); /*---------------------------------*/ void soap_server_entry(httpd_conn_t *conn, hrequest_t *req); static void _soap_server_send_env(hsocket_t sock, SoapEnv* env); static void _soap_server_send_fault(httpd_conn_t *conn, hpair_t *header, const char* errmsg); /*---------------------------------*/ int soap_server_init_args(int argc, char *argv[]) { return !httpd_init(argc, argv); } int soap_server_register_router(SoapRouter *router, const char* context) { if (!httpd_register(context, soap_server_entry)) { return 0; } if (tail == NULL) { head = tail = router_node_new(router, context, NULL); } else { tail->next = router_node_new(router, context, NULL); tail = tail->next; } return 1; } int soap_server_run() { return httpd_run(); } void soap_server_destroy() { SoapRouterNode *node = head; SoapRouterNode *tmp; while (node != NULL) { tmp = node->next; log_verbose2("soap_router_free(%p)", node->router); soap_router_free(node->router); free(node->context); free(node); node = tmp; } } void soap_server_entry(httpd_conn_t *conn, hrequest_t *req) { hpair_t *header = NULL; char *postdata; char buffer[1054]; char urn[150]; char method[150]; long received; SoapEnv *env, *envres; SoapRouter *router; SoapService *service; if (strcmp(req->method, "POST")) { httpd_send_header(conn, 200, "OK", header); hsocket_send(conn->sock, ""); hsocket_send(conn->sock, "

Sorry!


"); hsocket_send(conn->sock, "I only speak with 'POST' method"); hsocket_send(conn->sock, ""); return; } postdata = httpd_get_postdata(conn, req, &received, -1); header = hpairnode_new(HEADER_CONTENT_TYPE, "text/xml", NULL); if (postdata == NULL) { _soap_server_send_fault(conn, header,"Can not receive POST data!"); } else { env = soap_env_new_from_buffer(postdata); if (env == NULL) { _soap_server_send_fault(conn, header,"Can not parse POST data!"); } else { /*soap_xml_doc_print(env->root->doc);*/ router = router_find(req->path); if ( router == NULL) { _soap_server_send_fault(conn, header, "Can not find router!"); } else { if (!soap_env_find_urn(env, urn)) { _soap_server_send_fault(conn, header, "No URN found!"); return; } else { log_verbose2("urn: '%s'", urn); } if (!soap_env_find_methodname(env, method)) { _soap_server_send_fault(conn, header, "No method found!"); return; }else { log_verbose2("method: '%s'", method); } service = soap_router_find_service(router, urn, method); if (service == NULL) { sprintf(buffer, "URN '%s' not found", urn); _soap_server_send_fault(conn, header, buffer); return; } else { log_verbose2("func: %p", service->func); envres = service->func(env); log_verbose2("func returned: (%p)", envres); if (envres == NULL) { sprintf(buffer, "Service '%s' returned no envelope", urn); _soap_server_send_fault(conn, header, buffer); return; } else { httpd_send_header(conn, 200, "OK", header); _soap_server_send_env(conn->sock, envres); /* free envres */ } } } } } } static void _soap_server_send_env(hsocket_t sock, SoapEnv* env) { xmlBufferPtr buffer; if (env == NULL || env->root == NULL) return; buffer = xmlBufferCreate(); xmlNodeDump(buffer, env->root->doc, env->root, 1 ,1); hsocket_send(sock, (const char*)xmlBufferContent(buffer)); xmlBufferFree(buffer); } static void _soap_server_send_fault(httpd_conn_t *conn, hpair_t *header, const char* errmsg) { SoapEnv *envres; httpd_send_header(conn, 500, "FAILED", header); envres = soap_env_new_with_fault(Fault_Server, errmsg?errmsg:"General error", "cSOAP_Server", NULL); _soap_server_send_env(conn->sock, envres); } static SoapRouterNode *router_node_new(SoapRouter *router, const char *context, SoapRouterNode *next) { SoapRouterNode *node; const char *noname = "/lost_find"; node = (SoapRouterNode*)malloc(sizeof(SoapRouterNode)); if (context) { node->context = (char*)malloc(strlen(context)+1); strcpy(node->context, context); } else { log_warn2("context is null. Using '%s'", noname); node->context = (char*)malloc(strlen(noname)+1); strcpy(node->context, noname); } node->router = router; node->next = next; return node; } static SoapRouter *router_find(const char* context) { SoapRouterNode *node = head; while (node != NULL) { if (!strcmp(node->context, context)) return node->router; node = node->next; } return NULL; }