Merge remote-tracking branch 'origin/jerry-sandbox'

This commit is contained in:
XinyuHou 2015-02-10 10:28:45 +00:00
commit 3c4b6163e3
54 changed files with 1582 additions and 221 deletions

1
.gitignore vendored
View File

@ -6,6 +6,7 @@ config.h
/ext/cryptopp562
/ext/gmock-1.6.0
/ext/gtest-1.6.0
/ext/openssl
/src/gui/Makefile*
/src/gui/object_script*
/src/gui/tmp

View File

@ -76,7 +76,7 @@ if (UNIX)
# warnings as errors:
# we have a problem with people checking in code with warnings.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -fPIC")
# For config.h, detect the libraries, functions, etc.
include(CheckIncludeFiles)
@ -174,7 +174,7 @@ if (UNIX)
CACHE STRING "" FORCE)
else()
# >= 10.6: Intel only
set(CMAKE_OSX_ARCHITECTURES "i386;x86_64"
set(CMAKE_OSX_ARCHITECTURES "i386"
CACHE STRING "" FORCE)
endif()

BIN
ext/openssl-1.0.1h.zip Normal file

Binary file not shown.

View File

@ -16,7 +16,6 @@
add_subdirectory(lib)
add_subdirectory(cmd)
add_subdirectory(plugin)
add_subdirectory(micro)
if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "IRIX")

View File

@ -23,9 +23,11 @@ add_subdirectory(ipc)
add_subdirectory(mt)
add_subdirectory(net)
add_subdirectory(platform)
add_subdirectory(plugin)
add_subdirectory(server)
add_subdirectory(synergy)
if (WIN32)
add_subdirectory(synwinhk)
endif()

View File

@ -30,6 +30,11 @@ Arch::Arch()
s_instance = this;
}
Arch::Arch(Arch* arch)
{
s_instance = arch;
}
Arch::~Arch()
{
#if SYSAPI_WIN32

View File

@ -99,6 +99,7 @@ class Arch : public ARCH_CONSOLE,
public ARCH_TIME {
public:
Arch();
Arch(Arch* arch);
virtual ~Arch();
//! Call init on other arch classes.

View File

@ -50,5 +50,5 @@ endif()
add_library(arch STATIC ${sources})
if (UNIX)
target_link_libraries(arch ${libs})
target_link_libraries(arch dl ${libs})
endif()

View File

@ -21,6 +21,8 @@
#define PLUGINS_DIR "plugins"
#include "common/IInterface.h"
#include "common/stdmap.h"
#include "base/String.h"
class IEventQueue;
@ -34,11 +36,46 @@ public:
//! @name manipulators
//@{
//! Load plugins
//!Load plugins
/*!
Scan the plugins dir and load plugins.
*/
virtual void init(void* eventTarget, IEventQueue* events) = 0;
virtual void load() = 0;
//!Unload plugins
/*!
Look through the loaded plugins and unload them.
*/
virtual void unload() = 0;
//! Init the common parts
/*!
Initializes common parts like log and arch.
*/
virtual void init(void* log, void* arch) = 0;
//! Init the event part
/*!
Initializes event parts.
*/
virtual void initEvent(void* eventTarget, IEventQueue* events) = 0;
//! Check if exists
/*!
Returns true if the plugin exists and is loaded.
*/
virtual bool exists(const char* name) = 0;
//! Invoke function
/*!
Invokes a function from the plugin.
*/
virtual void* invoke(const char* plugin,
const char* command,
void** args) = 0;
//@}
protected:
typedef std::map<String, void*> PluginTable;
};

View File

@ -18,6 +18,24 @@
#include "arch/unix/ArchPluginUnix.h"
#include "arch/unix/XArchUnix.h"
#include "base/IEventQueue.h"
#include "base/Event.h"
#include "base/Log.h"
#include <vector>
#include <sys/types.h>
#include <dirent.h>
#include <dlfcn.h>
typedef void (*initFunc)(void*, void*);
typedef int (*initEventFunc)(void (*sendEvent)(const char*, void*));
typedef void* (*invokeFunc)(const char*, void*);
typedef void (*cleanupFunc)();
void* g_eventTarget = NULL;
IEventQueue* g_events = NULL;
ArchPluginUnix::ArchPluginUnix()
{
}
@ -27,6 +45,153 @@ ArchPluginUnix::~ArchPluginUnix()
}
void
ArchPluginUnix::init(void* eventTarget, IEventQueue* events)
ArchPluginUnix::load()
{
String pluginsDir = getPluginsDir();
LOG((CLOG_DEBUG "plugins dir: %s", pluginsDir.c_str()));
struct dirent* de = NULL;
DIR* dir = NULL;
dir = opendir(pluginsDir.c_str());
if (dir == NULL) {
LOG((CLOG_DEBUG "can't open plugins dir: %s",
pluginsDir.c_str()));
return;
}
std::vector<String> plugins;
while ((de = readdir(dir)) != NULL) {
// ignore hidden files and diretories like .. and .
if (de->d_name[0] != '.') {
LOG((CLOG_DEBUG "load plugin %s", de->d_name));
plugins.push_back(de->d_name);
}
}
closedir(dir);
std::vector<String>::iterator it;
for (it = plugins.begin(); it != plugins.end(); ++it) {
LOG((CLOG_DEBUG "loading plugin: %s", (*it).c_str()));
String path = String(getPluginsDir()).append("/").append(*it);
void* library = dlopen(path.c_str(), RTLD_LAZY);
if (library == NULL) {
throw XArch(dlerror());
}
String filename = synergy::string::removeFileExt(*it);
m_pluginTable.insert(std::make_pair(filename, library));
}
}
void
ArchPluginUnix::unload()
{
PluginTable::iterator it;
for (it = m_pluginTable.begin(); it != m_pluginTable.end(); it++) {
cleanupFunc cleanup = (cleanupFunc)dlsym(it->second, "cleanup");
if (cleanup != NULL) {
cleanup();
}
else {
LOG((CLOG_DEBUG "no cleanup function in %s", it->first.c_str()));
}
LOG((CLOG_DEBUG "unloading plugin: %s", it->first.c_str()));
dlclose(it->second);
}
}
void
ArchPluginUnix::init(void* log, void* arch)
{
PluginTable::iterator it;
for (it = m_pluginTable.begin(); it != m_pluginTable.end(); it++) {
initFunc initPlugin = (initFunc)dlsym(it->second, "init");
if (initPlugin != NULL) {
initPlugin(log, arch);
}
else {
LOG((CLOG_DEBUG "no init function in %s", it->first.c_str()));
}
}
}
void
ArchPluginUnix::initEvent(void* eventTarget, IEventQueue* events)
{
g_eventTarget = eventTarget;
g_events = events;
PluginTable::iterator it;
for (it = m_pluginTable.begin(); it != m_pluginTable.end(); it++) {
initEventFunc initEventPlugin = (initEventFunc)dlsym(it->second, "initEvent");
if (initEventPlugin != NULL) {
initEventPlugin(&sendEvent);
}
else {
LOG((CLOG_DEBUG "no init event function in %s", it->first.c_str()));
}
}
}
bool
ArchPluginUnix::exists(const char* name)
{
PluginTable::iterator it;
it = m_pluginTable.find(name);
return it != m_pluginTable.end() ? true : false;
}
void*
ArchPluginUnix::invoke(
const char* plugin,
const char* command,
void** args)
{
PluginTable::iterator it;
it = m_pluginTable.find(plugin);
if (it != m_pluginTable.end()) {
invokeFunc invokePlugin = (invokeFunc)dlsym(it->second, "invoke");
void* result = NULL;
if (invokePlugin != NULL) {
result = invokePlugin(command, args);
}
else {
LOG((CLOG_DEBUG "no invoke function in %s", it->first.c_str()));
}
return result;
}
else {
LOG((CLOG_DEBUG "invoke command failed, plugin: %s command: %s",
plugin, command));
return NULL;
}
}
String
ArchPluginUnix::getPluginsDir()
{
#if WINAPI_XWINDOWS
return "/usr/lib/synergy/plugin";
#else
// TODO: pluging should be in bundle in the final release
return "/Users/xinyu/Projects/synergy/bin/plugins";
#endif
}
void
sendEvent(const char* eventName, void* data)
{
LOG((CLOG_DEBUG5 "plugin sending event"));
Event::Type type = g_events->getRegisteredType(eventName);
g_events->addEvent(Event(type, g_eventTarget, data));
}
void
log(const char* text)
{
LOG((CLOG_DEBUG "plugin: %s", text));
}

View File

@ -31,5 +31,21 @@ public:
virtual ~ArchPluginUnix();
// IArchPlugin overrides
void init(void* eventTarget, IEventQueue* events);
void load();
void unload();
void init(void* log, void* arch);
void initEvent(void* eventTarget, IEventQueue* events);
bool exists(const char* name);
virtual void* invoke(const char* pluginName,
const char* functionName,
void** args);
private:
String getPluginsDir();
private:
PluginTable m_pluginTable;
};
void sendEvent(const char* text, void* data);
void log(const char* text);

View File

