00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027
00028 #ifdef HAVE_SYS_TYPES_H
00029 #include <sys/types.h>
00030 #endif
00031
00032 #ifdef HAVE_SYS_SOCKET_H
00033 #include <sys/socket.h>
00034 #endif
00035
00036 #ifdef HAVE_STDLIB_H
00037 #include <stdlib.h>
00038 #endif
00039
00040 #ifdef HAVE_STDIO_H
00041 #include <stdio.h>
00042 #endif
00043
00044 #ifdef HAVE_STRING_H
00045 #include <string.h>
00046 #endif
00047
00048 #ifdef HAVE_ERRNO_H
00049 #include <errno.h>
00050 #endif
00051
00052 #ifdef HAVE_UNISTD_H
00053 #include <unistd.h>
00054 #endif
00055
00056 #ifdef HAVE_PTHREAD_H
00057 #include <pthread.h>
00058 #endif
00059
00060 #ifdef HAVE_NETDB_H
00061 #include <netdb.h>
00062 #endif
00063
00064 #ifdef HAVE_NETINET_IN_H
00065 #include <netinet/in.h>
00066 #endif
00067
00068 #ifdef HAVE_ARPA_INET_H
00069 #include <arpa/inet.h>
00070 #endif
00071
00072 #include <libxml/tree.h>
00073 #include <libxml/uri.h>
00074
00075 #include <nanohttp/nanohttp-error.h>
00076 #include <nanohttp/nanohttp-logging.h>
00077
00078 #include "soap-fault.h"
00079 #include "soap-env.h"
00080 #include "soap-ctx.h"
00081 #include "soap-service.h"
00082 #include "soap-router.h"
00083 #include "soap-server.h"
00084 #include "soap-transport.h"
00085 #include "soap-addressing.h"
00086 #include "soap-nudp.h"
00087
00088 static short _soap_nudp_port = NUDP_DEFAULT_PORT;
00089 static int _soap_nudp_socket;
00090 static pthread_t _soap_nudp_thread;
00091 static pthread_attr_t _soap_nudp_attr;
00092 static volatile int _soap_nudp_running = 0;
00093
00094 static short
00095 _soap_nudp_server_set_port(void)
00096 {
00097 struct servent *entry;
00098
00099 if (!(entry = getservbyname("soap", "udp")))
00100 {
00101 log_warn1("getservbyname(\"soap\", \"udp\") returned NULL, please edit services database");
00102 _soap_nudp_port = NUDP_DEFAULT_PORT;
00103 }
00104 else
00105 {
00106 _soap_nudp_port = ntohs(entry->s_port);
00107 }
00108 return _soap_nudp_port;
00109 }
00110
00111 static void
00112 _soap_nudp_server_parse_arguments(int argc, char **argv)
00113 {
00114 int i;
00115
00116 for (i=1; i<argc; i++)
00117 {
00118 if (!strcmp(argv[i - 1], NUDP_ARG_PORT))
00119 {
00120 _soap_nudp_port = atoi(argv[i]);
00121 }
00122 }
00123
00124 log_verbose2("socket bind to port \"%d\"", _soap_nudp_port);
00125
00126 return;
00127 }
00128
00129 static herror_t
00130 _soap_nudp_send_document(int socket, xmlDocPtr doc, const struct sockaddr *addr, socklen_t addr_len)
00131 {
00132 xmlChar *buf;
00133 herror_t ret;
00134 int size;
00135 size_t sent;
00136
00137 ret = H_OK;
00138
00139 xmlDocDumpMemory(doc, &buf, &size);
00140 if ((sent = sendto(socket, buf, size, 0, addr, addr_len)) == -1)
00141 {
00142 log_error2("sendto failed (%s)", strerror(errno));
00143 ret = herror_new("soap_nudp_client_invoke", 0, "Cannot send message");
00144 }
00145
00146 xmlFree(buf);
00147
00148 return ret;
00149 }
00150
00151 static herror_t
00152 _soap_nudp_receive_document(int socket, xmlDocPtr *doc, struct sockaddr *addr, socklen_t *addr_len)
00153 {
00154 int cnt;
00155 char buf[4096];
00156
00158 if ((cnt = recvfrom(socket, buf, 4095, 0, addr, addr_len)) < 0)
00159 {
00160 log_error2("recvfrom failed (%s)", strerror(errno));
00161 return herror_new("_soap_nudp_receive_document", 0, "Receiving document failed");
00162 }
00163 buf[cnt] = '\0';
00164
00165 if (!(*doc = xmlReadDoc(buf, NULL, NULL, XML_PARSE_NONET)))
00166 {
00167 log_error1("xmlReadDoc failed");
00168 return herror_new("_soap_nudp_receive_document", 0, "Cannot parse received data");
00169 }
00170
00171 return H_OK;
00172 }
00173
00174 static herror_t
00175 _soap_nudp_client_invoke(void *unused, struct SoapCtx *request, struct SoapCtx **response)
00176 {
00177 xmlURI *to;
00178 xmlDocPtr doc;
00179 int sd;
00180 herror_t status;
00181 struct sockaddr_in addr;
00182 struct sockaddr saddr;
00183 socklen_t saddr_len;
00184
00185 if (!(to = soap_addressing_get_to_address(request->env)))
00186 {
00187 log_error1("soap_addressing_get_to_address returned NULL");
00188 return herror_new("soap_nudp_client_invoke", 0, "Destination address is missing");
00189 }
00190
00191 bzero(&addr, sizeof(struct sockaddr_in));
00192 addr.sin_family = AF_INET;
00193 if (to->port == 0)
00194 addr.sin_port = htons(NUDP_DEFAULT_PORT);
00195 else
00196 addr.sin_port = htons(to->port);
00197
00198 if (inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr) != 1)
00199 {
00200 log_error2("inet_pton failed (%s)", strerror(errno));
00201 return herror_new("soap_nudp_client_invoke", 0, "Cannot resolve destination address");
00202 }
00203
00204 if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
00205 {
00206 log_error2("socket failed (%s)", strerror(errno));
00207 return herror_new("soap_nudp_client_invoke", 0, "Cannot create socket");
00208 }
00209
00210 _soap_nudp_send_document(sd, request->env->root->doc, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
00211
00212 saddr_len = sizeof(struct sockaddr);
00213 if ((status = _soap_nudp_receive_document(sd, &doc, &saddr, &saddr_len)) != H_OK)
00214 {
00215 log_error2("_soap_nudp_receive_document failed (%s)", herror_message(status));
00216 return status;
00217 }
00218
00219 *response = soap_ctx_new(NULL);
00220 if ((status = soap_env_new_from_doc(doc, &(*response)->env)) != H_OK)
00221 {
00222 log_error2("soap_env_new_from_doc failed (%s)", herror_message(status));
00223 return status;
00224 }
00225
00228 return H_OK;
00229 }
00230
00231 herror_t
00232 soap_nudp_server_init_args(int argc, char **argv)
00233 {
00234 struct sockaddr_in addr;
00235
00236 _soap_nudp_server_set_port();
00237
00238 _soap_nudp_server_parse_arguments(argc, argv);
00239
00240 if ((_soap_nudp_socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
00241 {
00242 log_error2("socket failed (%s)", strerror(errno));
00243 return herror_new("soap_nudp_server_init_args", 0, "Cannot create socket (%s)", strerror(errno));
00244 }
00245
00246 memset(&addr, 0, sizeof(struct sockaddr_in));
00247 addr.sin_family = AF_INET;
00248 addr.sin_addr.s_addr = htonl(INADDR_ANY);
00249 addr.sin_port = htons(_soap_nudp_port);
00250
00251 if (bind(_soap_nudp_socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0)
00252 {
00253 log_error2("bind failed (%s)", strerror(errno));
00254 return herror_new("soap_nudp_server_init_args", 0, "Cannot bind socket (%s)", strerror(errno));
00255 }
00256
00257 return H_OK;
00258 }
00259
00260 herror_t
00261 soap_nudp_register(const void *data)
00262 {
00263 return H_OK;
00264 }
00265
00266 void *
00267 soap_nudp_server_run(void *unused)
00268 {
00269 xmlDocPtr doc;
00270 struct sockaddr addr;
00271 socklen_t addr_len;
00272 struct SoapCtx *req;
00273 struct SoapCtx *res;
00274 xmlURI *to;
00275 herror_t status;
00276
00277 while (_soap_nudp_running)
00278 {
00279
00280
00281 addr_len = sizeof(struct sockaddr);
00282 if (_soap_nudp_receive_document(_soap_nudp_socket, &doc, &addr, &addr_len) != H_OK)
00283 {
00284 log_error2("_soap_nudp_receive_document failed (%s)", herror_message(status));
00285 herror_release(status);
00286 continue;
00287 }
00288
00289
00290
00291
00292 req = soap_ctx_new(NULL);
00293
00294 soap_env_new_from_doc(doc, &(req->env));
00295
00296
00297 to = soap_addressing_get_to_address(req->env);
00298 soap_addressing_set_to_address_string(req->env, to->path);
00299
00300
00301
00302 soap_transport_process(req, &res);
00303
00304 xmlDocFormatDump(stderr, res->env->root->doc, 1);
00305
00306 _soap_nudp_send_document(_soap_nudp_socket, res->env->root->doc, &addr, addr_len);
00307
00308 soap_ctx_free(res);
00309
00310 soap_ctx_free(req);
00311 }
00312
00313 close(_soap_nudp_socket);
00314
00315 return NULL;
00316 }
00317
00318 herror_t
00319 soap_nudp_server_run_threaded(void)
00320 {
00321 int err;
00322
00323 _soap_nudp_running = 1;
00324
00325 if ((err = pthread_create(&_soap_nudp_thread, &_soap_nudp_attr, soap_nudp_server_run, NULL)) < 0)
00326 {
00327 log_error2("pthread_create failed (%s)", strerror(err));
00328 return herror_new("soap_nudp_server_run_threaded", 0, "pthread_create failed (%s)", strerror(err));
00329 }
00330
00331 return H_OK;
00332 }
00333
00334 void
00335 soap_nudp_server_destroy(void)
00336 {
00337 _soap_nudp_running = 0;
00338
00339
00340
00341 return;
00342 }
00343
00344 herror_t
00345 soap_nudp_client_init_args(int argc, char **argv)
00346 {
00347 soap_transport_add("soap.udp", NULL, _soap_nudp_client_invoke);
00348
00349 return H_OK;
00350 }
00351
00352 void
00353 soap_nudp_client_destroy(void)
00354 {
00355 return;
00356 }