parent
338b1364f1
commit
a12d07d909
@ -0,0 +1,62 @@
|
||||
#ifndef SSL_CONNECTION_HPP
|
||||
#define SSL_CONNECTION_HPP
|
||||
|
||||
|
||||
#include "SocketConnection.hpp"
|
||||
#include "TcpConnection.hpp"
|
||||
#include "Message.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
// #include <openssl/rand.h>
|
||||
#include <openssl/ssl.h>
|
||||
// #include <openssl/err.h>
|
||||
|
||||
|
||||
|
||||
/// @note Call init/destroy before/after usage
|
||||
class SslConnection : public SocketConnection
|
||||
{
|
||||
public:
|
||||
|
||||
static void init();
|
||||
static void destroy();
|
||||
|
||||
SslConnection ( const int socket,
|
||||
Message *message,
|
||||
const size_t bufferLength = 1024 );
|
||||
|
||||
SslConnection ( const std::string host,
|
||||
const std::string port,
|
||||
Message *message,
|
||||
const size_t bufferLength = 1024 );
|
||||
|
||||
virtual ~SslConnection();
|
||||
|
||||
SocketConnection* clone(const int socket);
|
||||
|
||||
bool connectToHost();
|
||||
bool bindToHost();
|
||||
bool listen( const int maxPendingQueueLen = 64 );
|
||||
void closeConnection();
|
||||
|
||||
bool send( const void* message, const size_t length );
|
||||
bool receive();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
SslConnection(const SslConnection&);
|
||||
SslConnection& operator=(const SslConnection&);
|
||||
|
||||
bool connect();
|
||||
std::string getSslError(const std::string &msg);
|
||||
|
||||
|
||||
TcpConnection m_tcpConnection;
|
||||
SSL *m_sslHandle;
|
||||
SSL_CTX *m_sslContext;
|
||||
};
|
||||
|
||||
|
||||
#endif // SSL_CONNECTION_HPP
|
@ -0,0 +1,107 @@
|
||||
// gpp sslclient_main.cpp -o sslclient -I../include ../src/Logger.cpp ../src/Thread.cpp ../src/Socket.cpp -lpthread ../src/SocketClient.cpp ../src/Poll.cpp ../src/SocketConnection.cpp ../src/SslConnection.cpp -lssl -lcrypto ../src/TcpConnection.cpp
|
||||
|
||||
#include "Logger.hpp"
|
||||
|
||||
#include "Message.hpp"
|
||||
#include "SslConnection.hpp"
|
||||
#include "SocketClient.hpp"
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <time.h> // nanosleep
|
||||
|
||||
|
||||
|
||||
|
||||
class SimpleMessage : public Message
|
||||
{
|
||||
public:
|
||||
|
||||
SimpleMessage( void *msgParam = 0)
|
||||
: Message(msgParam)
|
||||
{
|
||||
TRACE;
|
||||
}
|
||||
|
||||
bool buildMessage( const void *msgPart,
|
||||
const size_t msgLen )
|
||||
{
|
||||
TRACE;
|
||||
m_buffer = std::string( (const char*) msgPart, msgLen );
|
||||
onMessageReady();
|
||||
return true;
|
||||
}
|
||||
|
||||
void onMessageReady()
|
||||
{
|
||||
TRACE;
|
||||
|
||||
LOG( Logger::INFO, std::string("Got reply from server: ").
|
||||
append(m_buffer).c_str() );
|
||||
|
||||
*( static_cast<bool*>(m_param) ) = true;
|
||||
}
|
||||
|
||||
Message* clone()
|
||||
{
|
||||
TRACE;
|
||||
return new SimpleMessage(m_param);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
size_t getExpectedLength()
|
||||
{
|
||||
TRACE;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char* argv[] )
|
||||
{
|
||||
if ( argc != 4 ) {
|
||||
std::cerr << "Usage: " << argv[0] << " <HOST> <PORT> <MSG>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
Logger::createInstance();
|
||||
Logger::init(std::cout);
|
||||
Logger::setLogLevel(Logger::FINEST);
|
||||
SslConnection::init();
|
||||
|
||||
bool finished = false;
|
||||
|
||||
SimpleMessage msg(&finished);
|
||||
SslConnection conn(argv[1], argv[2], &msg);
|
||||
SocketClient socketClient(&conn);
|
||||
|
||||
if ( !socketClient.connect() ) {
|
||||
LOG( Logger::ERR, "Couldn't connect to server, exiting..." );
|
||||
Logger::destroy();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// wait for thread creation
|
||||
sleep(1);
|
||||
|
||||
// send message to server
|
||||
std::string msg1(argv[3]);
|
||||
if ( !socketClient.send( msg1.c_str(), msg1.length()) ) {
|
||||
LOG( Logger::ERR, "Couldn't send message to server, exiting..." );
|
||||
Logger::destroy();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// wait for the complate &handled reply
|
||||
struct timespec tm = {0,1000};
|
||||
while ( !finished && socketClient.isPolling() )
|
||||
nanosleep(&tm, &tm) ;
|
||||
|
||||
socketClient.disconnect();
|
||||
SslConnection::destroy();
|
||||
Logger::destroy();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,206 @@
|
||||
#include "SslConnection.hpp"
|
||||
|
||||
#include "Logger.hpp"
|
||||
#include "Common.hpp"
|
||||
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
|
||||
|
||||
void SslConnection::init()
|
||||
{
|
||||
TRACE_STATIC;
|
||||
|
||||
SSL_load_error_strings();
|
||||
SSL_library_init();
|
||||
}
|
||||
|
||||
void SslConnection::destroy()
|
||||
{
|
||||
TRACE_STATIC;
|
||||
|
||||
ERR_free_strings();
|
||||
}
|
||||
|
||||
|
||||
SslConnection::SslConnection ( const int socket,
|
||||
Message *message,
|
||||
const size_t bufferLength )
|
||||
: SocketConnection(socket, message, bufferLength)
|
||||
, m_tcpConnection(socket, 0, 0)
|
||||
, m_sslHandle(0)
|
||||
, m_sslContext(0)
|
||||
{
|
||||
TRACE;
|
||||
}
|
||||
|
||||
|
||||
SslConnection::SslConnection ( const std::string host,
|
||||
const std::string port,
|
||||
Message *message,
|
||||
const size_t bufferLength )
|
||||
: SocketConnection(host, port, message, bufferLength)
|
||||
, m_tcpConnection(host, port, 0, 0)
|
||||
, m_sslHandle(0)
|
||||
, m_sslContext(0)
|
||||
{
|
||||
TRACE;
|
||||
}
|
||||
|
||||
|
||||
SslConnection::~SslConnection()
|
||||
{
|
||||
TRACE;
|
||||
closeConnection();
|
||||
}
|
||||
|
||||
|
||||
SocketConnection* SslConnection::clone(const int socket)
|
||||
{
|
||||
SocketConnection *conn = new SslConnection(socket,
|
||||
m_message->clone(),
|
||||
m_bufferLength );
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
|
||||
bool SslConnection::connectToHost()
|
||||
{
|
||||
TRACE;
|
||||
|
||||
if ( !m_tcpConnection.connectToHost() )
|
||||
return false;
|
||||
|
||||
return connect();
|
||||
}
|
||||
|
||||
|
||||
bool SslConnection::bindToHost()
|
||||
{
|
||||
TRACE;
|
||||
|
||||
if ( !m_tcpConnection.bindToHost() )
|
||||
return false;
|
||||
|
||||
return connect();
|
||||
}
|
||||
|
||||
|
||||
bool SslConnection::listen( const int maxPendingQueueLen )
|
||||
{
|
||||
TRACE;
|
||||
return m_tcpConnection.listen(maxPendingQueueLen);
|
||||
}
|
||||
|
||||
|
||||
void SslConnection::closeConnection()
|
||||
{
|
||||
TRACE;
|
||||
|
||||
/// @note do I have to call this?
|
||||
m_tcpConnection.closeConnection();
|
||||
|
||||
int ret = SSL_shutdown(m_sslHandle);
|
||||
|
||||
if ( ret == 0 ) {
|
||||
LOG( Logger::INFO, "\"close notify\" alert was sent and the peer's "
|
||||
"\"close notify\" alert was received.");
|
||||
}
|
||||
else if (ret == 1 ) {
|
||||
LOG( Logger::WARNING, "\"The shutdown is not yet finished. "
|
||||
"Calling SSL_shutdown() for a second time...");
|
||||
SSL_shutdown(m_sslHandle);
|
||||
}
|
||||
else if ( ret == 2 ) {
|
||||
LOG (Logger::ERR, getSslError("The shutdown was not successful. ").c_str() );
|
||||
}
|
||||
|
||||
SSL_free(m_sslHandle);
|
||||
SSL_CTX_free(m_sslContext);
|
||||
}
|
||||
|
||||
|
||||
bool SslConnection::send( const void* message, const size_t length )
|
||||
{
|
||||
TRACE;
|
||||
|
||||
int ret = SSL_write(m_sslHandle, message, length);
|
||||
|
||||
if ( ret > 0 )
|
||||
return true;
|
||||
|
||||
unsigned long sslErrNo = ERR_peek_error();
|
||||
if ( ret == 0 && sslErrNo == SSL_ERROR_ZERO_RETURN ) {
|
||||
LOG( Logger::INFO, "Underlying connection has been closed.");
|
||||
return true;
|
||||
}
|
||||
|
||||
LOG (Logger::ERR, getSslError("SSL write failed. ").c_str() );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SslConnection::receive()
|
||||
{
|
||||
TRACE;
|
||||
|
||||
int length = SSL_read(m_sslHandle, m_buffer, m_bufferLength);
|
||||
|
||||
if ( length > 0 )
|
||||
return m_message->buildMessage( (void*)m_buffer, (size_t)length);
|
||||
|
||||
unsigned long sslErrNo = ERR_peek_error();
|
||||
if ( length == 0 && sslErrNo == SSL_ERROR_ZERO_RETURN ) {
|
||||
LOG( Logger::INFO, "Underlying connection has been closed.");
|
||||
return true;
|
||||
}
|
||||
|
||||
LOG (Logger::ERR, getSslError("SSL read failed. ").c_str() );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SslConnection::connect()
|
||||
{
|
||||
TRACE;
|
||||
|
||||
m_sslContext = SSL_CTX_new (SSLv23_client_method ());
|
||||
if ( m_sslContext == NULL ) {
|
||||
LOG (Logger::ERR, getSslError("Creating SSL context failed. ").c_str() );
|
||||
return false;
|
||||
}
|
||||
|
||||
m_sslHandle = SSL_new (m_sslContext);
|
||||
if ( m_sslHandle == NULL ) {
|
||||
LOG (Logger::ERR, getSslError("Creating SSL structure for connection failed. ").c_str() );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if ( !SSL_set_fd (m_sslHandle, m_tcpConnection.getSocket()) ) {
|
||||
LOG (Logger::ERR, getSslError("Connect the SSL object with a file descriptor failed. ").c_str() );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if ( SSL_connect (m_sslHandle) != 1 ) {
|
||||
LOG (Logger::ERR, getSslError("Handshake with SSL server failed. ").c_str() );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
std::string SslConnection::getSslError(const std::string &msg)
|
||||
{
|
||||
char buffer[130];
|
||||
unsigned long sslErrNo = ERR_get_error();
|
||||
|
||||
ERR_error_string(sslErrNo, buffer);
|
||||
|
||||
return std::string(msg).append(buffer);
|
||||
}
|
Loading…
Reference in new issue