@ -27,7 +27,10 @@
#include <Windows.h>
#include <iostream>
typedef int (*initFunc)(void (*sendEvent)(const char*, void*), void (*log)(const char*));
typedef void (*initFunc)(void*, void*);
typedef int (*initEventFunc)(void (*sendEvent)(const char*, void*));
typedef void* (*invokeFunc)(const char*, void**);
typedef void (*cleanupFunc)();
void* g_eventTarget = NULL;
IEventQueue* g_events = NULL;
@ -41,11 +44,8 @@ ArchPluginWindows::~ArchPluginWindows()
}
void
ArchPluginWindows::init(void* eventTarget, IEventQueue* events)
ArchPluginWindows::load()
{
g_eventTarget = eventTarget;
g_events = events;
String dir = getPluginsDir();
LOG((CLOG_DEBUG "plugins dir: %s", dir.c_str()));
@ -54,21 +54,113 @@ ArchPluginWindows::init(void* eventTarget, IEventQueue* events)
getFilenames(pattern, plugins);
std::vector<String>::iterator it;
for (it = plugins.begin(); it != plugins.end(); ++it)
load(*it);
for (it = plugins.begin(); it != plugins.end(); ++it) {
LOG((CLOG_DEBUG "loading plugin: %s", (*it).c_str()));
String path = String(getPluginsDir()).append("\\").append(*it);
HINSTANCE library = LoadLibrary(path.c_str());
if (library == NULL) {
throw XArch(new XArchEvalWindows);
}
void* lib = reinterpret_cast<void*>(library);
String filename = synergy::string::removeFileExt(*it);
m_pluginTable.insert(std::make_pair(filename, lib));
}
}
void
ArchPluginWindows::load(const String& dllFilename)
ArchPluginWindows::unload()
{
LOG((CLOG_DEBUG "loading plugin: %s", dllFilename.c_str()));
String path = String(getPluginsDir()).append("\\").append(dllFilename);
HINSTANCE library = LoadLibrary(path.c_str());
if (library == NULL)
throw XArch(new XArchEvalWindows);
PluginTable::iterator it;
HINSTANCE lib;
for (it = m_pluginTable.begin(); it != m_pluginTable.end(); it++) {
lib = reinterpret_cast<HINSTANCE>(it->second);
cleanupFunc cleanup = (cleanupFunc)GetProcAddress(lib, "cleanup");
if (cleanup != NULL) {
cleanup();
}
else {
LOG((CLOG_DEBUG "no cleanup function in %s", it->first.c_str()));
}
initFunc initPlugin = (initFunc)GetProcAddress(library, "init");
initPlugin(&sendEvent, &log);
LOG((CLOG_DEBUG "unloading plugin: %s", it->first.c_str()));
FreeLibrary(lib);
}
}
void
ArchPluginWindows::init(void* log, void* arch)
{
PluginTable::iterator it;
HINSTANCE lib;
for (it = m_pluginTable.begin(); it != m_pluginTable.end(); it++) {
lib = reinterpret_cast<HINSTANCE>(it->second);
initFunc initPlugin = (initFunc)GetProcAddress(lib, "init");
if (initPlugin != NULL) {
initPlugin(log, arch);
}
else {
LOG((CLOG_DEBUG "no init function in %s", it->first.c_str()));
}
}
}
void
ArchPluginWindows::initEvent(void* eventTarget, IEventQueue* events)
{
g_eventTarget = eventTarget;
g_events = events;
PluginTable::iterator it;
HINSTANCE lib;
for (it = m_pluginTable.begin(); it != m_pluginTable.end(); it++) {
lib = reinterpret_cast<HINSTANCE>(it->second);
initEventFunc initEventPlugin = (initEventFunc)GetProcAddress(lib, "initEvent");
if (initEventPlugin != NULL) {
initEventPlugin(&sendEvent);
}
else {
LOG((CLOG_DEBUG "no init event function in %s", it->first.c_str()));
}
}
}
bool
ArchPluginWindows::exists(const char* name)
{
PluginTable::iterator it;
it = m_pluginTable.find(name);
return it != m_pluginTable.end() ? true : false;
}
void*
ArchPluginWindows::invoke(
const char* plugin,
const char* command,
void** args)
{
PluginTable::iterator it;
it = m_pluginTable.find(plugin);
if (it != m_pluginTable.end()) {
HINSTANCE lib = reinterpret_cast<HINSTANCE>(it->second);
invokeFunc invokePlugin = (invokeFunc)GetProcAddress(lib, "invoke");
void* result = NULL;
if (invokePlugin != NULL) {
result = invokePlugin(command, args);
}
else {
LOG((CLOG_DEBUG "no invoke function in %s", it->first.c_str()));
}
return result;
}
else {
LOG((CLOG_DEBUG "invoke command failed, plugin: %s command: %s",
plugin, command));
return NULL;
}
}
String

View File

@ -19,7 +19,6 @@
#pragma once
#include "arch/IArchPlugin.h"
#include "base/String.h"
#include <vector>
@ -35,13 +34,22 @@ public:
virtual ~ArchPluginWindows();
// IArchPlugin overrides
void init(void* eventTarget, IEventQueue* events);
void load();
void unload();
void init(void* log, void* arch);
void initEvent(void* eventTarget, IEventQueue* events);
bool exists(const char* name);
void* invoke(const char* pluginName,
const char* functionName,
void** args);
private:
String getModuleDir();
void getFilenames(const String& pattern, std::vector<String>& filenames);
void load(const String& dllPath);
String getPluginsDir();
private:
PluginTable m_pluginTable;
};
void sendEvent(const char* text, void* data);

View File

