blob: 949e3f803ef995e4b456f2c8f5120633f44f6b6b [file] [log] [blame]
/* sslserver.c
Example stand-alone secure gSOAP Web service.
Copyright (C) 2000-2003 Robert A. van Engelen, Genivia inc.
All Rights Reserved.
*/
#include "soapH.h"
#include "ssl.nsmap"
#include <unistd.h> /* defines _POSIX_THREADS if pthreads are available */
#ifdef _POSIX_THREADS
# include <pthread.h>
#endif
#include <signal.h> /* defines SIGPIPE */
/******************************************************************************\
*
* Forward decls
*
\******************************************************************************/
void *process_request(void*);
int CRYPTO_thread_setup();
void CRYPTO_thread_cleanup();
void sigpipe_handle(int);
/******************************************************************************\
*
* Main
*
\******************************************************************************/
int main()
{ int m, s; /* master and slave sockets */
pthread_t tid;
struct soap soap, *tsoap;
/* Need SIGPIPE handler on Unix/Linux systems to catch broken pipes: */
signal(SIGPIPE, sigpipe_handle);
/* Init OpenSSL */
soap_ssl_init();
if (CRYPTO_thread_setup())
{ fprintf(stderr, "Cannot setup thread mutex\n");
exit(1);
}
soap_init(&soap);
if (soap_ssl_server_context(&soap,
SOAP_SSL_DEFAULT,
"server.pem", /* keyfile: see SSL docs on how to obtain this file */
"password", /* password to read the key file */
NULL, /* cacert file to store trusted certificates (to authenticate clients) */
NULL, /* capath */
"dh512.pem", /* DH file, if NULL use RSA */
NULL, /* if randfile!=NULL: use a file with random data to seed randomness */
"sslserver" /* server identification for SSL session cache (unique server name, e.g. use argv[0]) */
))
{ soap_print_fault(&soap, stderr);
exit(1);
}
soap.accept_timeout = 60; /* server times out after 10 minutes of inactivity */
soap.recv_timeout = 30; /* if read stalls, then timeout after 60 seconds */
m = soap_bind(&soap, NULL, 18081, 100);
if (m < 0)
{ soap_print_fault(&soap, stderr);
exit(1);
}
fprintf(stderr, "Bind successful: socket = %d\n", m);
for (;;)
{ s = soap_accept(&soap);
if (s < 0)
{ if (soap.errnum)
soap_print_fault(&soap, stderr);
else
fprintf(stderr, "Server timed out\n");
break;
}
fprintf(stderr, "Socket %d connection from IP %d.%d.%d.%d\n", s, (int)(soap.ip>>24)&0xFF, (int)(soap.ip>>16)&0xFF, (int)(soap.ip>>8)&0xFF, (int)soap.ip&0xFF);
tsoap = soap_copy(&soap);
if (!tsoap)
{ soap_closesock(&soap);
continue;
}
if (soap_ssl_accept(tsoap))
{ soap_print_fault(tsoap, stderr);
fprintf(stderr, "SSL request failed, continue with next call...\n");
soap_end(tsoap);
soap_done(tsoap);
free(tsoap);
continue;
}
pthread_create(&tid, NULL, &process_request, (void*)tsoap);
}
soap_end(&soap);
soap_done(&soap); /* MUST call after CRYPTO_thread_cleanup */
CRYPTO_thread_cleanup();
return 0;
}
void *process_request(void *soap)
{ pthread_detach(pthread_self());
soap_serve((struct soap*)soap);
soap_destroy((struct soap*)soap); /* for C++ */
soap_end((struct soap*)soap);
soap_done((struct soap*)soap);
free(soap);
return NULL;
}
/******************************************************************************\
*
* Service methods
*
\******************************************************************************/
int ns__add(struct soap *soap, double a, double b, double *result)
{ *result = a + b;
return SOAP_OK;
}
/******************************************************************************\
*
* OpenSSL
*
\******************************************************************************/
#ifdef WITH_OPENSSL
#if defined(WIN32)
# define MUTEX_TYPE HANDLE
# define MUTEX_SETUP(x) (x) = CreateMutex(NULL, FALSE, NULL)
# define MUTEX_CLEANUP(x) CloseHandle(x)
# define MUTEX_LOCK(x) WaitForSingleObject((x), INFINITE)
# define MUTEX_UNLOCK(x) ReleaseMutex(x)
# define THREAD_ID GetCurrentThreadId()
#elif defined(_POSIX_THREADS)
# define MUTEX_TYPE pthread_mutex_t
# define MUTEX_SETUP(x) pthread_mutex_init(&(x), NULL)
# define MUTEX_CLEANUP(x) pthread_mutex_destroy(&(x))
# define MUTEX_LOCK(x) pthread_mutex_lock(&(x))
# define MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x))
# define THREAD_ID pthread_self()
#else
# error "You must define mutex operations appropriate for your platform"
# error "See OpenSSL /threads/th-lock.c on how to implement mutex on your platform"
#endif
struct CRYPTO_dynlock_value
{ MUTEX_TYPE mutex;
};
static MUTEX_TYPE *mutex_buf;
static struct CRYPTO_dynlock_value *dyn_create_function(const char *file, int line)
{ struct CRYPTO_dynlock_value *value;
value = (struct CRYPTO_dynlock_value*)malloc(sizeof(struct CRYPTO_dynlock_value));
if (value)
MUTEX_SETUP(value->mutex);
return value;
}
static void dyn_lock_function(int mode, struct CRYPTO_dynlock_value *l, const char *file, int line)
{ if (mode & CRYPTO_LOCK)
MUTEX_LOCK(l->mutex);
else
MUTEX_UNLOCK(l->mutex);
}
static void dyn_destroy_function(struct CRYPTO_dynlock_value *l, const char *file, int line)
{ MUTEX_CLEANUP(l->mutex);
free(l);
}
void locking_function(int mode, int n, const char *file, int line)
{ if (mode & CRYPTO_LOCK)
MUTEX_LOCK(mutex_buf[n]);
else
MUTEX_UNLOCK(mutex_buf[n]);
}
unsigned long id_function()
{ return (unsigned long)THREAD_ID;
}
int CRYPTO_thread_setup()
{ int i;
mutex_buf = (MUTEX_TYPE*)malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
if (!mutex_buf)
return SOAP_EOM;
for (i = 0; i < CRYPTO_num_locks(); i++)
MUTEX_SETUP(mutex_buf[i]);
CRYPTO_set_id_callback(id_function);
CRYPTO_set_locking_callback(locking_function);
CRYPTO_set_dynlock_create_callback(dyn_create_function);
CRYPTO_set_dynlock_lock_callback(dyn_lock_function);
CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function);
return SOAP_OK;
}
void CRYPTO_thread_cleanup()
{ int i;
if (!mutex_buf)
return;
CRYPTO_set_id_callback(NULL);
CRYPTO_set_locking_callback(NULL);
CRYPTO_set_dynlock_create_callback(NULL);
CRYPTO_set_dynlock_lock_callback(NULL);
CRYPTO_set_dynlock_destroy_callback(NULL);
for (i = 0; i < CRYPTO_num_locks(); i++)
MUTEX_CLEANUP(mutex_buf[i]);
free(mutex_buf);
mutex_buf = NULL;
}
#endif
/******************************************************************************\
*
* SIGPIPE
*
\******************************************************************************/
void sigpipe_handle(int x) { }