blob: 54542f9dd65c71ac84f943aa2750f59c46be1b2a [file] [log] [blame]
/* handler.c
Multi-threaded stand-alone event handler service
Events are based on asynchronous one-way SOAP messaging using HTTP
keep-alive for persistent connections
The 'synchronous' global flag illustrates SOAP one-way messaging,
which requires an HTTP OK response with an empty body to be returned
by the server.
Copyright (C) 2000-2002 Robert A. van Engelen. All Rights Reserved.
Compile:
soapcpp2 -c event.h
cc -o handler handler.c stdsoap2.c soapC.c soapService.c
Run:
handler 18000 &
Server will time out after 24hr of inactivity
This code enables keep-alive support which can cause "broken pipes"
when the client prematurely closes the connection while indicating
it wants the connection to stay alive. Broken pipes (SIGPIPE) can be
fixed using MSG_NOSIGNAL, SO_NOSIGPIPE, or with a signal handler,
but this is not very portable (see code below)
*/
#include "soapH.h"
#include "Event.nsmap"
#include <pthread.h>
#define BACKLOG (100)
#define TIMEOUT (24*60*60) /* timeout after 24hrs of inactivity */
void *process_request(void*);
int synchronous = 0; /* =1: SOAP interoperable synchronous one-way messaging over HTTP */
int main(int argc, char **argv)
{ struct soap soap, *tsoap;
pthread_t tid;
int port;
int m, s, i;
if (argc < 2)
{ fprintf(stderr, "Usage: handler <port>\n");
exit(1);
}
port = atoi(argv[1]);
soap_init2(&soap, SOAP_IO_KEEPALIVE, SOAP_IO_KEEPALIVE); /* keep I/O alive */
soap.accept_timeout = TIMEOUT;
soap.bind_flags |= SO_REUSEADDR; /* don't use this in unsecured environments */
/* soap.socket_flags = MSG_NOSIGNAL; */ /* use this to disable SIGPIPE */
/* soap.bind_flags |= SO_NOSIGPIPE; */ /* or use this to disable SIGPIPE */
m = soap_bind(&soap, NULL, port, BACKLOG);
if (m < 0)
{ soap_print_fault(&soap, stderr);
exit(1);
}
fprintf(stderr, "Socket connection successful %d\n", m);
for (i = 1; ; i++)
{ s = soap_accept(&soap);
if (s < 0)
{ if (soap.errnum)
soap_print_fault(&soap, stderr);
else
fprintf(stderr, "%s timed out\n", argv[0]); /* should really wait for threads to terminate, but 24hr timeout should be enough ... */
break;
}
fprintf(stderr, "Thread %d accepts socket %d connection from IP %d.%d.%d.%d\n", i, s, (int)(soap.ip>>24)&0xFF, (int)(soap.ip>>16)&0xFF, (int)(soap.ip>>8)&0xFF, (int)soap.ip&0xFF);
tsoap = soap_copy(&soap);
pthread_create(&tid, NULL, (void*(*)(void*))process_request, (void*)tsoap);
}
return 0;
}
void *process_request(void *soap)
{ struct soap *tsoap = (struct soap*)soap;
pthread_detach(pthread_self());
soap_serve(tsoap);
soap_destroy(tsoap);
soap_end(tsoap);
soap_done(tsoap);
free(tsoap);
return NULL;
}
int ns__handle(struct soap *soap, enum ns__event event)
{ switch (event)
{ /* each event is just consumed without server response */
case EVENT_A: fprintf(stderr, "Server Event: A\n"); break;
case EVENT_B: fprintf(stderr, "Server Event: B\n"); break;
case EVENT_C: fprintf(stderr, "Server Event: C\n"); break;
/* after receiving event Z, we echo events A to C back to the client */
case EVENT_Z: fprintf(stderr, "Server Event: Z\n");
{ struct soap *resp = soap_copy(soap);
/* these multiple sends assume that the client enabled keep-alive */
soap_send_ns__handle(resp, "http://", NULL, EVENT_A);
soap_send_ns__handle(resp, "http://", NULL, EVENT_B);
soap_send_ns__handle(resp, "http://", NULL, EVENT_C);
soap_end(resp);
soap_done(resp);
free(resp);
}
}
if (event != EVENT_Z && synchronous)
return soap_send_empty_response(soap);
return SOAP_OK;
}