@ -74,6 +74,11 @@ Log::Log()
s_log = this;
}
Log::Log(Log* src)
{
s_log = src;
}
Log::~Log()
{
// clean up

View File

@ -41,6 +41,7 @@ LOGC() provide convenient access.
class Log {
public:
Log();
Log(Log* src);
~Log();
//! @name manipulators

View File

@ -168,6 +168,17 @@ findReplaceAll(
}
}
String
removeFileExt(String filename)
{
size_t dot = filename.find_last_of('.');
if (dot == String::npos) {
return filename;
}
return filename.substr(0, dot);
}
//
// CaselessCmp

View File

@ -64,6 +64,12 @@ Finds \c find inside \c subject and replaces it with \c replace
*/
void findReplaceAll(String& subject, const String& find, const String& replace);
//! Remove file extension
/*!
Finds the last dot and remove all characters from the dot to the end
*/
String removeFileExt(String filename);
//! Case-insensitive comparisons
/*!
This class provides case-insensitve comparison functions.

View File

@ -18,6 +18,7 @@
#include "client/Client.h"
#include "../plugin/ns/SecureSocket.h"
#include "client/ServerProxy.h"
#include "synergy/Screen.h"
#include "synergy/Clipboard.h"
@ -29,8 +30,8 @@
#include "synergy/FileChunker.h"
#include "synergy/IPlatformScreen.h"
#include "mt/Thread.h"
#include "io/IStreamFilterFactory.h"
#include "io/CryptoStream.h"
#include "net/TCPSocket.h"
#include "net/IDataSocket.h"
#include "net/ISocketFactory.h"
#include "arch/Arch.h"
@ -45,6 +46,12 @@
#include <sstream>
#include <fstream>
#if defined _WIN32
static const char s_networkSecurity[] = { "ns" };
#else
static const char s_networkSecurity[] = { "libns" };
#endif
//
// Client
//
@ -53,7 +60,6 @@ Client::Client(
IEventQueue* events,
const String& name, const NetworkAddress& address,
ISocketFactory* socketFactory,
IStreamFilterFactory* streamFilterFactory,
synergy::Screen* screen,
const CryptoOptions& crypto,
bool enableDragDrop) :
@ -61,7 +67,6 @@ Client::Client(
m_name(name),
m_serverAddress(address),
m_socketFactory(socketFactory),
m_streamFilterFactory(streamFilterFactory),
m_screen(screen),
m_stream(NULL),
m_timer(NULL),
@ -75,7 +80,9 @@ Client::Client(
m_crypto(crypto),
m_sendFileThread(NULL),
m_writeToDropDirThread(NULL),
m_enableDragDrop(enableDragDrop)
m_enableDragDrop(enableDragDrop),
m_socket(NULL),
m_useSecureNetwork(false)
{
assert(m_socketFactory != NULL);
assert(m_screen != NULL);
@ -118,7 +125,6 @@ Client::~Client()
cleanupConnecting();
cleanupConnection();
delete m_socketFactory;
delete m_streamFilterFactory;
}
void
@ -150,14 +156,14 @@ Client::connect()
}
// create the socket
IDataSocket* socket = m_socketFactory->create();
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;
if (m_streamFilterFactory != NULL) {
m_stream = m_streamFilterFactory->create(m_stream, true);
}
m_stream = new PacketStreamFilter(m_events, m_stream, true);
bool adopt = !m_useSecureNetwork;
m_stream = new PacketStreamFilter(m_events, m_stream, adopt);
if (m_crypto.m_mode != kDisabled) {
m_cryptoStream = new CryptoStream(
@ -174,8 +180,7 @@ Client::connect()
catch (XBase& e) {
cleanupTimer();
cleanupConnecting();
delete m_stream;
m_stream = NULL;
cleanupStream();
LOG((CLOG_DEBUG1 "connection failed"));
sendConnectionFailedEvent(e.what());
return;
@ -532,8 +537,7 @@ Client::cleanupConnection()
m_stream->getEventTarget());
m_events->removeHandler(m_events->forISocket().disconnected(),
m_stream->getEventTarget());
delete m_stream;
m_stream = NULL;
cleanupStream();
}
}
@ -564,6 +568,20 @@ Client::cleanupTimer()
}
}
void
Client::cleanupStream()
{
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);
}
}
void
Client::handleConnected(const Event&, void*)
{
@ -577,6 +595,8 @@ Client::handleConnected(const Event&, void*)
m_sentClipboard[id] = false;
m_timeClipboard[id] = 0;
}
m_socket->secureConnect();
}
void
@ -587,8 +607,7 @@ Client::handleConnectionFailed(const Event& event, void*)
cleanupTimer();
cleanupConnecting();
delete m_stream;
m_stream = NULL;
cleanupStream();
LOG((CLOG_DEBUG1 "connection failed"));
sendConnectionFailedEvent(info->m_what.c_str());
delete info;
@ -600,8 +619,7 @@ Client::handleConnectTimeout(const Event&, void*)
cleanupTimer();
cleanupConnecting();
cleanupConnection();
delete m_stream;
m_stream = NULL;
cleanupStream();
LOG((CLOG_DEBUG1 "connection timed out"));
sendConnectionFailedEvent("Timed out");
}

View File

@ -33,10 +33,10 @@ class ServerProxy;
class IDataSocket;
class ISocketFactory;
namespace synergy { class IStream; }
class IStreamFilterFactory;
class IEventQueue;
class CryptoStream;
class Thread;
class TCPSocket;
//! Synergy client
/*!
@ -60,7 +60,6 @@ public:
Client(IEventQueue* events,
const String& name, const NetworkAddress& address,
ISocketFactory* socketFactory,
IStreamFilterFactory* streamFilterFactory,
synergy::Screen* screen,
const CryptoOptions& crypto,
bool enableDragDrop);
@ -189,6 +188,7 @@ private:
void cleanupConnection();
void cleanupScreen();
void cleanupTimer();
void cleanupStream();
void handleConnected(const Event&, void*);
void handleConnectionFailed(const Event&, void*);
void handleConnectTimeout(const Event&, void*);
@ -204,33 +204,34 @@ private:
void onFileRecieveCompleted();
public:
bool m_mock;
bool m_mock;
private:
String m_name;
NetworkAddress m_serverAddress;
ISocketFactory* m_socketFactory;
IStreamFilterFactory* m_streamFilterFactory;
synergy::Screen* m_screen;
synergy::IStream* m_stream;
EventQueueTimer* m_timer;
ServerProxy* m_server;
bool m_ready;
bool m_active;
bool m_suspended;
bool m_connectOnResume;
bool m_ownClipboard[kClipboardEnd];
bool m_sentClipboard[kClipboardEnd];
IClipboard::Time m_timeClipboard[kClipboardEnd];
String m_dataClipboard[kClipboardEnd];
IEventQueue* m_events;
CryptoStream* m_cryptoStream;
CryptoOptions m_crypto;
std::size_t m_expectedFileSize;
String m_receivedFileData;
DragFileList m_dragFileList;
String m_dragFileExt;
String m_name;
NetworkAddress m_serverAddress;
ISocketFactory* m_socketFactory;
synergy::Screen* m_screen;
synergy::IStream* m_stream;
EventQueueTimer* m_timer;
ServerProxy* m_server;
bool m_ready;
bool m_active;
bool m_suspended;
bool m_connectOnResume;
bool m_ownClipboard[kClipboardEnd];
bool m_sentClipboard[kClipboardEnd];
IClipboard::Time m_timeClipboard[kClipboardEnd];
String m_dataClipboard[kClipboardEnd];
IEventQueue* m_events;
CryptoStream* m_cryptoStream;
CryptoOptions m_crypto;
std::size_t m_expectedFileSize;
String m_receivedFileData;
DragFileList m_dragFileList;
String m_dragFileExt;
Thread* m_sendFileThread;
Thread* m_writeToDropDirThread;
bool m_enableDragDrop;
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

@ -58,7 +58,7 @@ private:
private:
NetworkAddress m_serverAddress;
CTCPSocket m_socket;
TCPSocket m_socket;
IpcServerProxy* m_server;
IEventQueue* m_events;
};

View File

@ -18,6 +18,7 @@
#include "mt/Thread.h"
#include "net/XSocket.h"
#include "mt/XMT.h"
#include "mt/XThread.h"
#include "arch/Arch.h"
@ -158,6 +159,10 @@ Thread::threadFunc(void* vjob)
LOG((CLOG_DEBUG1 "thread 0x%08x exit", id));
}
catch (XSocket& e) {
// client called cancel()
LOG((CLOG_DEBUG "%s", e.what()));
}
catch (XThreadCancel&) {
// client called cancel()
LOG((CLOG_DEBUG1 "caught cancel on thread 0x%08x", id));

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

@ -34,10 +34,10 @@ public:
//@{
//! Create data socket
virtual IDataSocket* create() const = 0;
virtual IDataSocket* create(bool secure) const = 0;
//! Create listen socket
virtual IListenSocket* createListen() const = 0;
virtual IListenSocket* createListen(bool secure) const = 0;
//@}
};

View File

@ -96,15 +96,16 @@ private:
private:
Mutex* m_mutex;
Thread* m_thread;
Thread* m_thread;
bool m_update;
CondVar<bool>* m_jobsReady;
CondVar<bool>* m_jobListLock;
CondVar<bool>* m_jobListLockLocked;
Thread* m_jobListLocker;
Thread* m_jobListLockLocker;
Thread* m_jobListLocker;
Thread* m_jobListLockLocker;
SocketJobs m_socketJobs;
SocketJobMap m_socketJobMap;
ISocketMultiplexerJob* m_cursorMark;
ISocketMultiplexerJob*
m_cursorMark;
};

View File

@ -110,7 +110,7 @@ TCPListenSocket::accept()
{
IDataSocket* socket = NULL;
try {
socket = new CTCPSocket(m_events, m_socketMultiplexer, ARCH->acceptSocket(m_socket, NULL));
socket = new TCPSocket(m_events, m_socketMultiplexer, ARCH->acceptSocket(m_socket, NULL));
if (socket != NULL) {
m_socketMultiplexer->addSocket(this,
new TSocketMultiplexerMethodJob<TCPListenSocket>(

View File

@ -33,7 +33,7 @@ A listen socket using TCP.
class TCPListenSocket : public IListenSocket {
public:
TCPListenSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer);
~TCPListenSocket();
virtual ~TCPListenSocket();
// ISocket overrides
virtual void bind(const NetworkAddress&);
@ -41,16 +41,18 @@ public:
virtual void* getEventTarget() const;
// IListenSocket overrides
virtual IDataSocket* accept();
virtual IDataSocket*
accept();
virtual void deleteSocket(void*) { }
private:
public:
ISocketMultiplexerJob*
serviceListening(ISocketMultiplexerJob*,
bool, bool, bool);
private:
protected:
ArchSocket m_socket;
Mutex* m_mutex;
IEventQueue* m_events;
SocketMultiplexer* m_socketMultiplexer;
SocketMultiplexer* m_socketMultiplexer;
};

View File

@ -34,10 +34,10 @@
#include <memory>
//
// CTCPSocket
// TCPSocket
//
CTCPSocket::CTCPSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer) :
TCPSocket::TCPSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer) :
IDataSocket(events),
m_mutex(),
m_flushed(&m_mutex, true),
@ -54,7 +54,7 @@ CTCPSocket::CTCPSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer
init();
}
CTCPSocket::CTCPSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer, ArchSocket socket) :
TCPSocket::TCPSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer, ArchSocket socket) :
IDataSocket(events),
m_mutex(),
m_socket(socket),
@ -70,7 +70,7 @@ CTCPSocket::CTCPSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer
setJob(newJob());
}
CTCPSocket::~CTCPSocket()
TCPSocket::~TCPSocket()
{
try {
close();
@ -81,7 +81,7 @@ CTCPSocket::~CTCPSocket()
}
void
CTCPSocket::bind(const NetworkAddress& addr)
TCPSocket::bind(const NetworkAddress& addr)
{
try {
ARCH->bindSocket(m_socket, addr.getAddress());
@ -95,7 +95,7 @@ CTCPSocket::bind(const NetworkAddress& addr)
}
void
CTCPSocket::close()
TCPSocket::close()
{
// remove ourself from the multiplexer
setJob(NULL);
@ -123,13 +123,13 @@ CTCPSocket::close()
}
void*
CTCPSocket::getEventTarget() const
TCPSocket::getEventTarget() const
{
return const_cast<void*>(reinterpret_cast<const void*>(this));
}
UInt32
CTCPSocket::read(void* buffer, UInt32 n)
TCPSocket::read(void* buffer, UInt32 n)
{
// copy data directly from our input buffer
Lock lock(&m_mutex);
@ -152,7 +152,7 @@ CTCPSocket::read(void* buffer, UInt32 n)
}
void
CTCPSocket::write(const void* buffer, UInt32 n)
TCPSocket::write(const void* buffer, UInt32 n)
{
bool wasEmpty;
{
@ -184,7 +184,7 @@ CTCPSocket::write(const void* buffer, UInt32 n)
}
void
CTCPSocket::flush()
TCPSocket::flush()
{
Lock lock(&m_mutex);
while (m_flushed == false) {
@ -193,7 +193,7 @@ CTCPSocket::flush()
}
void
CTCPSocket::shutdownInput()
TCPSocket::shutdownInput()
{
bool useNewJob = false;
{
@ -220,7 +220,7 @@ CTCPSocket::shutdownInput()
}
void
CTCPSocket::shutdownOutput()
TCPSocket::shutdownOutput()
{
bool useNewJob = false;
{
@ -247,21 +247,21 @@ CTCPSocket::shutdownOutput()
}
bool
CTCPSocket::isReady() const
TCPSocket::isReady() const
{
Lock lock(&m_mutex);
return (m_inputBuffer.getSize() > 0);
}
UInt32
CTCPSocket::getSize() const
TCPSocket::getSize() const
{
Lock lock(&m_mutex);
return m_inputBuffer.getSize();
}
void
CTCPSocket::connect(const NetworkAddress& addr)
TCPSocket::connect(const NetworkAddress& addr)
{
{
Lock lock(&m_mutex);
@ -290,7 +290,7 @@ CTCPSocket::connect(const NetworkAddress& addr)
}
void
CTCPSocket::init()
TCPSocket::init()
{
// default state
m_connected = false;
@ -316,7 +316,7 @@ CTCPSocket::init()
}
void
CTCPSocket::setJob(ISocketMultiplexerJob* job)
TCPSocket::setJob(ISocketMultiplexerJob* job)
{
// multiplexer will delete the old job
if (job == NULL) {
@ -328,7 +328,7 @@ CTCPSocket::setJob(ISocketMultiplexerJob* job)
}
ISocketMultiplexerJob*
CTCPSocket::newJob()
TCPSocket::newJob()
{
// note -- must have m_mutex locked on entry
@ -340,23 +340,23 @@ CTCPSocket::newJob()
if (!(m_readable || m_writable)) {
return NULL;
}
return new TSocketMultiplexerMethodJob<CTCPSocket>(
this, &CTCPSocket::serviceConnecting,
return new TSocketMultiplexerMethodJob<TCPSocket>(
this, &TCPSocket::serviceConnecting,
m_socket, m_readable, m_writable);
}
else {
if (!(m_readable || (m_writable && (m_outputBuffer.getSize() > 0)))) {
return NULL;
}
return new TSocketMultiplexerMethodJob<CTCPSocket>(
this, &CTCPSocket::serviceConnected,
return new TSocketMultiplexerMethodJob<TCPSocket>(
this, &TCPSocket::serviceConnected,
m_socket, m_readable,
m_writable && (m_outputBuffer.getSize() > 0));
}
}
void
CTCPSocket::sendConnectionFailedEvent(const char* msg)
TCPSocket::sendConnectionFailedEvent(const char* msg)
{
ConnectionFailedInfo* info = new ConnectionFailedInfo(msg);
m_events->addEvent(Event(m_events->forIDataSocket().connectionFailed(),
@ -364,13 +364,13 @@ CTCPSocket::sendConnectionFailedEvent(const char* msg)
}
void
CTCPSocket::sendEvent(Event::Type type)
TCPSocket::sendEvent(Event::Type type)
{
m_events->addEvent(Event(type, getEventTarget(), NULL));
}
void
CTCPSocket::onConnected()
TCPSocket::onConnected()
{
m_connected = true;
m_readable = true;
@ -378,14 +378,14 @@ CTCPSocket::onConnected()
}
void
CTCPSocket::onInputShutdown()
TCPSocket::onInputShutdown()
{
m_inputBuffer.pop(m_inputBuffer.getSize());
m_readable = false;
}
void
CTCPSocket::onOutputShutdown()
TCPSocket::onOutputShutdown()
{
m_outputBuffer.pop(m_outputBuffer.getSize());
m_writable = false;
@ -396,7 +396,7 @@ CTCPSocket::onOutputShutdown()
}
void
CTCPSocket::onDisconnected()
TCPSocket::onDisconnected()
{
// disconnected
onInputShutdown();
@ -405,7 +405,7 @@ CTCPSocket::onDisconnected()
}
ISocketMultiplexerJob*
CTCPSocket::serviceConnecting(ISocketMultiplexerJob* job,
TCPSocket::serviceConnecting(ISocketMultiplexerJob* job,
bool, bool write, bool error)
{
Lock lock(&m_mutex);
@ -449,7 +449,7 @@ CTCPSocket::serviceConnecting(ISocketMultiplexerJob* job,
}
ISocketMultiplexerJob*
CTCPSocket::serviceConnected(ISocketMultiplexerJob* job,
TCPSocket::serviceConnected(ISocketMultiplexerJob* job,
bool read, bool write, bool error)
{
Lock lock(&m_mutex);
@ -467,7 +467,17 @@ CTCPSocket::serviceConnected(ISocketMultiplexerJob* job,
// write data
UInt32 n = m_outputBuffer.getSize();
const void* buffer = m_outputBuffer.peek(n);
n = (UInt32)ARCH->writeSocket(m_socket, buffer, n);
if (isSecure()) {
if (isSecureReady()) {
n = secureWrite(buffer, n);
}
else {
return job;
}
}
else {
n = (UInt32)ARCH->writeSocket(m_socket, buffer, n);
}
// discard written data
if (n > 0) {
@ -510,14 +520,34 @@ CTCPSocket::serviceConnected(ISocketMultiplexerJob* job,
if (read && m_readable) {
try {
UInt8 buffer[4096];
size_t n = ARCH->readSocket(m_socket, buffer, sizeof(buffer));
size_t n = 0;
if (isSecure()) {
if (isSecureReady()) {
n = secureRead(buffer, sizeof(buffer));
}
else {
return job;
}
}
else {
n = ARCH->readSocket(m_socket, buffer, sizeof(buffer));
}
if (n > 0) {
bool wasEmpty = (m_inputBuffer.getSize() == 0);
// slurp up as much as possible
do {
m_inputBuffer.write(buffer, (UInt32)n);
n = ARCH->readSocket(m_socket, buffer, sizeof(buffer));
if (isSecure() && isSecureReady()) {
n = secureRead(buffer, sizeof(buffer));
}
else {
n = ARCH->readSocket(m_socket, buffer, sizeof(buffer));
}
} while (n > 0);
// send input ready if input buffer was empty

View File

@ -34,11 +34,11 @@ class SocketMultiplexer;
/*!
A data socket using TCP.
*/
class CTCPSocket : public IDataSocket {
class TCPSocket : public IDataSocket {
public:
CTCPSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer);
CTCPSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer, ArchSocket socket);
~CTCPSocket();
TCPSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer);
TCPSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer, ArchSocket socket);
virtual ~TCPSocket();
// ISocket overrides
virtual void bind(const NetworkAddress&);
@ -57,14 +57,31 @@ public:
// IDataSocket overrides
virtual void connect(const NetworkAddress&);
virtual void secureConnect() {}
virtual void secureAccept() {}
protected:
ArchSocket getSocket() { return m_socket; }
IEventQueue* getEvents() { return m_events; }
virtual bool isSecureReady() { return false; }
virtual bool isSecure() { return false; }
virtual UInt32 secureRead(void* buffer, UInt32) { return 0; }
virtual UInt32 secureWrite(const void*, UInt32) { return 0; }
void setJob(ISocketMultiplexerJob*);
ISocketMultiplexerJob*
newJob();
bool isReadable() { return m_readable; }
bool isWritable() { return m_writable; }
Mutex& getMutex() { return m_mutex; }
void sendEvent(Event::Type);
private:
void init();
void setJob(ISocketMultiplexerJob*);
ISocketMultiplexerJob* newJob();
void sendConnectionFailedEvent(const char*);
void sendEvent(Event::Type);
void onConnected();
void onInputShutdown();
void onOutputShutdown();
@ -87,5 +104,5 @@ private:
bool m_readable;
bool m_writable;
IEventQueue* m_events;
SocketMultiplexer* m_socketMultiplexer;
SocketMultiplexer* m_socketMultiplexer;
};

