summaryrefslogtreecommitdiffstats
path: root/libcsoap/soap-nhttp.c
diff options
context:
space:
mode:
Diffstat (limited to 'libcsoap/soap-nhttp.c')
-rw-r--r--libcsoap/soap-nhttp.c470
1 files changed, 470 insertions, 0 deletions
diff --git a/libcsoap/soap-nhttp.c b/libcsoap/soap-nhttp.c
new file mode 100644
index 0000000..a49800b
--- /dev/null
+++ b/libcsoap/soap-nhttp.c
@@ -0,0 +1,470 @@
+/******************************************************************
+* $Id: soap-nhttp.c,v 1.1 2006/11/21 20:59:02 m0gg 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
+******************************************************************/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#ifdef WIN32
+#define snprintf(buffer, num, s1, s2) sprintf(buffer, s1,s2)
+#endif
+
+#include <libxml/tree.h>
+#include <libxml/uri.h>
+
+#include <nanohttp/nanohttp-common.h>
+#include <nanohttp/nanohttp-logging.h>
+
+#include <nanohttp/nanohttp-socket.h>
+#include <nanohttp/nanohttp-stream.h>
+#include <nanohttp/nanohttp-request.h>
+#include <nanohttp/nanohttp-response.h>
+
+#include <nanohttp/nanohttp-client.h>
+#include <nanohttp/nanohttp-server.h>
+
+#include "soap-admin.h"
+#include "soap-fault.h"
+#include "soap-env.h"
+#include "soap-ctx.h"
+#include "soap-service.h"
+#include "soap-router.h"
+#include "soap-server.h"
+#include "soap-client.h"
+#include "soap-addressing.h"
+
+#include "soap-nhttp.h"
+
+static herror_t
+_soap_nhttp_send_document(httpd_conn_t *conn, xmlDocPtr doc)
+{
+ char length[16];
+ xmlBufferPtr buf;
+
+ buf = xmlBufferCreate();
+ xmlNodeDump(buf, doc, xmlDocGetRootElement(doc), 1, 1);
+
+ sprintf(length, "%d", xmlBufferLength(buf));
+ httpd_set_header(conn, HEADER_CONTENT_TYPE, "text/xml");
+ httpd_set_header(conn, HEADER_CONTENT_LENGTH, length);
+ httpd_send_header(conn, 200, "OK");
+
+ http_output_stream_write_string(conn->out, xmlBufferContent(buf));
+
+ xmlBufferFree(buf);
+
+ return H_OK;
+}
+
+static herror_t
+_soap_nhttp_send_fault(httpd_conn_t *conn, const char *message)
+{
+ xmlDocPtr doc;
+ herror_t ret;
+
+ doc = soap_fault_build(SOAP_FAULT_SENDER, message, soap_server_get_name(), NULL);
+ ret = _soap_nhttp_send_document(conn, doc);
+ xmlFreeDoc(doc);
+
+ return ret;
+}
+
+static herror_t
+_soap_nhttp_send(httpd_conn_t *conn, SoapCtx *context, SoapEnv *env)
+{
+ return _soap_nhttp_send_document(conn, env->root->doc);
+}
+
+static int
+_soap_nhttp_xml_io_read(void *ctx, char *buffer, int len)
+{
+ int ret;
+
+ http_input_stream_t *in = (http_input_stream_t *)ctx;
+ if (!http_input_stream_is_ready(in))
+ return 0;
+
+ if ((ret = http_input_stream_read(in, buffer, len)) == -1)
+ return 0;
+
+ return ret;
+}
+
+static int
+_soap_nhttp_xml_io_close(void *ctx)
+{
+ /* nothing */
+ return 0;
+}
+
+static herror_t
+_soap_nhttp_env_new_from_stream(http_input_stream_t *in, SoapEnv **out)
+{
+ xmlDocPtr doc;
+
+ doc = xmlReadIO(_soap_nhttp_xml_io_read, _soap_nhttp_xml_io_close, in, "", NULL, 0);
+ if (in->err != H_OK)
+ return in->err;
+
+ if (doc == NULL)
+ return herror_new("_soap_nhttp_env_new_from_stream", XML_ERROR_PARSE, "Trying to parse not valid xml");
+
+ return soap_env_new_from_doc(doc, out);
+}
+
+static void
+soap_nhttp_process(httpd_conn_t * conn, hrequest_t * req)
+{
+ char *action;
+ SoapEnv *env;
+ SoapCtx *ctx;
+ SoapCtx *response;
+ herror_t err;
+
+/* if (req->method == HTTP_REQUEST_GET && router->wsdl)
+ {
+ _soap_nhttp_send_document(conn, router->wsdl);
+ return;
+ } */
+
+ if (req->method != HTTP_REQUEST_POST)
+ {
+ httpd_send_header(conn, 200, "OK");
+ http_output_stream_write_string(conn->out,
+ "<html>"
+ "<head>"
+ "</head>"
+ "<body>"
+ "<h1>Sorry!</h1>"
+ "<hr />"
+ "<div>I only speak with 'POST' method.</div>"
+ "</body>"
+ "</html>");
+ return;
+ }
+
+ if ((err = _soap_nhttp_env_new_from_stream(req->in, &env)) != H_OK)
+ {
+ _soap_nhttp_send_fault(conn, herror_message(err));
+ herror_release(err);
+ return;
+ }
+
+ if (env == NULL)
+ {
+ _soap_nhttp_send_fault(conn, "Can not receive POST data!");
+ return;
+ }
+
+ ctx = soap_ctx_new(env);
+
+ if ((action = hpairnode_get_ignore_case(req->header, SOAP_NHTTP_SOAP_ACTION)))
+ {
+ xmlURI *uri;
+
+ uri = xmlParseURI(action);
+ soap_addressing_set_action(env, uri);
+ xmlFree(uri);
+ }
+
+ soap_xml_doc_print(ctx->env->root->doc);
+
+ soap_ctx_add_files(ctx, req->attachments);
+
+ /* only local part is interesting... */
+ soap_addressing_set_to_address_string(ctx->env, req->path);
+
+ soap_server_process(ctx, &response);
+
+ _soap_nhttp_send_document(conn, response->env->root->doc);
+
+ soap_ctx_free(response);
+
+ soap_ctx_free(ctx);
+
+ return;
+}
+
+herror_t
+soap_nhttp_server_init_args(int argc, char **argv)
+{
+ herror_t err;
+
+ if ((err = httpd_init(argc, argv)) != H_OK)
+ return err;
+
+ return soap_admin_init_args(argc, argv);
+}
+
+static herror_t
+_soap_nhttp_client_build_result(hresponse_t * res, SoapEnv ** env)
+{
+ log_verbose2("Building result (%p)", res);
+
+ if (res == NULL)
+ return herror_new("_soap_client_build_result",
+ GENERAL_INVALID_PARAM, "hresponse_t is NULL");
+
+ if (res->in == NULL)
+ return herror_new("_soap_client_build_result",
+ GENERAL_INVALID_PARAM, "Empty response from server");
+
+ if (res->errcode != 200)
+ return herror_new("_soap_client_build_result",
+ GENERAL_INVALID_PARAM, "HTTP code is not OK (%i)", res->errcode);
+
+ return _soap_nhttp_env_new_from_stream(res->in, env);
+}
+
+static herror_t
+_soap_nhttp_client_invoke(void *unused, SoapCtx *request, SoapCtx **response)
+{
+ herror_t status;
+
+ /* Buffer variables */
+ xmlBufferPtr buffer;
+ char *content;
+ char tmp[15];
+ char *action;
+ char *url;
+ SoapEnv *res_env;
+
+ /* Transport variables */
+ httpc_conn_t *conn;
+ hresponse_t *res;
+
+ /* multipart/related start id */
+ char start_id[150];
+ static int counter = 1;
+ part_t *part;
+
+ /* for copy attachments */
+ char href[MAX_HREF_SIZE];
+
+ log_verbose1("nanohttp client");
+
+ /* Create buffer */
+ buffer = xmlBufferCreate();
+ xmlNodeDump(buffer, request->env->root->doc, request->env->root, 1, 0);
+ content = (char *) xmlBufferContent(buffer);
+
+ soap_xml_doc_print(request->env->root->doc);
+
+ /* Transport via HTTP */
+ if (!(conn = httpc_new()))
+ {
+ return herror_new("soap_client_invoke", SOAP_ERROR_CLIENT_INIT, "Unable to create HTTP client!");
+ }
+
+ if ((action = soap_addressing_get_action_string(request->env)))
+ httpc_set_header(conn, SOAP_NHTTP_SOAP_ACTION, action);
+ else
+ httpc_set_header(conn, SOAP_NHTTP_SOAP_ACTION, "");
+ log_verbose2("action is \"%s\"", action);
+ free(action);
+
+ httpc_set_header(conn, HEADER_CONNECTION, "Close");
+
+ if (!(url = soap_addressing_get_to_address_string(request->env)))
+ return herror_new("soap_nhttp_client_invoke", 0, "Missing client URL");
+ log_verbose2("url is \"%s\"", url);
+
+ if (!request->attachments)
+ {
+ /* content-type is always 'text/xml' */
+ httpc_set_header(conn, HEADER_CONTENT_TYPE, "text/xml");
+
+ sprintf(tmp, "%d", (int) strlen(content));
+ httpc_set_header(conn, HEADER_CONTENT_LENGTH, tmp);
+
+ if ((status = httpc_post_begin(conn, url)) != H_OK)
+ {
+ httpc_close_free(conn);
+ xmlBufferFree(buffer);
+ return status;
+ }
+
+ if ((status = http_output_stream_write_string(conn->out, content)) != H_OK)
+ {
+ httpc_close_free(conn);
+ xmlBufferFree(buffer);
+ return status;
+ }
+
+ if ((status = httpc_post_end(conn, &res)) != H_OK)
+ {
+ httpc_close_free(conn);
+ xmlBufferFree(buffer);
+ return status;
+ }
+ }
+ else
+ {
+ httpc_set_header(conn, HEADER_TRANSFER_ENCODING, TRANSFER_ENCODING_CHUNKED);
+
+ sprintf(start_id, "289247829121218%d", counter++);
+ if ((status = httpc_mime_begin(conn, url, start_id, "", "text/xml")) != H_OK)
+ {
+ httpc_close_free(conn);
+ xmlBufferFree(buffer);
+ return status;
+ }
+
+ if ((status = httpc_mime_next(conn, start_id, "text/xml", "binary")) != H_OK)
+ {
+ httpc_close_free(conn);
+ xmlBufferFree(buffer);
+ return status;
+ }
+
+ if ((status = http_output_stream_write(conn->out, content, strlen(content))) != H_OK)
+ {
+ httpc_close_free(conn);
+ xmlBufferFree(buffer);
+ return status;
+ }
+
+ for (part=request->attachments->parts; part; part=part->next)
+ {
+ status = httpc_mime_send_file(conn, part->id, part->content_type, part->transfer_encoding, part->filename);
+
+ if (status != H_OK)
+ {
+ log_error2("Send file failed. Status: %d", status);
+ httpc_close_free(conn);
+ xmlBufferFree(buffer);
+ return status;
+ }
+ }
+
+ if ((status = httpc_mime_end(conn, &res)) != H_OK)
+ {
+ httpc_close_free(conn);
+ xmlBufferFree(buffer);
+ return status;
+ }
+ }
+
+ xmlBufferFree(buffer);
+ free(url);
+
+ if ((status = _soap_nhttp_client_build_result(res, &res_env)) != H_OK)
+ {
+ hresponse_free(res);
+ httpc_close_free(conn);
+ return status;
+ }
+
+ *response = soap_ctx_new(res_env);
+ /* soap_ctx_add_files(*response, res->attachments) */
+
+ if (res->attachments != NULL)
+ {
+ part = res->attachments->parts;
+ while (part)
+ {
+ soap_ctx_add_file(*response, part->filename, part->content_type, href);
+ part->deleteOnExit = 0;
+ part = part->next;
+ }
+ }
+
+ hresponse_free(res);
+ httpc_close_free(conn);
+
+ log_verbose1("done");
+
+ return H_OK;
+}
+herror_t
+soap_nhttp_client_init_args(int argc, char **argv)
+{
+ soap_transport_add("https", NULL, _soap_nhttp_client_invoke);
+ soap_transport_add("http", NULL, _soap_nhttp_client_invoke);
+
+ return httpc_init(argc, argv);
+}
+
+herror_t
+soap_nhttp_register_router(SoapRouter * router, const char *context)
+{
+
+ if (!httpd_register_secure(context, soap_nhttp_process, router->auth))
+ {
+ return /* XXX */ H_OK;
+ }
+
+ return H_OK;
+}
+
+herror_t
+soap_nhttp_server_run(void)
+{
+ return httpd_run();
+}
+
+void
+soap_nhttp_server_destroy(void)
+{
+ httpd_destroy();
+
+ return;
+}
+
+
+void
+soap_nhttp_client_destroy(void)
+{
+ httpc_destroy();
+
+ return;
+}
+
+short
+soap_nhttp_get_port(void)
+{
+ return httpd_get_port();
+}
+
+const char *
+soap_nhttp_get_protocol(void)
+{
+ return httpd_get_protocol();
+}
+