Merge remote-tracking branch 'origin/jerry-sandbox'
This commit is contained in:
commit
3c4b6163e3
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
Binary file not shown.
|
@ -16,7 +16,6 @@
|
|||
|
||||
add_subdirectory(lib)
|
||||
add_subdirectory(cmd)
|
||||
add_subdirectory(plugin)
|
||||
add_subdirectory(micro)
|
||||
|
||||
if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "IRIX")
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -30,6 +30,11 @@ Arch::Arch()
|
|||
s_instance = this;
|
||||
}
|
||||
|
||||
Arch::Arch(Arch* arch)
|
||||
{
|
||||
s_instance = arch;
|
||||
}
|
||||
|
||||
Arch::~Arch()
|
||||
{
|
||||
#if SYSAPI_WIN32
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -50,5 +50,5 @@ endif()
|
|||
add_library(arch STATIC ${sources})
|
||||
|
||||
if (UNIX)
|
||||
target_link_libraries(arch ${libs})
|
||||
target_link_libraries(arch dl ${libs})
|
||||
endif()
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -74,6 +74,11 @@ Log::Log()
|
|||
s_log = this;
|
||||
}
|
||||
|
||||
Log::Log(Log* src)
|
||||
{
|
||||
s_log = src;
|
||||
}
|
||||
|
||||
Log::~Log()
|
||||
{
|
||||
// clean up
|
||||
|
|
|
@ -41,6 +41,7 @@ LOGC() provide convenient access.
|
|||
class Log {
|
||||
public:
|
||||
Log();
|
||||
Log(Log* src);
|
||||
~Log();
|
||||
|
||||
//! @name manipulators
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -58,7 +58,7 @@ private:
|
|||
|
||||
private:
|
||||
NetworkAddress m_serverAddress;
|
||||
CTCPSocket m_socket;
|
||||
TCPSocket m_socket;
|
||||
IpcServerProxy* m_server;
|
||||
IEventQueue* m_events;
|
||||
};
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
||||
//@}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
//@}
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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>(
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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()
|
|
@ -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()
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
};
|
|
@ -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();
|
||||
}
|
|
@ -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;
|
||||
};
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
|
||||
}
|
|
@ -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\\
|
||||
)
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
||||
//@}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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(",");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue