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_writeToDropDirThread(NULL),
m_enableDragDrop(enableDragDrop),
m_socket(NULL)
m_socket(NULL),
m_useSecureNetwork(false)
{
assert(m_socketFactory != NULL);
assert(m_screen != NULL);
@ -155,13 +156,13 @@ Client::connect()
}
// create the socket
bool useSecureSocket = ARCH->plugin().exists(s_networkSecurity);
IDataSocket* socket = m_socketFactory->create(useSecureSocket);
m_useSecureNetwork = ARCH->plugin().exists(s_networkSecurity);
IDataSocket* socket = m_socketFactory->create(m_useSecureNetwork);
m_socket = dynamic_cast<TCPSocket*>(socket);
// filter socket messages, including a packetizing filter
m_stream = socket;
bool adopt = !useSecureSocket;
bool adopt = !m_useSecureNetwork;
m_stream = new PacketStreamFilter(m_events, m_stream, adopt);
if (m_crypto.m_mode != kDisabled) {
@ -570,10 +571,14 @@ Client::cleanupTimer()
void
Client::cleanupStream()
{
bool useSecureSocket = ARCH->plugin().exists(s_networkSecurity);
if (!useSecureSocket) {
delete m_stream;
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;
bool m_enableDragDrop;
TCPSocket* m_socket;
bool m_useSecureNetwork;
};

View File

@ -49,13 +49,13 @@ public:
virtual bool isReady() const;
virtual UInt32 getSize() const;
protected:
//! Get the stream
/*!
Returns the stream passed to the c'tor.
*/
synergy::IStream* getStream() const;
protected:
//! Handle events from source stream
/*!
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.
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
virtual IDataSocket*
accept();
ArchSocket& getSocket() { return m_socket; }
virtual void deleteSocket(void*) { }
public:
ISocketMultiplexerJob*

View File

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

View File

@ -36,6 +36,11 @@ SecureListenSocket::SecureListenSocket(
SecureListenSocket::~SecureListenSocket()
{
SecureSocketSet::iterator it;
for (it = m_secureSocketSet.begin(); it != m_secureSocketSet.end(); it++) {
delete *it;
}
m_secureSocketSet.clear();
}
IDataSocket*
@ -47,6 +52,9 @@ SecureListenSocket::accept()
m_events,
m_socketMultiplexer,
ARCH->acceptSocket(m_socket, NULL));
m_secureSocketSet.insert(socket);
socket->initSsl(true);
// TODO: customized certificate path
socket->loadCertificates("C:\\Temp\\synergy.pem");
@ -73,3 +81,14 @@ SecureListenSocket::accept()
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
#include "net/TCPListenSocket.h"
#include "common/stdset.h"
class IEventQueue;
class SocketMultiplexer;
class IDataSocket;
class SecureListenSocket : public TCPListenSocket{
public:
@ -31,4 +33,10 @@ public:
// IListenSocket overrides
virtual IDataSocket*
accept();
void deleteSocket(void*);
private:
typedef std::set<IDataSocket*> SecureSocketSet;
SecureSocketSet m_secureSocketSet;
};

View File

@ -68,21 +68,6 @@ SecureSocket::~SecureSocket()
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
SecureSocket::secureConnect()

View File

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

View File

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

View File

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

View File

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

View File

@ -49,6 +49,8 @@ public:
//@}
void deleteSocket(void* socket);
//! @name accessors
//@{
@ -84,5 +86,5 @@ private:
Server* m_server;
CryptoOptions m_crypto;
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 fileChunkSending(UInt8 mark, char* data, size_t dataSize);
virtual synergy::IStream*
getStream() const { return NULL; }
private:
synergy::Screen* m_screen;
bool m_clipboardDirty[kClipboardEnd];

View File

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

View File

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

View File

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