View File

@ -20,31 +20,65 @@
#include "net/TCPSocket.h"
#include "net/TCPListenSocket.h"
#include "arch/Arch.h"
#include "base/Log.h"
//
// CTCPSocketFactory
// TCPSocketFactory
//
CTCPSocketFactory::CTCPSocketFactory(IEventQueue* events, SocketMultiplexer* socketMultiplexer) :
#if defined _WIN32
static const char s_networkSecurity[] = { "ns" };
#else
static const char s_networkSecurity[] = { "libns" };
#endif
TCPSocketFactory::TCPSocketFactory(IEventQueue* events, SocketMultiplexer* socketMultiplexer) :
m_events(events),
m_socketMultiplexer(socketMultiplexer)
{
// do nothing
}
CTCPSocketFactory::~CTCPSocketFactory()
TCPSocketFactory::~TCPSocketFactory()
{
// do nothing
}
IDataSocket*
CTCPSocketFactory::create() const
TCPSocketFactory::create(bool secure) const
{
return new CTCPSocket(m_events, m_socketMultiplexer);
IDataSocket* socket = NULL;
if (secure) {
void* args[2] = {
m_events,
m_socketMultiplexer
};
socket = static_cast<IDataSocket*>(
ARCH->plugin().invoke(s_networkSecurity, "getSocket", args));
}
else {
socket = new TCPSocket(m_events, m_socketMultiplexer);
}
return socket;
}
IListenSocket*
CTCPSocketFactory::createListen() const
TCPSocketFactory::createListen(bool secure) const
{
return new TCPListenSocket(m_events, m_socketMultiplexer);
IListenSocket* socket = NULL;
if (secure) {
void* args[2] = {
m_events,
m_socketMultiplexer
};
socket = static_cast<IListenSocket*>(
ARCH->plugin().invoke(s_networkSecurity, "getListenSocket", args));
}
else {
socket = new TCPListenSocket(m_events, m_socketMultiplexer);
}
return socket;
}

View File

