#define _BSD_SOURCE 1
#define _XOPEN_SOURCE 1 /* or any value < 500 */
#define _POSIX_C_SOURCE 1
#include <sys/types.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <bits/sigthread.h>
#include <sys/time.h>
#include <sys/types.h>
#include <openssl/rand.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
// Simple structure to keep track of the handle, and
// of what needs to be freed later.
typedef struct {
int socket;
SSL_CTX *sslContext;
char* protocol_list;
int protocol_list_length;
} connection_t;
// Simple structure representing a session here
typedef struct {
int socket;
SSL *sslHandle;
// Protocol index selected during negotiation....
int protocol_index;
} wired_session_t;
// This is the public API of this server...
// No arguments, all are wired here somewhere... for now
connection_t* make_connection();
// Call when you are done
void close_connection(connection_t* conn);
// Wait for the next one...
#define ALL_OK 0
#define BAD_HAPPENED 1
#define TIMEOUT_REACHED 3
// This is also a failed IO with SSL, but this one may be quite
// natural and we want to handle it differently
#define TRANSPORT_CLOSED 2
int wait_for_connection(connection_t* conn, int microseconds, wired_session_t** wired_session);
int send_data(wired_session_t* ws, char* buffer, int buffer_size);
int recv_data(wired_session_t* ws, char* inbuffer, int buffer_size, int* data_recvd);
int get_selected_protocol(wired_session_t* ws){ return ws->protocol_index; }
void dispose_wired_session(wired_session_t* ws);
static int thread_setup(void);
////////////////////////////////////////////////////////////////////////
static int threads_are_up = 0;
// Leaky implementation now
void close_connection(connection_t* conn)
{
if (conn->socket)
{
close (conn->socket);
conn->socket = 0;
}
if (conn->sslContext)
{
SSL_CTX_free(conn->sslContext);
conn->sslContext = 0;
}
free(conn);
}
// For this example, we'll be testing on openssl.org
// Establish a regular tcp connection
static int tcpStart (char* hostname, int portno, int* errorh)
{
int error, handle;
*errorh = 0;
struct hostent *host;
struct sockaddr_in server;
bzero((char *) &server, sizeof(server));
host = gethostbyname (hostname);
handle = socket (AF_INET, SOCK_STREAM, 0);
int one = 1;
setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
if (handle == -1)
{
perror ("Socket could not be created");
handle = 0;
*errorh = BAD_HAPPENED;
}
else
{
server.sin_family = AF_INET;
server.sin_port = htons (portno);
server.sin_addr = *((struct in_addr *) host->h_addr);
bzero (&(server.sin_zero), 8);
error = bind (handle, (struct sockaddr *) &server,
sizeof (struct sockaddr));
if (error == -1)
{
perror ("Bind");
handle = 0;
*errorh = BAD_HAPPENED;
}
else
{
error = listen(handle, 5);
if ( error != 0 )
{
perror("Listen");
handle = 0;
*errorh = BAD_HAPPENED;
}
}
}
return handle;
}
// Dh_Callback {{{
#ifndef HEADER_DH_H
#include <openssl/dh.h>
#endif
DH *get_dh2236()
{
static unsigned char dh2236_p[]={
0x08,0x32,0x3B,0x6A,0xE8,0xEA,0x55,0xE3,0x0C,0xD9,0x95,0x3D,
0xE7,0x78,0xDA,0xF0,0x05,0x81,0x94,0x85,0x34,0x5C,0x26,0x5A,
0xAE,0x9E,0x31,0x8F,0x0C,0xCC,0xFC,0xF3,0x30,0x88,0x20,0x0B,
0x41,0xC3,0xC9,0xEC,0x13,0xA7,0xFF,0xDA,0xBB,0x11,0xFB,0x7B,
0x19,0x92,0x3B,0x61,0xDF,0x31,0xEF,0x2C,0x4A,0x5C,0xD1,0x59,
0x16,0x90,0xAC,0xFC,0xEA,0xFF,0xCB,0xC4,0x04,0x07,0x93,0x9D,
0xF0,0x70,0x0B,0xCB,0x3E,0x79,0x0D,0xEB,0xD3,0x3E,0x06,0x0B,
0x19,0xF2,0x97,0x1E,0xE1,0xBF,0xD2,0xBE,0x5E,0xA5,0xBD,0x5F,
0x73,0x2C,0x57,0x0C,0xB0,0x97,0x78,0xAA,0x60,0xDC,0x98,0x89,
0xAF,0xBF,0xCD,0x49,0x74,0x82,0x64,0x09,0x60,0x47,0xD0,0xD4,
0x5D,0x25,0xDC,0x38,0xAC,0x17,0xE7,0xA4,0x47,0x59,0x94,0xFE,
0xA8,0xAD,0x58,0xD0,0xD1,0x43,0x3C,0x20,0x2E,0x34,0xEE,0xA9,
0x0F,0x71,0x20,0x93,0xB7,0x8E,0xEC,0xB1,0x75,0xB9,0xE9,0x9A,
0xAB,0x73,0xBB,0x7F,0xA2,0x8F,0x11,0xDE,0x58,0x5E,0xB0,0x98,
0xD6,0x95,0x84,0x62,0x90,0x87,0x90,0x32,0x34,0xF7,0x61,0x28,
0xFF,0x17,0xD0,0x58,0x33,0xA6,0xC2,0xC6,0x58,0x65,0x1C,0x92,
0xF3,0xDF,0x4D,0xB3,0xB0,0xFD,0xD2,0x4A,0x97,0x1B,0xA7,0xD2,
0x7C,0x8D,0x8F,0x1F,0x69,0x98,0x54,0xD9,0x33,0x15,0xE5,0xEA,
0xBA,0xAA,0x31,0xB1,0x17,0x65,0x21,0xFA,0xC7,0x54,0xC0,0xE4,
0x72,0x3C,0x15,0x74,0x41,0xF2,0x9A,0xF6,0xD1,0x16,0x10,0x35,
0x4F,0x36,0xA6,0x23,0x67,0x67,0x89,0x65,0xDD,0x77,0x5D,0x8F,
0x69,0x49,0x22,0x24,0xB6,0xB8,0x45,0xCA,0x8F,0x35,0x71,0x45,
0x4C,0x65,0x38,0x11,0x21,0xD5,0x39,0x03,0x4D,0x05,0xBB,0x95,
0x43,0x58,0xBB,0xF3,
};
static unsigned char dh2236_g[]={
0x02,
};
DH *dh;
if ((dh=DH_new()) == NULL) return(NULL);
dh->p=BN_bin2bn(dh2236_p,sizeof(dh2236_p),NULL);
dh->g=BN_bin2bn(dh2236_g,sizeof(dh2236_g),NULL);
if ((dh->p == NULL) || (dh->g == NULL))
{ DH_free(dh); return(NULL); }
return(dh);
}
DH *get_dh2048()
{
static unsigned char dh2048_p[]={
0xCE,0x28,0x14,0x1C,0xEF,0x22,0x1D,0x86,0xEA,0x10,0x00,0x50,
0x24,0x42,0x95,0xC3,0x07,0x5A,0x87,0xED,0x0F,0xC5,0xDC,0x0F,
0x5E,0x7E,0x69,0x25,0x85,0x90,0x39,0x60,0x1E,0x87,0x5C,0x4B,
0xAD,0xDF,0xA8,0xF4,0x9C,0xC6,0x2D,0x6A,0x2E,0x7C,0xD1,0x5C,
0xC5,0x1A,0x74,0xD3,0x9E,0xE1,0xBB,0x31,0xC4,0x23,0x2F,0x78,
0xF5,0x61,0x5C,0x09,0x7E,0x29,0x06,0xC5,0x07,0x50,0x32,0x80,
0x4A,0xBE,0x5F,0x7F,0x68,0x69,0x8F,0xB1,0x6D,0xA0,0x0C,0x7F,
0x9E,0x28,0x77,0x9D,0x4F,0xEA,0xB5,0x38,0xB3,0x72,0x8E,0x1D,
0x8D,0x1C,0x58,0x74,0x58,0xC4,0xDD,0x06,0x8E,0x80,0x91,0x36,
0x2D,0x42,0x3D,0xF0,0x11,0xEC,0xDF,0x02,0xFD,0x84,0x54,0x32,
0x90,0xFE,0x7C,0x74,0x3A,0x5F,0x87,0xBA,0xD3,0x21,0x0E,0xDD,
0xF4,0xB3,0xFD,0xF9,0x89,0x8F,0x96,0x59,0x90,0x74,0xE8,0x45,
0x5A,0x3A,0x7C,0x88,0x7F,0xD8,0x5F,0xD2,0x32,0x57,0x46,0x29,
0x6B,0xA1,0x0A,0x05,0x1E,0xB6,0x49,0x8A,0x68,0xB4,0xEE,0x84,
0x45,0xEF,0x56,0x7E,0x59,0x83,0x67,0x20,0x85,0x63,0x69,0x6B,
0x39,0xCA,0x24,0x46,0x68,0x51,0x94,0x9E,0x3E,0xB4,0x69,0x1F,
0x63,0x07,0x40,0x0E,0x84,0x8B,0x26,0x98,0xCE,0xE5,0x48,0x2C,
0xD8,0xF9,0x6A,0x3F,0x20,0xFA,0xFA,0xDC,0x4E,0xFA,0xBD,0xC3,
0x81,0x09,0x4D,0xCF,0x07,0xEF,0xE8,0x32,0x9B,0x63,0x32,0x5B,
0x06,0x59,0x4F,0xE7,0x5B,0xD2,0xFC,0x25,0xC6,0x2C,0xA3,0xE8,
0x05,0xE5,0x8D,0xC2,0x94,0x76,0x90,0x63,0x29,0xB4,0xEE,0x2D,
0xD6,0x50,0x83,0x8B,
};
static unsigned char dh2048_g[]={
0x02,
};
DH *dh;
if ((dh=DH_new()) == NULL) return(NULL);
dh->p=BN_bin2bn(dh2048_p,sizeof(dh2048_p),NULL);
dh->g=BN_bin2bn(dh2048_g,sizeof(dh2048_g),NULL);
if ((dh->p == NULL) || (dh->g == NULL))
{ DH_free(dh); return(NULL); }
return(dh);
}
DH *get_dh1024()
{
static unsigned char dh1024_p[]={
0x87,0xF4,0xE5,0x5A,0x1E,0x7F,0x98,0x83,0xFD,0x23,0x6A,0xF3,
0x8C,0xE8,0x2F,0x35,0x64,0x3D,0x13,0x34,0x5B,0x0A,0x52,0xEC,
0x0B,0x3A,0xBF,0x92,0xE4,0x67,0x14,0x47,0x86,0x55,0x2C,0x83,
0x1B,0xDD,0x0E,0xC8,0x2D,0x98,0x72,0x2A,0xB6,0x68,0xF1,0x32,
0xD8,0xBD,0x6B,0x17,0x23,0x46,0x08,0xB6,0x19,0x58,0x01,0x30,
0x32,0x68,0x60,0x78,0xD1,0x5B,0x5C,0x88,0x3F,0x20,0xD7,0xEB,
0xE8,0xD5,0x80,0xB0,0x23,0x75,0xAE,0x97,0x26,0xBD,0xA5,0x11,
0x7F,0x83,0x8C,0x21,0xD4,0x39,0x52,0xE0,0x25,0x1F,0x03,0xA9,
0x69,0xF8,0x07,0x4F,0x33,0x17,0x72,0xCC,0xEB,0xBD,0x77,0xD1,
0x9C,0x40,0xA6,0x55,0xE3,0x87,0x76,0x66,0x3B,0xE3,0xE4,0x6A,
0x4B,0x6B,0xF1,0x92,0x1A,0x3A,0x25,0xC3,
};
static unsigned char dh1024_g[]={
0x02,
};
DH *dh;
if ((dh=DH_new()) == NULL) return(NULL);
dh->p=BN_bin2bn(dh1024_p,sizeof(dh1024_p),NULL);
dh->g=BN_bin2bn(dh1024_g,sizeof(dh1024_g),NULL);
if ((dh->p == NULL) || (dh->g == NULL))
{ DH_free(dh); return(NULL); }
return (dh);
}
static DH *tmp_dh_callback(SSL *s, int is_export, int keylength);
// Setup dh params
static void setup_dh_parms(SSL_CTX *sslContext)
{
/* Set up ephemeral DH stuff */
SSL_CTX_set_tmp_dh_callback(sslContext, tmp_dh_callback);
}
static DH *tmp_dh_callback(SSL *s, int is_export, int keylength)
{
static DH *dh_2048 = NULL;
static DH *dh_1024 = NULL;
DH *dh_tmp=NULL;
switch (keylength) {
case 2048:
if (!dh_2048)
dh_2048 = get_dh2048();
dh_tmp = dh_2048;
break;
case 1024:
if (!dh_1024)
dh_1024 = get_dh1024();
dh_tmp = dh_1024;
break;
default:
/* Generating a key on the fly is very costly, so use what is there */
printf("UNEXPECTED: Keylength %d \n", keylength);
}
return(dh_tmp);
}
// dh_callback }}}
static int protocol_select (
SSL *ssl,
const unsigned char **out,
unsigned char *outlen,
const unsigned char *in,
unsigned int inlen,
void *arg)
{
// Oh well, C is a verbose beast
connection_t* conn = (connection_t*) arg;
static char output[64];
char* incursor = (char*) in;
while (incursor < (char*)in + inlen )
{
// Got a protocol.... can I satisfy it?
char sublen = *incursor;
//printf("offered prot %.*s \n", sublen, incursor+1);
char* stored_cursor = conn->protocol_list;
int sto_protocol = 0;
while( stored_cursor < conn->protocol_list + conn->protocol_list_length)
{
char sublen2 = *stored_cursor;
if (sublen != sublen2)
{
} else {
int cmpresult = strncmp( incursor + 1, stored_cursor + 1, sublen);
if (cmpresult == 0)
{
// They are equal, choose this one...
strncpy( output, stored_cursor+1, sublen);
*outlen = sublen;
*out = output;
return SSL_TLSEXT_ERR_OK;
}
}
sto_protocol += 1;
stored_cursor += (1+sublen2);
}
incursor += (1+sublen);
}
// I think this is what should be returned
return -1;
}
int lookup_protocol(
char* selected, int selected_len,
char* myprotocol_list, int mpl_len
)
{
char* incursor = selected;
char* stored_cursor = myprotocol_list;
int sto_protocol = 0;
if (selected_len == 0)
{
// No protocol was selected
return -2;
}
while( stored_cursor < myprotocol_list + mpl_len)
{
char sublen2 = *stored_cursor;
if (sublen2 != selected_len)
{
// It is not this cone, continue
} else {
int cmpresult = strncmp( selected, stored_cursor + 1, sublen2);
if (cmpresult == 0)
{
// They are equal, choose this one...
return sto_protocol;
}
}
sto_protocol += 1;
stored_cursor += (1+sublen2);
}
// I think this is what should be returned
return -1;
}
static int ssl_servername_cb(SSL *s, int *ad, void *arg)
{
// TODO: Use this for something .... although I'm not sure what...
// tlsextctx *p = (tlsextctx *) arg;
// const char *servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
// if (servername && p->biodebug)
// BIO_printf(p->biodebug, "Hostname in TLS extension: \"%s\"\n",
// servername);
// if (!p->servername)
// return SSL_TLSEXT_ERR_NOACK;
// if (servername) {
// if (strcasecmp(servername, p->servername))
// return p->extension_error;
// if (ctx2) {
// BIO_printf(p->biodebug, "Switching server context.\n");
// SSL_set_SSL_CTX(s, ctx2);
// }
// }
return SSL_TLSEXT_ERR_OK;
}
// Establish a connection using an SSL layer
static connection_t *sslStart (
char* certificate_filename, char* privkey_filename, char* hostname, int portno,
char* protocol_list, int protocol_list_length
)
{
int result;
connection_t *c;
if (! threads_are_up)
{
threads_are_up = 1;
thread_setup();
}
c = malloc (sizeof (connection_t));
c->sslContext = NULL;
c->protocol_list = (char*) malloc(protocol_list_length);
strncpy( c->protocol_list, protocol_list, protocol_list_length );
c->protocol_list_length = protocol_list_length;
c->socket = tcpStart (hostname, portno, &result);
if ( result )
{
return 0;
}
if (c->socket)
{
// Register the error strings for libcrypto & libssl
SSL_load_error_strings ();
// Register the available ciphers and digests
SSL_library_init ();
// New context saying we are a server, and using SSL 2 or 3
c->sslContext = SSL_CTX_new( TLSv1_2_server_method() );
if (c->sslContext == NULL)
{
ERR_print_errors_fp (stderr);
perror("Could not create context");
return 0;
}
// Now I set a few options....
/*SSL_CTX_set_verify(c->sslContext, NULL );*/
// const long flags =
// SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_NO_COMPRESSION;
const long flags =
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_NO_COMPRESSION;
SSL_CTX_set_options(c->sslContext, flags);
setup_dh_parms( c->sslContext );
SSL_CTX_set_ecdh_auto (c->sslContext, 1);
// Give the impression that we are using SNI
SSL_CTX_set_tlsext_servername_callback(c->sslContext, ssl_servername_cb);
// The only cipher supported by HTTP/2 ... sort of.
result = SSL_CTX_set_cipher_list(c->sslContext, "ECDHE-RSA-AES128-GCM-SHA256");
/*result = SSL_CTX_set_cipher_list(c->sslContext, "DEFAULT");*/
// Be sure we are able to do ALPN
// void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx,
// int (*cb) (SSL *ssl,
// const unsigned char **out,
// unsigned char *outlen,
// const unsigned char *in,
// unsigned int inlen,
// void *arg), void *arg);
SSL_CTX_set_alpn_select_cb( c->sslContext, protocol_select, c);
if ( result != 1 )
{
ERR_print_errors_fp (stderr);
perror("Could not set cipher");
return 0;
}
// The certificate (well-wired)
SSL_CTX_use_certificate_file(c->sslContext, certificate_filename, SSL_FILETYPE_PEM);
SSL_CTX_use_PrivateKey_file(c->sslContext, privkey_filename, SSL_FILETYPE_PEM);
// Check the private key
result = SSL_CTX_check_private_key(c->sslContext);
if ( result != 1)
{
char msg[600];
snprintf(msg, 600, "Check certificate file %s and privkey %s failed", certificate_filename,
privkey_filename);
perror(msg);
return 0;
}
// //////////////////////////////////////////
}
else
{
perror ("Connect failed");
}
return c;
}
connection_t* make_connection(char* certificate_filename, char* privkey_filename, char* hostname, int portno,
char* my_protocol_list, int protocol_list_length
)
{
const int len = strlen(hostname);
if ( len > 0 && hostname[len-1] == '\n' )
{
printf("HELLO THERE. I'M A FLIMSY C FUNCTION AND I CAN NOT REMOVE THE END-OF-LINE IN THE PROVIDED HOST NAME WITHOUT A TON OF LINES. I'M GOING TO SEGFAULT NOW. BYE.\n");
*( (int*) 0) = 42; // <-- This is the answer
}
return sslStart(
certificate_filename, privkey_filename, hostname,
portno, my_protocol_list, protocol_list_length);
}
int wait_for_connection(
connection_t* c,
int microseconds,
wired_session_t** wired_session)
{
int clilen, newsockfd;
// Don't return anything if there's a failure...
*wired_session = 0;
// Wait for a connection
struct sockaddr_in cli_addr;
clilen = sizeof(cli_addr);
// Use select to get "interruptible" accepts
fd_set rfds;
int can_go = 0;
while( ! can_go )
{
FD_ZERO(&rfds);
FD_SET(c->socket, &rfds);
struct timeval tv;
tv.tv_sec = microseconds / 1000000;
tv.tv_usec = microseconds % 1000000;
int retval = select(FD_SETSIZE, &rfds, NULL, NULL, &tv);
if ( retval == -1 )
{
if ( errno == EINTR )
{
// printf(".");
can_go = 0;
} else {
perror("select()");
return BAD_HAPPENED;
}
} else if (retval > 0)
{
// We got data, just let it go...
// printf("letitgo\n");
can_go = 1;
} else
{
// We didn't get data, finish and terminate
// printf("timeo\n");
return TIMEOUT_REACHED;
}
}
wired_session_t* result = (wired_session_t*) malloc(sizeof(wired_session_t) );
if ( result == 0 )
{
perror("Malloc failed");
return BAD_HAPPENED;
}
/* Accept actual connection from the client */
newsockfd = accept(c->socket, (struct sockaddr *)&cli_addr, &clilen);
if (newsockfd < 0)
{
perror("ERROR on accept");
return BAD_HAPPENED;
}
// Create an SSL struct for the connection
result->socket = newsockfd;
result->sslHandle = SSL_new (c->sslContext);
if (result->sslHandle == NULL)
{
perror("No handle on SSL new");
ERR_print_errors_fp (stderr);
return BAD_HAPPENED;
}
// Connect the SSL struct to our connection
if (!SSL_set_fd (result->sslHandle, result->socket))
{
perror("Could not associate");
ERR_print_errors_fp (stderr);
return BAD_HAPPENED;
}
// Initiate SSL handshake
if (SSL_accept (result->sslHandle) != 1)
{
perror("Could not accept");
ERR_print_errors_fp (stderr);
return BAD_HAPPENED;
}
// After this one is okej, see which protocol was selected
const unsigned char* out_protocol; unsigned pr_len;
SSL_get0_alpn_selected(result->sslHandle, &out_protocol,
&pr_len);
// Wonder who is in charge of releasing that buffer...
result -> protocol_index = lookup_protocol(
(char*)out_protocol, pr_len,
c->protocol_list, c->protocol_list_length);
*wired_session = result;
return ALL_OK;
}
// Disconnect & free connection struct
/*static void sslDisconnect (connection *c)*/
/*{*/
/*if (c->socket)*/
/*close (c->socket);*/
/*if (c->sslHandle)*/
/*{*/
/*SSL_shutdown (c->sslHandle);*/
/*SSL_free (c->sslHandle);*/
/*}*/
/*if (c->sslContext)*/
/*SSL_CTX_free (c->sslContext);*/
/*free (c);*/
/*}*/
int send_data(wired_session_t* ws, char* buffer, int buffer_size)
{
if ( buffer_size == 0 )
{
return ALL_OK;
}
if (ws)
{
int result = SSL_write( ws->sslHandle, buffer, buffer_size);
if ( result > 0 )
{
return ALL_OK;
} else {
return BAD_HAPPENED;
}
} else
{
return BAD_HAPPENED;
}
}
int recv_data(wired_session_t* ws, char* inbuffer, int buffer_size, int* data_recvd)
{
int received=0, count = 0;
char buffer[1024];
// printf("Recvd entered\n");
if (ws)
{
received = SSL_read (ws->sslHandle, inbuffer, buffer_size);
}
if ( received <= 0 )
{
ERR_print_errors_fp (stderr);
return BAD_HAPPENED;
}
*data_recvd = received ;
// printf("Recvd exited\n");
return ALL_OK;
}
#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( )
void handle_error(const char *file, int lineno, const char *msg){
fprintf(stderr, "** %s:%d %s\n", file, lineno, msg);
ERR_print_errors_fp(stderr);
/* exit(-1); */
}
/* This array will store all of the mutexes available to OpenSSL. */
static MUTEX_TYPE *mutex_buf= NULL;
static 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]);
}
static unsigned long id_function(void)
{
return ((unsigned long)THREAD_ID);
}
void dispose_wired_session(wired_session_t* ws)
{
if (ws == 0)
return ;
if ( ws-> sslHandle )
{
SSL_shutdown( ws->sslHandle );
ws -> sslHandle = 0;
}
if (ws->socket)
{
close(ws->socket);
ws -> socket = 0;
}
free(ws);
}
int thread_setup(void)
{
int i;
// printf("Threads setup\n");
mutex_buf = malloc(CRYPTO_num_locks( ) * sizeof(MUTEX_TYPE));
if (!mutex_buf)
return 0;
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);
return 1;
}
int thread_cleanup(void)
{
int i;
if (!mutex_buf)
return 0;
CRYPTO_set_id_callback(NULL);
CRYPTO_set_locking_callback(NULL);
for (i = 0; i < CRYPTO_num_locks( ); i++)
MUTEX_CLEANUP(mutex_buf[i]);
free(mutex_buf);
mutex_buf = NULL;
return 1;
}