managed secure socket allocation and deallocation #4313

This commit is contained in:
XinyuHou 2015-01-28 13:07:03 +00:00
parent d80aa7c938
commit 622e40e5d7
20 changed files with 119 additions and 48 deletions

View File

@ -81,7 +81,8 @@ Client::Client(
m_sendFileThread(NULL), m_sendFileThread(NULL),
m_writeToDropDirThread(NULL), m_writeToDropDirThread(NULL),
m_enableDragDrop(enableDragDrop), m_enableDragDrop(enableDragDrop),
m_socket(NULL) m_socket(NULL),
m_useSecureNetwork(false)
{ {
assert(m_socketFactory != NULL); assert(m_socketFactory != NULL);
assert(m_screen != NULL); assert(m_screen != NULL);
@ -155,13 +156,13 @@ Client::connect()
} }
// create the socket // create the socket
bool useSecureSocket = ARCH->plugin().exists(s_networkSecurity); m_useSecureNetwork = ARCH->plugin().exists(s_networkSecurity);
IDataSocket* socket = m_socketFactory->create(useSecureSocket); IDataSocket* socket = m_socketFactory->create(m_useSecureNetwork);
m_socket = dynamic_cast<TCPSocket*>(socket); m_socket = dynamic_cast<TCPSocket*>(socket);
// filter socket messages, including a packetizing filter // filter socket messages, including a packetizing filter
m_stream = socket; m_stream = socket;
bool adopt = !useSecureSocket; bool adopt = !m_useSecureNetwork;
m_stream = new PacketStreamFilter(m_events, m_stream, adopt); m_stream = new PacketStreamFilter(m_events, m_stream, adopt);
if (m_crypto.m_mode != kDisabled) { if (m_crypto.m_mode != kDisabled) {
@ -570,10 +571,14 @@ Client::cleanupTimer()
void void
Client::cleanupStream() Client::cleanupStream()
{ {
bool useSecureSocket = ARCH->plugin().exists(s_networkSecurity);
if (!useSecureSocket) {
delete m_stream; delete m_stream;
m_stream = NULL; m_stream = NULL;
// PacketStreamFilter doen't adopt secure socket, because
// we need to tell the dynamic lib that allocated this object
// to do the deletion.
if (m_useSecureNetwork) {
ARCH->plugin().invoke(s_networkSecurity, "deleteSocket", NULL);
} }
} }

View File

@ -233,4 +233,5 @@ private:
Thread* m_writeToDropDirThread; Thread* m_writeToDropDirThread;
bool m_enableDragDrop; bool m_enableDragDrop;
TCPSocket* m_socket; TCPSocket* m_socket;
bool m_useSecureNetwork;
}; };

View File

@ -49,13 +49,13 @@ public:
virtual bool isReady() const; virtual bool isReady() const;
virtual UInt32 getSize() const; virtual UInt32 getSize() const;
protected:
//! Get the stream //! Get the stream
/*! /*!
Returns the stream passed to the c'tor. Returns the stream passed to the c'tor.
*/ */
synergy::IStream* getStream() const; synergy::IStream* getStream() const;
protected:
//! Handle events from source stream //! Handle events from source stream
/*! /*!
Does the event filtering. The default simply dispatches an event Does the event filtering. The default simply dispatches an event

View File

@ -39,7 +39,15 @@ public:
data stream. Returns NULL if no socket is waiting to be accepted. data stream. Returns NULL if no socket is waiting to be accepted.
This is only valid after a call to \c bind(). This is only valid after a call to \c bind().
*/ */
virtual IDataSocket* accept() = 0; virtual IDataSocket*
accept() = 0;
//! Delete connection socket
/*!
This is used when the socket was created but not adopted by a client
proxy.
*/
virtual void deleteSocket(void*) = 0;
//@} //@}

View File

@ -43,8 +43,7 @@ public:
// IListenSocket overrides // IListenSocket overrides
virtual IDataSocket* virtual IDataSocket*
accept(); accept();
virtual void deleteSocket(void*) { }
ArchSocket& getSocket() { return m_socket; }
public: public:
ISocketMultiplexerJob* ISocketMultiplexerJob*

View File

@ -55,7 +55,7 @@ TCPSocketFactory::create(bool secure) const
m_socketMultiplexer m_socketMultiplexer
}; };
socket = static_cast<IDataSocket*>( socket = static_cast<IDataSocket*>(
ARCH->plugin().invoke(s_networkSecurity, "getSecureSocket", args)); ARCH->plugin().invoke(s_networkSecurity, "getSocket", args));
} }
else { else {
socket = new TCPSocket(m_events, m_socketMultiplexer); socket = new TCPSocket(m_events, m_socketMultiplexer);
@ -74,7 +74,7 @@ TCPSocketFactory::createListen(bool secure) const
m_socketMultiplexer m_socketMultiplexer
}; };
socket = static_cast<IListenSocket*>( socket = static_cast<IListenSocket*>(
ARCH->plugin().invoke(s_networkSecurity, "getSecureListenSocket", args)); ARCH->plugin().invoke(s_networkSecurity, "getListenSocket", args));
} }
else { else {
socket = new TCPListenSocket(m_events, m_socketMultiplexer); socket = new TCPListenSocket(m_events, m_socketMultiplexer);

View File

@ -36,6 +36,11 @@ SecureListenSocket::SecureListenSocket(
SecureListenSocket::~SecureListenSocket() SecureListenSocket::~SecureListenSocket()
{ {
SecureSocketSet::iterator it;
for (it = m_secureSocketSet.begin(); it != m_secureSocketSet.end(); it++) {
delete *it;
}
m_secureSocketSet.clear();
} }
IDataSocket* IDataSocket*
@ -47,6 +52,9 @@ SecureListenSocket::accept()
m_events, m_events,
m_socketMultiplexer, m_socketMultiplexer,
ARCH->acceptSocket(m_socket, NULL)); ARCH->acceptSocket(m_socket, NULL));
m_secureSocketSet.insert(socket);
socket->initSsl(true); socket->initSsl(true);
// TODO: customized certificate path // TODO: customized certificate path
socket->loadCertificates("C:\\Temp\\synergy.pem"); socket->loadCertificates("C:\\Temp\\synergy.pem");
@ -73,3 +81,14 @@ SecureListenSocket::accept()
throw ex; throw ex;
} }
} }
void
SecureListenSocket::deleteSocket(void* socket)
{
SecureSocketSet::iterator it;
it = m_secureSocketSet.find((IDataSocket*)socket);
if (it != m_secureSocketSet.end()) {
delete *it;
m_secureSocketSet.erase(it);
}
}