@ -24,16 +24,18 @@ class IEventQueue;
class SocketMultiplexer;
//! Socket factory for TCP sockets
class CTCPSocketFactory : public ISocketFactory {
class TCPSocketFactory : public ISocketFactory {
public:
CTCPSocketFactory(IEventQueue* events, SocketMultiplexer* socketMultiplexer);
virtual ~CTCPSocketFactory();
TCPSocketFactory(IEventQueue* events, SocketMultiplexer* socketMultiplexer);
virtual ~TCPSocketFactory();
// ISocketFactory overrides
virtual IDataSocket* create() const;
virtual IListenSocket* createListen() const;
virtual IDataSocket*
create(bool secure) const;
virtual IListenSocket*
createListen(bool secure) const;
private:
IEventQueue* m_events;
SocketMultiplexer* m_socketMultiplexer;
SocketMultiplexer* m_socketMultiplexer;
};

View File

@ -14,6 +14,8 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
add_subdirectory(ns)
if (WIN32)
add_subdirectory(winmmjoy)
endif()

View File

@ -0,0 +1,93 @@
# synergy -- mouse and keyboard sharing utility
# Copyright (C) 2015 Synergy Si Ltd.
#
# This package is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# found in the file COPYING that should have accompanied this file.
#
# This package is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
file(GLOB headers "*.h")
file(GLOB sources "*.cpp")
if (SYNERGY_ADD_HEADERS)
list(APPEND sources ${headers})
endif()
if (WIN32)
set(OPENSSL_INCLUDE ../../../../ext/openssl/inc32)
endif()
if (APPLE)
set(OPENSSL_INCLUDE ../../../../ext/openssl/include)
endif()
include_directories(
../../../lib/
../../../..
${OPENSSL_INCLUDE}
)
add_library(ns SHARED ${sources})
if (WIN32)
set(OPENSSL_LIBS
${CMAKE_SOURCE_DIR}/ext/openssl/out32dll/libeay32.lib
${CMAKE_SOURCE_DIR}/ext/openssl/out32dll/ssleay32.lib
)
endif()
if (UNIX)
if (APPLE)
set(OPENSSL_LIBS
${CMAKE_SOURCE_DIR}/ext/openssl/libssl.a
${CMAKE_SOURCE_DIR}/ext/openssl/libcrypto.a
)
else()
set(OPENSSL_LIBS ssl crypto)
endif()
endif()
target_link_libraries(ns
arch base client common io mt net ipc platform server synergy cryptopp ${libs} ${OPENSSL_LIBS})
if (WIN32)
add_custom_command(
TARGET ns
POST_BUILD
COMMAND xcopy /Y /Q
..\\..\\..\\..\\..\\lib\\${CMAKE_CFG_INTDIR}\\ns.dll
..\\..\\..\\..\\..\\bin\\${CMAKE_CFG_INTDIR}\\plugins\\
)
else()
if (APPLE)
add_custom_command(
TARGET ns
POST_BUILD
COMMAND
mkdir -p
${CMAKE_SOURCE_DIR}/bin/plugins
&&
cp
${CMAKE_SOURCE_DIR}/lib/${CMAKE_CFG_INTDIR}/libns.dylib
${CMAKE_SOURCE_DIR}/bin/plugins/
)
else()
add_custom_command(
TARGET ns
POST_BUILD
COMMAND mkdir -p
${CMAKE_SOURCE_DIR}/bin/plugins
&&
cp
${CMAKE_SOURCE_DIR}/lib/libns.so
${CMAKE_SOURCE_DIR}/bin/plugins/
)
endif()
endif()

View File

@ -0,0 +1,94 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2015 Synergy Si Ltd.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file COPYING that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "SecureListenSocket.h"
#include "SecureSocket.h"
#include "net/NetworkAddress.h"
#include "net/SocketMultiplexer.h"
#include "net/TSocketMultiplexerMethodJob.h"
#include "arch/XArch.h"
//
// SecureListenSocket
//
SecureListenSocket::SecureListenSocket(
IEventQueue* events,
SocketMultiplexer* socketMultiplexer) :
TCPListenSocket(events, socketMultiplexer)
{
}
SecureListenSocket::~SecureListenSocket()
{
SecureSocketSet::iterator it;
for (it = m_secureSocketSet.begin(); it != m_secureSocketSet.end(); it++) {
delete *it;
}
m_secureSocketSet.clear();
}
IDataSocket*
SecureListenSocket::accept()
{
SecureSocket* socket = NULL;
try {
socket = new SecureSocket(
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");
socket->secureAccept();
if (socket != NULL) {
m_socketMultiplexer->addSocket(this,
new TSocketMultiplexerMethodJob<TCPListenSocket>(
this, &TCPListenSocket::serviceListening,
m_socket, true, false));
}
return dynamic_cast<IDataSocket*>(socket);
}
catch (XArchNetwork&) {
if (socket != NULL) {
delete socket;
}
return NULL;
}
catch (std::exception &ex) {
if (socket != NULL) {
delete socket;
}
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

@ -1,7 +1,6 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2012 Synergy Si Ltd.
* Copyright (C) 2002 Chris Schoeneman
* Copyright (C) 2015 Synergy Si Ltd.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -18,21 +17,26 @@
#pragma once
#include "common/IInterface.h"
#include "net/TCPListenSocket.h"
#include "common/stdset.h"
namespace synergy { class IStream; }
class IEventQueue;
class SocketMultiplexer;
class IDataSocket;
//! Stream filter factory interface
/*!
This interface provides factory methods to create stream filters.
*/
class IStreamFilterFactory : public IInterface {
class SecureListenSocket : public TCPListenSocket{
public:
//! Create filter
/*!
Create and return a stream filter on \p stream. The caller must
delete the returned object.
*/
virtual synergy::IStream*
create(synergy::IStream* stream, bool adoptStream) = 0;
SecureListenSocket(IEventQueue* events,
SocketMultiplexer* socketMultiplexer);
~SecureListenSocket();
// IListenSocket overrides
virtual IDataSocket*
accept();
void deleteSocket(void*);
private:
typedef std::set<IDataSocket*> SecureSocketSet;
SecureSocketSet m_secureSocketSet;
};

View File

@ -0,0 +1,390 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2015 Synergy Si Ltd.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file COPYING that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "SecureSocket.h"
#include "net/TSocketMultiplexerMethodJob.h"
#include "net/TCPSocket.h"
#include "mt/Lock.h"
#include "arch/XArch.h"
#include "base/Log.h"
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <cstring>
#include <cstdlib>
#include <memory>
//
// SecureSocket
//
#define MAX_ERROR_SIZE 65535
struct Ssl {
SSL_CTX* m_context;
SSL* m_ssl;
};
SecureSocket::SecureSocket(
IEventQueue* events,
SocketMultiplexer* socketMultiplexer) :
TCPSocket(events, socketMultiplexer),
m_secureReady(false)
{
}
SecureSocket::SecureSocket(
IEventQueue* events,
SocketMultiplexer* socketMultiplexer,
ArchSocket socket) :
TCPSocket(events, socketMultiplexer, socket),
m_secureReady(false)
{
}
SecureSocket::~SecureSocket()
{
if (m_ssl->m_ssl != NULL) {
SSL_shutdown(m_ssl->m_ssl);
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;
}
delete m_ssl;
delete[] m_error;
}
void
SecureSocket::close()
{
SSL_shutdown(m_ssl->m_ssl);
TCPSocket::close();
}
void
SecureSocket::secureConnect()
{
setJob(new TSocketMultiplexerMethodJob<SecureSocket>(
this, &SecureSocket::serviceConnect,
getSocket(), isReadable(), isWritable()));
}
void
SecureSocket::secureAccept()
{
setJob(new TSocketMultiplexerMethodJob<SecureSocket>(
this, &SecureSocket::serviceAccept,
getSocket(), isReadable(), isWritable()));
}
UInt32
SecureSocket::secureRead(void* buffer, UInt32 n)
{
bool retry = false;
int r = 0;
if (m_ssl->m_ssl != NULL) {
r = SSL_read(m_ssl->m_ssl, buffer, n);
retry = checkResult(r);
if (retry) {
r = 0;
}
}
return r > 0 ? (UInt32)r : 0;
}
UInt32
SecureSocket::secureWrite(const void* buffer, UInt32 n)
{
bool retry = false;
int r = 0;
if (m_ssl->m_ssl != NULL) {
r = SSL_write(m_ssl->m_ssl, buffer, n);
retry = checkResult(r);
if (retry) {
r = 0;
}
}
return r > 0 ? (UInt32)r : 0;
}
bool
SecureSocket::isSecureReady()
{
return m_secureReady;
}
void
SecureSocket::initSsl(bool server)
{
m_ssl = new Ssl();
m_ssl->m_context = NULL;
m_ssl->m_ssl = NULL;
m_error = new char[MAX_ERROR_SIZE];
initContext(server);
}
void
SecureSocket::loadCertificates(const char* filename)
{
int r = 0;
r = SSL_CTX_use_certificate_file(m_ssl->m_context, filename, SSL_FILETYPE_PEM);
if (r <= 0) {
showError();
}
r = SSL_CTX_use_PrivateKey_file(m_ssl->m_context, filename, SSL_FILETYPE_PEM);
if (r <= 0) {
showError();
}
//verify private key
r = SSL_CTX_check_private_key(m_ssl->m_context);
if (!r) {
showError();
}
}
void
SecureSocket::initContext(bool server)
{
SSL_library_init();
const SSL_METHOD* method;
// load & register all cryptos, etc.
OpenSSL_add_all_algorithms();
// load all error messages
SSL_load_error_strings();
if (server) {
// create new server-method instance
method = SSLv23_server_method();
}
else {
// create new client-method instance
method = SSLv23_client_method();
}
// create new context from method
m_ssl->m_context = SSL_CTX_new(method);
if (m_ssl->m_context == NULL) {
showError();
}
}
void
SecureSocket::createSSL()
{
// I assume just one instance is needed
// get new SSL state with context
if (m_ssl->m_ssl == NULL) {
m_ssl->m_ssl = SSL_new(m_ssl->m_context);
}
}
bool
SecureSocket::secureAccept(int socket)
{
createSSL();
// set connection socket to SSL state
SSL_set_fd(m_ssl->m_ssl, socket);
// do SSL-protocol accept
LOG((CLOG_DEBUG1 "secureAccept"));
int r = SSL_accept(m_ssl->m_ssl);
bool retry = checkResult(r);
m_secureReady = !retry;
return retry;
}
bool
SecureSocket::secureConnect(int socket)
{
createSSL();
// attach the socket descriptor
SSL_set_fd(m_ssl->m_ssl, socket);
LOG((CLOG_DEBUG1 "secureConnect"));
int r = SSL_connect(m_ssl->m_ssl);
bool retry = checkResult(r);
m_secureReady = !retry;
if (m_secureReady) {
showCertificate();
}
return retry;
}
void
SecureSocket::showCertificate()
{
X509* cert;
char* line;
// get the server's certificate
cert = SSL_get_peer_certificate(m_ssl->m_ssl);
if (cert != NULL) {
LOG((CLOG_INFO "server certificate"));
line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
LOG((CLOG_INFO "subject: %s", line));
OPENSSL_free(line);
X509_free(cert);
}
else {
LOG((CLOG_INFO "no certificates"));
}
}
bool
SecureSocket::checkResult(int n)
{
bool retry = false;
int errorCode = SSL_get_error(m_ssl->m_ssl, n);
switch (errorCode) {
case SSL_ERROR_NONE:
// the TLS/SSL I/O operation completed
break;
case SSL_ERROR_ZERO_RETURN:
// the TLS/SSL connection has been closed
LOG((CLOG_DEBUG2 "SSL_ERROR_ZERO_RETURN"));
break;
case SSL_ERROR_WANT_READ:
LOG((CLOG_DEBUG2 "secure socket error: SSL_ERROR_WANT_READ"));
retry = true;
break;
case SSL_ERROR_WANT_WRITE:
LOG((CLOG_DEBUG2 "secure socket error: SSL_ERROR_WANT_WRITE"));
retry = true;
break;
case SSL_ERROR_WANT_CONNECT:
LOG((CLOG_DEBUG2 "secure socket error: SSL_ERROR_WANT_CONNECT"));
retry = true;
break;
case SSL_ERROR_WANT_ACCEPT:
LOG((CLOG_DEBUG2 "secure socket error: SSL_ERROR_WANT_ACCEPT"));
retry = true;
break;
case SSL_ERROR_SYSCALL:
// some I/O error occurred
throwError("Secure socket syscall error");
break;
case SSL_ERROR_SSL:
// a failure in the SSL library occurred
LOG((CLOG_DEBUG2 "SSL_ERROR_SSL"));
sendEvent(getEvents()->forISocket().disconnected());
sendEvent(getEvents()->forIStream().inputShutdown());
showError();
retry = true;
break;
default:
// possible cases:
// SSL_ERROR_WANT_X509_LOOKUP
showError();
}
return retry;
}
void
SecureSocket::showError()
{
if (getError()) {
LOG((CLOG_ERR "secure socket error: %s", m_error));
}
}
void
SecureSocket::throwError(const char* reason)
{
if (getError()) {
throw XSocket(synergy::string::sprintf(
"%s: %s", reason, m_error));
}
}
bool
SecureSocket::getError()
{
unsigned long e = ERR_get_error();
bool errorUpdated = false;
if (e != 0) {
ERR_error_string_n(e, m_error, MAX_ERROR_SIZE);
errorUpdated = true;
}
else {
LOG((CLOG_DEBUG2 "can not detect any error in secure socket"));
}
return errorUpdated;
}
ISocketMultiplexerJob*
SecureSocket::serviceConnect(ISocketMultiplexerJob* job,
bool, bool write, bool error)
{
Lock lock(&getMutex());
bool retry = true;
#ifdef SYSAPI_WIN32
retry = secureConnect(static_cast<int>(getSocket()->m_socket));
#elif SYSAPI_UNIX
retry = secureConnect(getSocket()->m_fd);
#endif
return retry ? job : newJob();
}
ISocketMultiplexerJob*
SecureSocket::serviceAccept(ISocketMultiplexerJob* job,
bool, bool write, bool error)
{
Lock lock(&getMutex());
bool retry = true;
#ifdef SYSAPI_WIN32
retry = secureAccept(static_cast<int>(getSocket()->m_socket));
#elif SYSAPI_UNIX
retry = secureAccept(getSocket()->m_fd);
#endif
return retry ? job : newJob();
}

View File

@ -0,0 +1,78 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2015 Synergy Si Ltd.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file COPYING that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "net/TCPSocket.h"
#include "net/XSocket.h"
class IEventQueue;
class SocketMultiplexer;
class ISocketMultiplexerJob;
struct Ssl;
//! Secure socket
/*!
A secure socket using SSL.
*/
class SecureSocket : public TCPSocket {
public:
SecureSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer);
SecureSocket(IEventQueue* events,
SocketMultiplexer* socketMultiplexer,
ArchSocket socket);
~SecureSocket();
// ISocket overrides
void close();
void secureConnect();
void secureAccept();
bool isReady() const { return m_secureReady; }
bool isSecureReady();
bool isSecure() { return true; }
UInt32 secureRead(void* buffer, UInt32 n);
UInt32 secureWrite(const void* buffer, UInt32 n);
void initSsl(bool server);
void loadCertificates(const char* CertFile);
private:
// SSL
void initContext(bool server);
void createSSL();
bool secureAccept(int s);
bool secureConnect(int s);
void showCertificate();
bool checkResult(int n);
void showError();
void throwError(const char* reason);
bool getError();
ISocketMultiplexerJob*
serviceConnect(ISocketMultiplexerJob*,
bool, bool, bool);
ISocketMultiplexerJob*
serviceAccept(ISocketMultiplexerJob*,
bool, bool, bool);
private:
Ssl* m_ssl;
bool m_secureReady;
char* m_error;
};

105
src/lib/plugin/ns/ns.cpp Normal file
View File

@ -0,0 +1,105 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2015 Synergy Si Ltd
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file COPYING that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ns.h"
#include "SecureSocket.h"
#include "SecureListenSocket.h"
#include "arch/Arch.h"
#include "base/Log.h"
#include <iostream>
SecureSocket* g_secureSocket = NULL;
SecureListenSocket* g_secureListenSocket = NULL;
Arch* g_arch = NULL;
Log* g_log = NULL;
extern "C" {
void
init(void* log, void* arch)
{
if (g_log == NULL) {
g_log = new Log(reinterpret_cast<Log*>(log));
}
if (g_arch == NULL) {
g_arch = new Arch(reinterpret_cast<Arch*>(arch));
}
}
int
initEvent(void (*sendEvent)(const char*, void*))
{
return 0;
}
void*
invoke(const char* command, void** args)
{
IEventQueue* arg1 = NULL;
SocketMultiplexer* arg2 = NULL;
if (args != NULL) {
arg1 = reinterpret_cast<IEventQueue*>(args[0]);
arg2 = reinterpret_cast<SocketMultiplexer*>(args[1]);
}
if (strcmp(command, "getSocket") == 0) {
if (g_secureSocket != NULL) {
delete g_secureSocket;
}
g_secureSocket = new SecureSocket(arg1, arg2);
g_secureSocket->initSsl(false);
return g_secureSocket;
}
else if (strcmp(command, "getListenSocket") == 0) {
if (g_secureListenSocket != NULL) {
delete g_secureListenSocket;
}
g_secureListenSocket = new SecureListenSocket(arg1, arg2);
return g_secureListenSocket;
}
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()
{
if (g_secureSocket != NULL) {
delete g_secureSocket;
}
if (g_secureListenSocket != NULL) {
delete g_secureListenSocket;
}
}
}

41
src/lib/plugin/ns/ns.h Normal file
View File

@ -0,0 +1,41 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2015 Synergy Si Ltd
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file COPYING that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#if defined _WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#if defined(ns_EXPORTS)
#define NS_API __declspec(dllexport)
#else
#define NS_API __declspec(dllimport)
#endif
#else
#define NS_API
#endif
extern "C" {
NS_API void init(void* log, void* arch);
NS_API int initEvent(void (*sendEvent)(const char*, void*));
NS_API void* invoke(const char* command, void** args);
NS_API void cleanup();
}

View File

@ -27,6 +27,6 @@ add_custom_command(
TARGET winmmjoy
POST_BUILD
COMMAND xcopy /Y /Q
..\\..\\..\\..\\lib\\${CMAKE_CFG_INTDIR}\\winmmjoy.*
..\\..\\..\\..\\bin\\${CMAKE_CFG_INTDIR}\\plugins\\
..\\..\\..\\..\\..\\lib\\${CMAKE_CFG_INTDIR}\\winmmjoy.*
..\\..\\..\\..\\..\\bin\\${CMAKE_CFG_INTDIR}\\plugins\\
)

View File

@ -36,22 +36,23 @@ static void (*s_log)(const char*) = NULL;
extern "C" {
void
init(void* log, void* arch)
{
}
int
init(void (*sendEvent)(const char*, void*), void (*log)(const char*))
initEvent(void (*sendEvent)(const char*, void*))
{
s_sendEvent = sendEvent;
s_log = log;
LOG("init");
CreateThread(NULL, 0, mainLoop, NULL, 0, NULL);
return 0;
}
int
void
cleanup()
{
LOG("cleanup");
s_running = false;
return 0;
}
}

View File

@ -29,8 +29,9 @@
extern "C" {
WINMMJOY_API int init(void (*sendEvent)(const char*, void*), void (*log)(const char*));
WINMMJOY_API int cleanup();
WINMMJOY_API void init(void* log, void* arch);
WINMMJOY_API int initEvent(void (*sendEvent)(const char*, void*));
WINMMJOY_API 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

@ -27,7 +27,6 @@
#include "net/XSocket.h"
#include "io/CryptoStream.h"
#include "io/CryptoOptions.h"
#include "io/IStreamFilterFactory.h"
#include "base/Log.h"
#include "base/IEventQueue.h"
#include "base/TMethodEventJob.h"
@ -36,13 +35,17 @@
// ClientListener
//
#if defined _WIN32
static const char s_networkSecurity[] = { "ns" };
#else
static const char s_networkSecurity[] = { "libns" };
#endif
ClientListener::ClientListener(const NetworkAddress& address,
ISocketFactory* socketFactory,
IStreamFilterFactory* streamFilterFactory,
const CryptoOptions& crypto,
IEventQueue* events) :
m_socketFactory(socketFactory),
m_streamFilterFactory(streamFilterFactory),
m_server(NULL),
m_crypto(crypto),
m_events(events)
@ -51,22 +54,21 @@ ClientListener::ClientListener(const NetworkAddress& address,
try {
// create listen socket
m_listen = m_socketFactory->createListen();
m_useSecureNetwork = ARCH->plugin().exists(s_networkSecurity);
m_listen = m_socketFactory->createListen(m_useSecureNetwork);
// bind listen address
LOG((CLOG_DEBUG1 "binding listen socket"));
m_listen->bind(address);
}
catch (XSocketAddressInUse&) {
delete m_listen;
cleanupListenSocket();
delete m_socketFactory;
delete m_streamFilterFactory;
throw;
}
catch (XBase&) {
delete m_listen;
cleanupListenSocket();
delete m_socketFactory;
delete m_streamFilterFactory;
throw;
}
LOG((CLOG_DEBUG1 "listening for clients"));
@ -102,9 +104,8 @@ ClientListener::~ClientListener()
}
m_events->removeHandler(m_events->forIListenSocket().connecting(), m_listen);
delete m_listen;
cleanupListenSocket();
delete m_socketFactory;
delete m_streamFilterFactory;
}
void
@ -114,6 +115,12 @@ ClientListener::setServer(Server* server)
m_server = server;
}
void
ClientListener::deleteSocket(void* socket)
{
m_listen->deleteSocket(socket);
}
ClientProxy*
ClientListener::getNextClient()
{
@ -130,17 +137,18 @@ void
ClientListener::handleClientConnecting(const Event&, void*)
{
// accept client connection
synergy::IStream* stream = m_listen->accept();
IDataSocket* socket = m_listen->accept();
synergy::IStream* stream = socket;
if (stream == NULL) {
return;
}
LOG((CLOG_NOTE "accepted client connection"));
// filter socket messages, including a packetizing filter
if (m_streamFilterFactory != NULL) {
stream = m_streamFilterFactory->create(stream, true);
}
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(
@ -150,6 +158,12 @@ ClientListener::handleClientConnecting(const Event&, void*)
assert(m_server != NULL);
if (m_useSecureNetwork) {
while(!socket->isReady()) {
ARCH->sleep(.5f);
}
}
// create proxy for unknown client
ClientProxyUnknown* client = new ClientProxyUnknown(stream, 30.0, m_server, m_events);
m_newClients.insert(client);
@ -174,6 +188,7 @@ ClientListener::handleUnknownClient(const Event&, void* vclient)
// get the real client proxy and install it
ClientProxy* client = unknownClient->orphanClientProxy();
bool handshakeOk = true;
if (client != NULL) {
// handshake was successful
m_waitingClients.push_back(client);
@ -185,12 +200,25 @@ ClientListener::handleUnknownClient(const Event&, void* vclient)
&ClientListener::handleClientDisconnected,
client));
}
else {
handshakeOk = false;
}
// now finished with unknown client
m_events->removeHandler(m_events->forClientProxyUnknown().success(), client);
m_events->removeHandler(m_events->forClientProxyUnknown().failure(), client);
m_newClients.erase(unknownClient);
PacketStreamFilter* streamFileter = dynamic_cast<PacketStreamFilter*>(unknownClient->getStream());
IDataSocket* socket = NULL;
if (streamFileter != NULL) {
socket = dynamic_cast<IDataSocket*>(streamFileter->getStream());
}
delete unknownClient;
if (m_useSecureNetwork && !handshakeOk) {
deleteSocket(socket);
}
}
void
@ -210,3 +238,17 @@ ClientListener::handleClientDisconnected(const Event&, void* vclient)
}
}
}
void
ClientListener::cleanupListenSocket()
{
if (!m_useSecureNetwork) {
delete m_listen;
}
else {
ARCH->plugin().invoke(
s_networkSecurity,
"deleteListenSocket",
NULL);
}
}

View File

@ -30,7 +30,6 @@ class ClientProxyUnknown;
class NetworkAddress;
class IListenSocket;
class ISocketFactory;
class IStreamFilterFactory;
class Server;
class IEventQueue;
@ -39,7 +38,6 @@ public:
// The factories are adopted.
ClientListener(const NetworkAddress&,
ISocketFactory*,
IStreamFilterFactory*,
const CryptoOptions& crypto,
IEventQueue* events);
~ClientListener();
@ -51,6 +49,8 @@ public:
//@}
void deleteSocket(void* socket);
//! @name accessors
//@{
@ -63,7 +63,7 @@ public:
ClientProxy* getNextClient();
//! Get server which owns this listener
Server* getServer() { return m_server; }
Server* getServer() { return m_server; }
//@}
@ -73,16 +73,18 @@ private:
void handleUnknownClient(const Event&, void*);
void handleClientDisconnected(const Event&, void*);
void cleanupListenSocket();
private:
typedef std::set<ClientProxyUnknown*> NewClients;
typedef std::deque<ClientProxy*> WaitingClients;
IListenSocket* m_listen;
ISocketFactory* m_socketFactory;
IStreamFilterFactory* m_streamFilterFactory;
NewClients m_newClients;
WaitingClients m_waitingClients;
Server* m_server;
Server* m_server;
CryptoOptions m_crypto;
IEventQueue* m_events;
bool m_useSecureNetwork;
};

