@@ -2,7 +2,7 @@ EXECUTABLE = server | |||
EXECUTABLECLI = client | |||
CC=g++ -lboost_system -lboost_thread | |||
CFLAGS=-Wall -DDEBUG -Wreorder | |||
CFLAGS=-Wall -DDEBUG -Wreorder -D_RENEG_ON_ | |||
COMPILE=$(CC) $(CFLAGS) | |||
all: server client | |||
@@ -33,6 +33,28 @@ int CharsRead = 0; | |||
// with this you can block sender thread during renegotiation | |||
mutex WriteReadMutex; | |||
bool handle_error_code(int& len, SSL* SSLHandler, int code, const char* func) | |||
{ | |||
switch( SSL_get_error( SSLHandler, code ) ) | |||
{ | |||
case SSL_ERROR_NONE: | |||
len+=code; | |||
return false; | |||
case SSL_ERROR_ZERO_RETURN: | |||
cout << "CONNETION CLOSE ON WRITE" << endl; | |||
break; | |||
case SSL_ERROR_WANT_READ: | |||
cout << func << " WANT READ" << endl; | |||
break; | |||
case SSL_ERROR_WANT_WRITE: | |||
cout << func << " WANT WRITE" << endl; | |||
break; | |||
} | |||
return true; | |||
} | |||
void Sender() | |||
{ | |||
while(1) | |||
@@ -42,7 +64,14 @@ void Sender() | |||
do | |||
{ | |||
lock_guard<mutex> lock(WriteReadMutex); | |||
len+=SSL_write(SSLHandler, buf.c_str()+len, buf.size()-len); | |||
bool flag = true; | |||
while( flag ) | |||
{ | |||
int code = SSL_write(SSLHandler, buf.c_str()+len, buf.size()-len); | |||
flag = handle_error_code(len, SSLHandler, code, "SSL_write"); | |||
} | |||
// for debugging re-neg | |||
cout << "SSL STATE: " << SSL_state_string(SSLHandler) << endl; | |||
} while( len != static_cast<int>(buf.size()) ); | |||
@@ -59,7 +88,12 @@ void Client::receive() | |||
int len_rcv = 0; | |||
{ | |||
lock_guard<mutex> lock(WriteReadMutex); | |||
len_rcv = SSL_read(SSLHandler, buf, MAX_PACKET_SIZE); | |||
bool flag = true; | |||
while( flag ) | |||
{ | |||
len_rcv = SSL_read(SSLHandler, buf, MAX_PACKET_SIZE); | |||
flag = handle_error_code(len_rcv, SSLHandler, len_rcv, "SSL_read"); | |||
} | |||
} | |||
if( len_rcv != 0 ) | |||
@@ -99,11 +133,12 @@ void Client::connect() | |||
SSLHandler = SSL_new(_ctx); | |||
long mode = SSL_CTX_set_mode(_ctx, SSL_MODE_AUTO_RETRY); | |||
if( ( mode & SSL_MODE_AUTO_RETRY) != SSL_MODE_AUTO_RETRY ) | |||
{ | |||
throw runtime_error("SSL_MODE_AUTO_RETRY couldn't be set"); | |||
} | |||
// if socket is blocking you can set this and forget about looking at SSL_get_error code on I/O calls | |||
// long mode = SSL_CTX_set_mode(_ctx, SSL_MODE_AUTO_RETRY); | |||
// if( ( mode & SSL_MODE_AUTO_RETRY) != SSL_MODE_AUTO_RETRY ) | |||
// { | |||
// throw runtime_error("SSL_MODE_AUTO_RETRY couldn't be set"); | |||
// } | |||
SSL_set_fd(SSLHandler, _handler); | |||
@@ -140,11 +175,13 @@ void Client::start() | |||
if( FD_ISSET(_handler, &fd_read ) ) | |||
{ | |||
// this should be in other thread but... it works | |||
#ifdef _RENEG_ON_ | |||
if( CharsRead > RENEG_INIT_LEN ) | |||
{ | |||
CharsRead = 0; | |||
renegotiate(); | |||
} | |||
#endif | |||
receive(); | |||
} | |||
} | |||
@@ -3,7 +3,7 @@ | |||
#define IP "127.0.0.1" | |||
#define EXCHANGE_STRING "ABCDEFGHIJKLMNOPRSTUWXYZ" | |||
#define EXCHANGE_STRING_LEN sizeof(EXCHANGE_STRING)/sizeof(EXCHANGE_STRING[0]) | |||
#define RENEG_INIT_LEN 200 | |||
#define RENEG_INIT_LEN 4200 | |||
#define CERTIFICATE_FILE "etc/cert" | |||
#define PRIVATE_KEY_FILE "etc/pkey" | |||
#define SEND_ITERATIONS 100000 |
@@ -227,28 +227,41 @@ void Receive() | |||
{ | |||
lock_guard<mutex> lock(WriteReadMutex); | |||
len_rcv = SSL_read(handler.second, buf, 1024); | |||
} | |||
if( len_rcv ) | |||
{ | |||
// dirty thing - if it has \n on the end - remove it | |||
if( buf[len_rcv-1] == '\n' ) | |||
buf[len_rcv-1] = '\0'; | |||
cout << buf << endl; | |||
// add it back to the socket so that select can use it | |||
lock_guard<mutex> guard(SocketSetMutex); | |||
SocketSet.insert(handler); | |||
switch( SSL_get_error(handler.second, len_rcv) ) | |||
{ | |||
case SSL_ERROR_NONE: | |||
{ | |||
// dirty thing - if it has \n on the end - remove it | |||
if( buf[len_rcv-1] == '\n' ) | |||
buf[len_rcv-1] = '\0'; | |||
cout << buf << endl; | |||
{ | |||
// add it back to the socket so that select can use it | |||
lock_guard<mutex> guard(SocketSetMutex); | |||
SocketSet.insert(handler); | |||
// push handler ID and notify sender thread | |||
WriteHandler = handler; | |||
WaitForWrite.notify_one(); | |||
} | |||
break; | |||
} | |||
case SSL_ERROR_WANT_READ: | |||
case SSL_ERROR_WANT_WRITE: | |||
{ | |||
cout << "WANT_SOMETHING WHEN Receive" << endl; | |||
exit(1); | |||
break; | |||
} | |||
default : | |||
{ | |||
cout << "Closing connection " << handler.first << endl; | |||
::close(handler.first); | |||
exit(1); | |||
} | |||
// push handler ID and notify sender thread | |||
WriteHandler = handler; | |||
WaitForWrite.notify_one(); | |||
} | |||
else | |||
{ | |||
cout << "Closing connection " << handler.first << endl; | |||
::close(handler.first); | |||
} | |||
} | |||
} | |||
} | |||
@@ -273,7 +286,28 @@ void Send() | |||
do | |||
{ | |||
lock_guard<mutex> lock(WriteReadMutex); | |||
len+=SSL_write(handler.second, buf.c_str()+len, buf.size()-len); | |||
int write_len=SSL_write(handler.second, buf.c_str()+len, buf.size()-len); | |||
switch( SSL_get_error(handler.second, write_len) ) | |||
{ | |||
case SSL_ERROR_NONE: | |||
{ | |||
len += write_len; | |||
break; | |||
} | |||
case SSL_ERROR_WANT_READ: | |||
case SSL_ERROR_WANT_WRITE: | |||
{ | |||
cout << "WANT_SOMETHING WHEN Send" << endl; | |||
exit(1); | |||
break; | |||
} | |||
default : | |||
{ | |||
cout << "Closing connection " << handler.first << endl; | |||
::close(handler.first); | |||
exit(1); | |||
} | |||
} | |||
// for debugging re-neg | |||
// cout << "SSL STATE: " << SSL_state_string(handler.second) << endl; | |||
} while( len != static_cast<int>(buf.size()) ); | |||