View File

@ -18,9 +18,11 @@
#pragma once #pragma once
#include "net/TCPListenSocket.h" #include "net/TCPListenSocket.h"
#include "common/stdset.h"
class IEventQueue; class IEventQueue;
class SocketMultiplexer; class SocketMultiplexer;
class IDataSocket;
class SecureListenSocket : public TCPListenSocket{ class SecureListenSocket : public TCPListenSocket{
public: public:
@ -31,4 +33,10 @@ public:
// IListenSocket overrides // IListenSocket overrides
virtual IDataSocket* virtual IDataSocket*
accept(); accept();
void deleteSocket(void*);
private:
typedef std::set<IDataSocket*> SecureSocketSet;
SecureSocketSet m_secureSocketSet;
}; };

View File

@ -68,21 +68,6 @@ SecureSocket::~SecureSocket()
delete[] m_error; delete[] m_error;
} }
void
SecureSocket::close()
{
if (m_ssl->m_ssl != NULL) {
SSL_free(m_ssl->m_ssl);
m_ssl->m_ssl = NULL;
}
if (m_ssl->m_context != NULL) {
SSL_CTX_free(m_ssl->m_context);
m_ssl->m_context = NULL;
}
TCPSocket::close();
}
void void
SecureSocket::secureConnect() SecureSocket::secureConnect()

View File

@ -42,9 +42,6 @@ public:
ArchSocket socket); ArchSocket socket);
~SecureSocket(); ~SecureSocket();
// ISocket overrides
void close();
void secureConnect(); void secureConnect();
void secureAccept(); void secureAccept();
bool isSecureReady(); bool isSecureReady();

View File