View File

@ -52,7 +52,7 @@ public:
Returns a crypto stream if the user has this enabled,
otherwise returns the original stream passed to the c'tor.
*/
synergy::IStream* getStream() const;
synergy::IStream* getStream() const;
//@}

View File

@ -43,6 +43,9 @@ public:
*/
ClientProxy* orphanClientProxy();
//! Get the stream
synergy::IStream* getStream() { return m_stream; }
//@}
private:
@ -63,6 +66,6 @@ private:
EventQueueTimer* m_timer;
ClientProxy* m_proxy;
bool m_ready;
Server* m_server;
Server* m_server;
IEventQueue* m_events;
};

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
@ -1368,7 +1375,10 @@ Server::handleClientCloseTimeout(const Event&, void* vclient)
BaseClientProxy* client = reinterpret_cast<BaseClientProxy*>(vclient);
LOG((CLOG_NOTE "forced disconnection of client \"%s\"", getName(client).c_str()));
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
/*!
@ -154,6 +155,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
@ -412,7 +416,7 @@ private:
SInt32 m_xDelta2, m_yDelta2;
// current configuration
Config* m_config;
Config* m_config;
// input filter (from m_config);
InputFilter* m_inputFilter;
@ -458,7 +462,7 @@ private:
bool m_lockedToScreen;
// server screen
synergy::Screen* m_screen;
synergy::Screen* m_screen;
IEventQueue* m_events;
@ -466,12 +470,14 @@ private:
size_t m_expectedFileSize;
String m_receivedFileData;
DragFileList m_dragFileList;
Thread* m_sendFileThread;
Thread* m_writeToDropDirThread;
Thread* m_sendFileThread;
Thread* m_writeToDropDirThread;
String m_dragFileExt;
bool m_ignoreFileTransfer;
bool m_enableDragDrop;
Thread* m_getDragInfoThread;
Thread* m_getDragInfoThread;
bool m_waitDragInfoThread;
ClientListener* m_clientListener;
};

View File

@ -326,7 +326,7 @@ ClientApp::handleClientDisconnected(const Event&, void*)
m_events->addEvent(Event(Event::kQuit));
}
else if (!m_suspended) {
m_client->connect();
scheduleClientRestart(nextRestartTimeout());
}
updateStatus();
}
@ -340,8 +340,7 @@ ClientApp::openClient(const String& name, const NetworkAddress& address,
m_events,
name,
address,
new CTCPSocketFactory(m_events, getSocketMultiplexer()),
NULL,
new TCPSocketFactory(m_events, getSocketMultiplexer()),
screen,
crypto,
args().m_enableDragDrop);
@ -458,6 +457,11 @@ ClientApp::mainLoop()
SocketMultiplexer multiplexer;
setSocketMultiplexer(&multiplexer);
// load all available plugins.
ARCH->plugin().load();
// pass log and arch into plugins.
ARCH->plugin().init(Log::getInstance(), Arch::getInstance());
// start client, etc
appUtil().startNode();
@ -467,8 +471,8 @@ ClientApp::mainLoop()
initIpcClient();
}
// load all available plugins.
ARCH->plugin().init(m_clientScreen->getEventTarget(), m_events);
// init event for all available plugins.
ARCH->plugin().initEvent(m_clientScreen->getEventTarget(), m_events);
// run event loop. if startClient() failed we're supposed to retry
// later. the timer installed by startClient() will take care of
@ -504,6 +508,9 @@ ClientApp::mainLoop()
cleanupIpcClient();
}
// unload all plugins.
ARCH->plugin().unload();
return kExitSuccess;
}

View File

@ -101,7 +101,7 @@ DragInformation::getDragFileExtension(String filename)
int
DragInformation::setupDragInfo(DragFileList& fileList, String& output)
{
int size = fileList.size();
int size = static_cast<int>(fileList.size());
for (int i = 0; i < size; ++i) {
output.append(fileList.at(i).getFilename());
output.append(",");

View File

@ -338,8 +338,8 @@ void
ServerApp::stopServer()
{
if (m_serverState == kStarted) {
closeClientListener(m_listener);
closeServer(m_server);
closeClientListener(m_listener);
m_server = NULL;
m_listener = NULL;
m_serverState = kInitialized;
@ -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"));
@ -631,8 +632,7 @@ ServerApp::openClientListener(const NetworkAddress& address)
{
ClientListener* listen = new ClientListener(
address,
new CTCPSocketFactory(m_events, getSocketMultiplexer()),
NULL,
new TCPSocketFactory(m_events, getSocketMultiplexer()),
args().m_crypto,
m_events);
@ -707,6 +707,11 @@ ServerApp::mainLoop()
return kExitFailed;
}
// load all available plugins.
ARCH->plugin().load();
// pass log and arch into plugins.
ARCH->plugin().init(Log::getInstance(), Arch::getInstance());
// start server, etc
appUtil().startNode();
@ -716,8 +721,8 @@ ServerApp::mainLoop()
initIpcClient();
}
// load all available plugins.
ARCH->plugin().init(m_serverScreen->getEventTarget(), m_events);
// init event for all available plugins.
ARCH->plugin().initEvent(m_serverScreen->getEventTarget(), m_events);
// handle hangup signal by reloading the server's configuration
ARCH->setSignalHandler(Arch::kHANGUP, &reloadSignalHandler, NULL);
@ -775,6 +780,9 @@ ServerApp::mainLoop()
cleanupIpcClient();
}
// unload all plugins.
ARCH->plugin().unload();
return kExitSuccess;
}

View File

@ -115,8 +115,8 @@ TEST_F(NetworkTests, sendToClient_mockData)
// server
SocketMultiplexer serverSocketMultiplexer;
CTCPSocketFactory* serverSocketFactory = new CTCPSocketFactory(&m_events, &serverSocketMultiplexer);
ClientListener listener(serverAddress, serverSocketFactory, NULL, cryptoOptions, &m_events);
TCPSocketFactory* serverSocketFactory = new TCPSocketFactory(&m_events, &serverSocketMultiplexer);
ClientListener listener(serverAddress, serverSocketFactory, cryptoOptions, &m_events);
NiceMock<MockScreen> serverScreen;
NiceMock<MockPrimaryClient> primaryClient;
NiceMock<MockConfig> serverConfig;
@ -137,12 +137,12 @@ TEST_F(NetworkTests, sendToClient_mockData)
// client
NiceMock<MockScreen> clientScreen;
SocketMultiplexer clientSocketMultiplexer;
CTCPSocketFactory* clientSocketFactory = new CTCPSocketFactory(&m_events, &clientSocketMultiplexer);
TCPSocketFactory* clientSocketFactory = new TCPSocketFactory(&m_events, &clientSocketMultiplexer);
ON_CALL(clientScreen, getShape(_, _, _, _)).WillByDefault(Invoke(getScreenShape));
ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos));
Client client(&m_events, "stub", serverAddress, clientSocketFactory, NULL, &clientScreen, cryptoOptions, true);
Client client(&m_events, "stub", serverAddress, clientSocketFactory, &clientScreen, cryptoOptions, true);
m_events.adoptHandler(
m_events.forIScreen().fileRecieveCompleted(), &client,
@ -168,8 +168,8 @@ TEST_F(NetworkTests, sendToClient_mockFile)
// server
SocketMultiplexer serverSocketMultiplexer;
CTCPSocketFactory* serverSocketFactory = new CTCPSocketFactory(&m_events, &serverSocketMultiplexer);
ClientListener listener(serverAddress, serverSocketFactory, NULL, cryptoOptions, &m_events);
TCPSocketFactory* serverSocketFactory = new TCPSocketFactory(&m_events, &serverSocketMultiplexer);
ClientListener listener(serverAddress, serverSocketFactory, cryptoOptions, &m_events);
NiceMock<MockScreen> serverScreen;
NiceMock<MockPrimaryClient> primaryClient;
NiceMock<MockConfig> serverConfig;
@ -190,12 +190,12 @@ TEST_F(NetworkTests, sendToClient_mockFile)
// client
NiceMock<MockScreen> clientScreen;
SocketMultiplexer clientSocketMultiplexer;
CTCPSocketFactory* clientSocketFactory = new CTCPSocketFactory(&m_events, &clientSocketMultiplexer);
TCPSocketFactory* clientSocketFactory = new TCPSocketFactory(&m_events, &clientSocketMultiplexer);
ON_CALL(clientScreen, getShape(_, _, _, _)).WillByDefault(Invoke(getScreenShape));
ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos));
Client client(&m_events, "stub", serverAddress, clientSocketFactory, NULL, &clientScreen, cryptoOptions, true);
Client client(&m_events, "stub", serverAddress, clientSocketFactory, &clientScreen, cryptoOptions, true);
m_events.adoptHandler(
m_events.forIScreen().fileRecieveCompleted(), &client,
@ -221,8 +221,8 @@ TEST_F(NetworkTests, sendToServer_mockData)
// server
SocketMultiplexer serverSocketMultiplexer;
CTCPSocketFactory* serverSocketFactory = new CTCPSocketFactory(&m_events, &serverSocketMultiplexer);
ClientListener listener(serverAddress, serverSocketFactory, NULL, cryptoOptions, &m_events);
TCPSocketFactory* serverSocketFactory = new TCPSocketFactory(&m_events, &serverSocketMultiplexer);
ClientListener listener(serverAddress, serverSocketFactory, cryptoOptions, &m_events);
NiceMock<MockScreen> serverScreen;
NiceMock<MockPrimaryClient> primaryClient;
NiceMock<MockConfig> serverConfig;
@ -238,12 +238,12 @@ TEST_F(NetworkTests, sendToServer_mockData)
// client
NiceMock<MockScreen> clientScreen;
SocketMultiplexer clientSocketMultiplexer;
CTCPSocketFactory* clientSocketFactory = new CTCPSocketFactory(&m_events, &clientSocketMultiplexer);
TCPSocketFactory* clientSocketFactory = new TCPSocketFactory(&m_events, &clientSocketMultiplexer);
ON_CALL(clientScreen, getShape(_, _, _, _)).WillByDefault(Invoke(getScreenShape));
ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos));
Client client(&m_events, "stub", serverAddress, clientSocketFactory, NULL, &clientScreen, cryptoOptions, true);
Client client(&m_events, "stub", serverAddress, clientSocketFactory, &clientScreen, cryptoOptions, true);
m_events.adoptHandler(
m_events.forClientListener().connected(), &listener,
@ -274,8 +274,8 @@ TEST_F(NetworkTests, sendToServer_mockFile)
// server
SocketMultiplexer serverSocketMultiplexer;
CTCPSocketFactory* serverSocketFactory = new CTCPSocketFactory(&m_events, &serverSocketMultiplexer);
ClientListener listener(serverAddress, serverSocketFactory, NULL, cryptoOptions, &m_events);
TCPSocketFactory* serverSocketFactory = new TCPSocketFactory(&m_events, &serverSocketMultiplexer);
ClientListener listener(serverAddress, serverSocketFactory, cryptoOptions, &m_events);
NiceMock<MockScreen> serverScreen;
NiceMock<MockPrimaryClient> primaryClient;
NiceMock<MockConfig> serverConfig;
@ -291,12 +291,12 @@ TEST_F(NetworkTests, sendToServer_mockFile)
// client
NiceMock<MockScreen> clientScreen;
SocketMultiplexer clientSocketMultiplexer;
CTCPSocketFactory* clientSocketFactory = new CTCPSocketFactory(&m_events, &clientSocketMultiplexer);
TCPSocketFactory* clientSocketFactory = new TCPSocketFactory(&m_events, &clientSocketMultiplexer);
ON_CALL(clientScreen, getShape(_, _, _, _)).WillByDefault(Invoke(getScreenShape));
ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos));
Client client(&m_events, "stub", serverAddress, clientSocketFactory, NULL, &clientScreen, cryptoOptions, true);
Client client(&m_events, "stub", serverAddress, clientSocketFactory, &clientScreen, cryptoOptions, true);
m_events.adoptHandler(
m_events.forClientListener().connected(), &listener,