@ -59,7 +59,7 @@ invoke(const char* command, void** args)
arg2 = reinterpret_cast<SocketMultiplexer*>(args[1]); arg2 = reinterpret_cast<SocketMultiplexer*>(args[1]);
} }
if (strcmp(command, "getSecureSocket") == 0) { if (strcmp(command, "getSocket") == 0) {
if (g_secureSocket != NULL) { if (g_secureSocket != NULL) {
delete g_secureSocket; delete g_secureSocket;
} }
@ -67,17 +67,28 @@ invoke(const char* command, void** args)
g_secureSocket->initSsl(false); g_secureSocket->initSsl(false);
return g_secureSocket; return g_secureSocket;
} }
else if (strcmp(command, "getSecureListenSocket") == 0) { else if (strcmp(command, "getListenSocket") == 0) {
if (g_secureListenSocket != NULL) { if (g_secureListenSocket != NULL) {
delete g_secureListenSocket; delete g_secureListenSocket;
} }
g_secureListenSocket = new SecureListenSocket(arg1, arg2); g_secureListenSocket = new SecureListenSocket(arg1, arg2);
return g_secureListenSocket; return g_secureListenSocket;
} }
else { else if (strcmp(command, "deleteSocket") == 0) {
return NULL; if (g_secureSocket != NULL) {
delete g_secureSocket;
g_secureSocket = NULL;
} }
} }
else if (strcmp(command, "deleteListenSocket") == 0) {
if (g_secureListenSocket != NULL) {
delete g_secureListenSocket;
g_secureListenSocket = NULL;
}
}
return NULL;
}
void void
cleanup() cleanup()

View File

@ -21,6 +21,8 @@
#include "synergy/IClient.h" #include "synergy/IClient.h"
#include "base/String.h" #include "base/String.h"
namespace synergy { class IStream; }
//! Generic proxy for client or primary //! Generic proxy for client or primary
class BaseClientProxy : public IClient { class BaseClientProxy : public IClient {
public: public:
@ -82,6 +84,8 @@ public:
size_t size) = 0; size_t size) = 0;
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize) = 0; virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize) = 0;
virtual String getName() const; virtual String getName() const;
virtual synergy::IStream*
getStream() const = 0;
private: private:
String m_name; String m_name;

View File

@ -54,8 +54,8 @@ ClientListener::ClientListener(const NetworkAddress& address,
try { try {
// create listen socket // create listen socket
m_useSecureSocket = ARCH->plugin().exists(s_networkSecurity); m_useSecureNetwork = ARCH->plugin().exists(s_networkSecurity);
m_listen = m_socketFactory->createListen(m_useSecureSocket); m_listen = m_socketFactory->createListen(m_useSecureNetwork);
// bind listen address // bind listen address
LOG((CLOG_DEBUG1 "binding listen socket")); LOG((CLOG_DEBUG1 "binding listen socket"));
@ -115,6 +115,12 @@ ClientListener::setServer(Server* server)
m_server = server; m_server = server;
} }
void
ClientListener::deleteSocket(void* socket)
{
m_listen->deleteSocket(socket);
}
ClientProxy* ClientProxy*
ClientListener::getNextClient() ClientListener::getNextClient()
{ {
@ -132,13 +138,16 @@ ClientListener::handleClientConnecting(const Event&, void*)
{ {
// accept client connection // accept client connection
synergy::IStream* stream = m_listen->accept(); synergy::IStream* stream = m_listen->accept();
if (stream == NULL) { if (stream == NULL) {
return; return;
} }
LOG((CLOG_NOTE "accepted client connection")); LOG((CLOG_NOTE "accepted client connection"));
// filter socket messages, including a packetizing filter // filter socket messages, including a packetizing filter
stream = new PacketStreamFilter(m_events, stream, true); bool adopt = !m_useSecureNetwork;
stream = new PacketStreamFilter(m_events, stream, adopt);
if (m_crypto.m_mode != kDisabled) { if (m_crypto.m_mode != kDisabled) {
CryptoStream* cryptoStream = new CryptoStream( CryptoStream* cryptoStream = new CryptoStream(
@ -212,7 +221,13 @@ ClientListener::handleClientDisconnected(const Event&, void* vclient)
void void
ClientListener::cleanupListenSocket() ClientListener::cleanupListenSocket()
{ {
if (!m_useSecureSocket) { if (!m_useSecureNetwork) {
delete m_listen; delete m_listen;
} }
else {
ARCH->plugin().invoke(
s_networkSecurity,
"deleteListenSocket",
NULL);
}
} }

View File

@ -49,6 +49,8 @@ public:
//@} //@}
void deleteSocket(void* socket);
//! @name accessors //! @name accessors
//@{ //@{
@ -84,5 +86,5 @@ private:
Server* m_server; Server* m_server;
CryptoOptions m_crypto; CryptoOptions m_crypto;
IEventQueue* m_events; IEventQueue* m_events;
bool m_useSecureSocket; bool m_useSecureNetwork;
}; };

View File

@ -146,6 +146,9 @@ public:
virtual void sendDragInfo(UInt32 fileCount, const char* info, size_t size); virtual void sendDragInfo(UInt32 fileCount, const char* info, size_t size);
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize); virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize);
virtual synergy::IStream*
getStream() const { return NULL; }
private: private:
synergy::Screen* m_screen; synergy::Screen* m_screen;
bool m_clipboardDirty[kClipboardEnd]; bool m_clipboardDirty[kClipboardEnd];

View File

@ -21,6 +21,7 @@
#include "server/ClientProxy.h" #include "server/ClientProxy.h"
#include "server/ClientProxyUnknown.h" #include "server/ClientProxyUnknown.h"
#include "server/PrimaryClient.h" #include "server/PrimaryClient.h"
#include "server/ClientListener.h"
#include "synergy/IPlatformScreen.h" #include "synergy/IPlatformScreen.h"
#include "synergy/DropHelper.h" #include "synergy/DropHelper.h"
#include "synergy/option_types.h" #include "synergy/option_types.h"
@ -30,6 +31,8 @@
#include "synergy/FileChunker.h" #include "synergy/FileChunker.h"
#include "synergy/KeyState.h" #include "synergy/KeyState.h"
#include "synergy/Screen.h" #include "synergy/Screen.h"
#include "synergy/PacketStreamFilter.h"
#include "net/TCPSocket.h"
#include "net/IDataSocket.h" #include "net/IDataSocket.h"
#include "net/IListenSocket.h" #include "net/IListenSocket.h"
#include "net/XSocket.h" #include "net/XSocket.h"
@ -1358,7 +1361,11 @@ Server::handleClientDisconnected(const Event&, void* vclient)
BaseClientProxy* client = reinterpret_cast<BaseClientProxy*>(vclient); BaseClientProxy* client = reinterpret_cast<BaseClientProxy*>(vclient);
removeActiveClient(client); removeActiveClient(client);
removeOldClient(client); removeOldClient(client);
PacketStreamFilter* streamFileter = dynamic_cast<PacketStreamFilter*>(client->getStream());
TCPSocket* socket = dynamic_cast<TCPSocket*>(streamFileter->getStream());
delete client; delete client;
m_clientListener->deleteSocket(socket);
} }
void void

View File

@ -39,6 +39,7 @@ class InputFilter;
namespace synergy { class Screen; } namespace synergy { class Screen; }
class IEventQueue; class IEventQueue;
class Thread; class Thread;
class ClientListener;
//! Synergy server //! Synergy server
/*! /*!
@ -155,6 +156,9 @@ public:
//! Received dragging information from client //! Received dragging information from client
void dragInfoReceived(UInt32 fileNum, String content); void dragInfoReceived(UInt32 fileNum, String content);
//! Store ClientListener pointer
void setListener(ClientListener* p) { m_clientListener = p; }
//@} //@}
//! @name accessors //! @name accessors
//@{ //@{
@ -474,4 +478,6 @@ private:
Thread* m_getDragInfoThread; Thread* m_getDragInfoThread;
bool m_waitDragInfoThread; bool m_waitDragInfoThread;
ClientListener* m_clientListener;
}; };

View File

@ -543,6 +543,7 @@ ServerApp::startServer()
listener = openClientListener(args().m_config->getSynergyAddress()); listener = openClientListener(args().m_config->getSynergyAddress());
m_server = openServer(*args().m_config, m_primaryClient); m_server = openServer(*args().m_config, m_primaryClient);
listener->setServer(m_server); listener->setServer(m_server);
m_server->setListener(listener);
m_listener = listener; m_listener = listener;
updateStatus(); updateStatus();
LOG((CLOG_NOTE "started server, waiting for clients")); LOG((CLOG_NOTE "started server, waiting for clients"));