Merge remote-tracking branch 'origin/jerry-sandbox'
This commit is contained in:
commit
3c4b6163e3
|
@ -6,6 +6,7 @@ config.h
|
||||||
/ext/cryptopp562
|
/ext/cryptopp562
|
||||||
/ext/gmock-1.6.0
|
/ext/gmock-1.6.0
|
||||||
/ext/gtest-1.6.0
|
/ext/gtest-1.6.0
|
||||||
|
/ext/openssl
|
||||||
/src/gui/Makefile*
|
/src/gui/Makefile*
|
||||||
/src/gui/object_script*
|
/src/gui/object_script*
|
||||||
/src/gui/tmp
|
/src/gui/tmp
|
||||||
|
|
|
@ -76,7 +76,7 @@ if (UNIX)
|
||||||
|
|
||||||
# warnings as errors:
|
# warnings as errors:
|
||||||
# we have a problem with people checking in code with warnings.
|
# 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.
|
# For config.h, detect the libraries, functions, etc.
|
||||||
include(CheckIncludeFiles)
|
include(CheckIncludeFiles)
|
||||||
|
@ -174,7 +174,7 @@ if (UNIX)
|
||||||
CACHE STRING "" FORCE)
|
CACHE STRING "" FORCE)
|
||||||
else()
|
else()
|
||||||
# >= 10.6: Intel only
|
# >= 10.6: Intel only
|
||||||
set(CMAKE_OSX_ARCHITECTURES "i386;x86_64"
|
set(CMAKE_OSX_ARCHITECTURES "i386"
|
||||||
CACHE STRING "" FORCE)
|
CACHE STRING "" FORCE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -16,7 +16,6 @@
|
||||||
|
|
||||||
add_subdirectory(lib)
|
add_subdirectory(lib)
|
||||||
add_subdirectory(cmd)
|
add_subdirectory(cmd)
|
||||||
add_subdirectory(plugin)
|
|
||||||
add_subdirectory(micro)
|
add_subdirectory(micro)
|
||||||
|
|
||||||
if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "IRIX")
|
if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "IRIX")
|
||||||
|
|
|
@ -23,9 +23,11 @@ add_subdirectory(ipc)
|
||||||
add_subdirectory(mt)
|
add_subdirectory(mt)
|
||||||
add_subdirectory(net)
|
add_subdirectory(net)
|
||||||
add_subdirectory(platform)
|
add_subdirectory(platform)
|
||||||
|
add_subdirectory(plugin)
|
||||||
add_subdirectory(server)
|
add_subdirectory(server)
|
||||||
add_subdirectory(synergy)
|
add_subdirectory(synergy)
|
||||||
|
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
add_subdirectory(synwinhk)
|
add_subdirectory(synwinhk)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -30,6 +30,11 @@ Arch::Arch()
|
||||||
s_instance = this;
|
s_instance = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Arch::Arch(Arch* arch)
|
||||||
|
{
|
||||||
|
s_instance = arch;
|
||||||
|
}
|
||||||
|
|
||||||
Arch::~Arch()
|
Arch::~Arch()
|
||||||
{
|
{
|
||||||
#if SYSAPI_WIN32
|
#if SYSAPI_WIN32
|
||||||
|
|
|
@ -99,6 +99,7 @@ class Arch : public ARCH_CONSOLE,
|
||||||
public ARCH_TIME {
|
public ARCH_TIME {
|
||||||
public:
|
public:
|
||||||
Arch();
|
Arch();
|
||||||
|
Arch(Arch* arch);
|
||||||
virtual ~Arch();
|
virtual ~Arch();
|
||||||
|
|
||||||
//! Call init on other arch classes.
|
//! Call init on other arch classes.
|
||||||
|
|
|
@ -50,5 +50,5 @@ endif()
|
||||||
add_library(arch STATIC ${sources})
|
add_library(arch STATIC ${sources})
|
||||||
|
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
target_link_libraries(arch ${libs})
|
target_link_libraries(arch dl ${libs})
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
#define PLUGINS_DIR "plugins"
|
#define PLUGINS_DIR "plugins"
|
||||||
|
|
||||||
#include "common/IInterface.h"
|
#include "common/IInterface.h"
|
||||||
|
#include "common/stdmap.h"
|
||||||
|
#include "base/String.h"
|
||||||
|
|
||||||
class IEventQueue;
|
class IEventQueue;
|
||||||
|
|
||||||
|
@ -38,7 +40,42 @@ public:
|
||||||
/*!
|
/*!
|
||||||
Scan the plugins dir and 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/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()
|
ArchPluginUnix::ArchPluginUnix()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -27,6 +45,153 @@ ArchPluginUnix::~ArchPluginUnix()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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();
|
virtual ~ArchPluginUnix();
|
||||||
|
|
||||||
// IArchPlugin overrides
|
// 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 <Windows.h>
|
||||||
#include <iostream>
|
#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;
|
void* g_eventTarget = NULL;
|
||||||
IEventQueue* g_events = NULL;
|
IEventQueue* g_events = NULL;
|
||||||
|
@ -41,11 +44,8 @@ ArchPluginWindows::~ArchPluginWindows()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ArchPluginWindows::init(void* eventTarget, IEventQueue* events)
|
ArchPluginWindows::load()
|
||||||
{
|
{
|
||||||
g_eventTarget = eventTarget;
|
|
||||||
g_events = events;
|
|
||||||
|
|
||||||
String dir = getPluginsDir();
|
String dir = getPluginsDir();
|
||||||
LOG((CLOG_DEBUG "plugins dir: %s", dir.c_str()));
|
LOG((CLOG_DEBUG "plugins dir: %s", dir.c_str()));
|
||||||
|
|
||||||
|
@ -54,21 +54,113 @@ ArchPluginWindows::init(void* eventTarget, IEventQueue* events)
|
||||||
getFilenames(pattern, plugins);
|
getFilenames(pattern, plugins);
|
||||||
|
|
||||||
std::vector<String>::iterator it;
|
std::vector<String>::iterator it;
|
||||||
for (it = plugins.begin(); it != plugins.end(); ++it)
|
for (it = plugins.begin(); it != plugins.end(); ++it) {
|
||||||
load(*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
|
void
|
||||||
ArchPluginWindows::load(const String& dllFilename)
|
ArchPluginWindows::unload()
|
||||||
{
|
{
|
||||||
LOG((CLOG_DEBUG "loading plugin: %s", dllFilename.c_str()));
|
PluginTable::iterator it;
|
||||||
String path = String(getPluginsDir()).append("\\").append(dllFilename);
|
HINSTANCE lib;
|
||||||
HINSTANCE library = LoadLibrary(path.c_str());
|
for (it = m_pluginTable.begin(); it != m_pluginTable.end(); it++) {
|
||||||
if (library == NULL)
|
lib = reinterpret_cast<HINSTANCE>(it->second);
|
||||||
throw XArch(new XArchEvalWindows);
|
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");
|
LOG((CLOG_DEBUG "unloading plugin: %s", it->first.c_str()));
|
||||||
initPlugin(&sendEvent, &log);
|
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
|
String
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "arch/IArchPlugin.h"
|
#include "arch/IArchPlugin.h"
|
||||||
#include "base/String.h"
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -35,13 +34,22 @@ public:
|
||||||
virtual ~ArchPluginWindows();
|
virtual ~ArchPluginWindows();
|
||||||
|
|
||||||
// IArchPlugin overrides
|
// 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:
|
private:
|
||||||
String getModuleDir();
|
String getModuleDir();
|
||||||
void getFilenames(const String& pattern, std::vector<String>& filenames);
|
void getFilenames(const String& pattern, std::vector<String>& filenames);
|
||||||
void load(const String& dllPath);
|
|
||||||
String getPluginsDir();
|
String getPluginsDir();
|
||||||
|
|
||||||
|
private:
|
||||||
|
PluginTable m_pluginTable;
|
||||||
};
|
};
|
||||||
|
|
||||||
void sendEvent(const char* text, void* data);
|
void sendEvent(const char* text, void* data);
|
||||||
|
|
|
@ -74,6 +74,11 @@ Log::Log()
|
||||||
s_log = this;
|
s_log = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log::Log(Log* src)
|
||||||
|
{
|
||||||
|
s_log = src;
|
||||||
|
}
|
||||||
|
|
||||||
Log::~Log()
|
Log::~Log()
|
||||||
{
|
{
|
||||||
// clean up
|
// clean up
|
||||||
|
|
|
@ -41,6 +41,7 @@ LOGC() provide convenient access.
|
||||||
class Log {
|
class Log {
|
||||||
public:
|
public:
|
||||||
Log();
|
Log();
|
||||||
|
Log(Log* src);
|
||||||
~Log();
|
~Log();
|
||||||
|
|
||||||
//! @name manipulators
|
//! @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
|
// 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);
|
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
|
//! Case-insensitive comparisons
|
||||||
/*!
|
/*!
|
||||||
This class provides case-insensitve comparison functions.
|
This class provides case-insensitve comparison functions.
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include "client/Client.h"
|
#include "client/Client.h"
|
||||||
|
|
||||||
|
#include "../plugin/ns/SecureSocket.h"
|
||||||
#include "client/ServerProxy.h"
|
#include "client/ServerProxy.h"
|
||||||
#include "synergy/Screen.h"
|
#include "synergy/Screen.h"
|
||||||
#include "synergy/Clipboard.h"
|
#include "synergy/Clipboard.h"
|
||||||
|
@ -29,8 +30,8 @@
|
||||||
#include "synergy/FileChunker.h"
|
#include "synergy/FileChunker.h"
|
||||||
#include "synergy/IPlatformScreen.h"
|
#include "synergy/IPlatformScreen.h"
|
||||||
#include "mt/Thread.h"
|
#include "mt/Thread.h"
|
||||||
#include "io/IStreamFilterFactory.h"
|
|
||||||
#include "io/CryptoStream.h"
|
#include "io/CryptoStream.h"
|
||||||
|
#include "net/TCPSocket.h"
|
||||||
#include "net/IDataSocket.h"
|
#include "net/IDataSocket.h"
|
||||||
#include "net/ISocketFactory.h"
|
#include "net/ISocketFactory.h"
|
||||||
#include "arch/Arch.h"
|
#include "arch/Arch.h"
|
||||||
|
@ -45,6 +46,12 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
|
#if defined _WIN32
|
||||||
|
static const char s_networkSecurity[] = { "ns" };
|
||||||
|
#else
|
||||||
|
static const char s_networkSecurity[] = { "libns" };
|
||||||
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
// Client
|
// Client
|
||||||
//
|
//
|
||||||
|
@ -53,7 +60,6 @@ Client::Client(
|
||||||
IEventQueue* events,
|
IEventQueue* events,
|
||||||
const String& name, const NetworkAddress& address,
|
const String& name, const NetworkAddress& address,
|
||||||
ISocketFactory* socketFactory,
|
ISocketFactory* socketFactory,
|
||||||
IStreamFilterFactory* streamFilterFactory,
|
|
||||||
synergy::Screen* screen,
|
synergy::Screen* screen,
|
||||||
const CryptoOptions& crypto,
|
const CryptoOptions& crypto,
|
||||||
bool enableDragDrop) :
|
bool enableDragDrop) :
|
||||||
|
@ -61,7 +67,6 @@ Client::Client(
|
||||||
m_name(name),
|
m_name(name),
|
||||||
m_serverAddress(address),
|
m_serverAddress(address),
|
||||||
m_socketFactory(socketFactory),
|
m_socketFactory(socketFactory),
|
||||||
m_streamFilterFactory(streamFilterFactory),
|
|
||||||
m_screen(screen),
|
m_screen(screen),
|
||||||
m_stream(NULL),
|
m_stream(NULL),
|
||||||
m_timer(NULL),
|
m_timer(NULL),
|
||||||
|
@ -75,7 +80,9 @@ Client::Client(
|
||||||
m_crypto(crypto),
|
m_crypto(crypto),
|
||||||
m_sendFileThread(NULL),
|
m_sendFileThread(NULL),
|
||||||
m_writeToDropDirThread(NULL),
|
m_writeToDropDirThread(NULL),
|
||||||
m_enableDragDrop(enableDragDrop)
|
m_enableDragDrop(enableDragDrop),
|
||||||
|
m_socket(NULL),
|
||||||
|
m_useSecureNetwork(false)
|
||||||
{
|
{
|
||||||
assert(m_socketFactory != NULL);
|
assert(m_socketFactory != NULL);
|
||||||
assert(m_screen != NULL);
|
assert(m_screen != NULL);
|
||||||
|
@ -118,7 +125,6 @@ Client::~Client()
|
||||||
cleanupConnecting();
|
cleanupConnecting();
|
||||||
cleanupConnection();
|
cleanupConnection();
|
||||||
delete m_socketFactory;
|
delete m_socketFactory;
|
||||||
delete m_streamFilterFactory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -150,14 +156,14 @@ Client::connect()
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the socket
|
// 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
|
// filter socket messages, including a packetizing filter
|
||||||
m_stream = socket;
|
m_stream = socket;
|
||||||
if (m_streamFilterFactory != NULL) {
|
bool adopt = !m_useSecureNetwork;
|
||||||
m_stream = m_streamFilterFactory->create(m_stream, true);
|
m_stream = new PacketStreamFilter(m_events, m_stream, adopt);
|
||||||
}
|
|
||||||
m_stream = new PacketStreamFilter(m_events, m_stream, true);
|
|
||||||
|
|
||||||
if (m_crypto.m_mode != kDisabled) {
|
if (m_crypto.m_mode != kDisabled) {
|
||||||
m_cryptoStream = new CryptoStream(
|
m_cryptoStream = new CryptoStream(
|
||||||
|
@ -174,8 +180,7 @@ Client::connect()
|
||||||
catch (XBase& e) {
|
catch (XBase& e) {
|
||||||
cleanupTimer();
|
cleanupTimer();
|
||||||
cleanupConnecting();
|
cleanupConnecting();
|
||||||
delete m_stream;
|
cleanupStream();
|
||||||
m_stream = NULL;
|
|
||||||
LOG((CLOG_DEBUG1 "connection failed"));
|
LOG((CLOG_DEBUG1 "connection failed"));
|
||||||
sendConnectionFailedEvent(e.what());
|
sendConnectionFailedEvent(e.what());
|
||||||
return;
|
return;
|
||||||
|
@ -532,8 +537,7 @@ Client::cleanupConnection()
|
||||||
m_stream->getEventTarget());
|
m_stream->getEventTarget());
|
||||||
m_events->removeHandler(m_events->forISocket().disconnected(),
|
m_events->removeHandler(m_events->forISocket().disconnected(),
|
||||||
m_stream->getEventTarget());
|
m_stream->getEventTarget());
|
||||||
delete m_stream;
|
cleanupStream();
|
||||||
m_stream = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
void
|
||||||
Client::handleConnected(const Event&, void*)
|
Client::handleConnected(const Event&, void*)
|
||||||
{
|
{
|
||||||
|
@ -577,6 +595,8 @@ Client::handleConnected(const Event&, void*)
|
||||||
m_sentClipboard[id] = false;
|
m_sentClipboard[id] = false;
|
||||||
m_timeClipboard[id] = 0;
|
m_timeClipboard[id] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_socket->secureConnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -587,8 +607,7 @@ Client::handleConnectionFailed(const Event& event, void*)
|
||||||
|
|
||||||
cleanupTimer();
|
cleanupTimer();
|
||||||
cleanupConnecting();
|
cleanupConnecting();
|
||||||
delete m_stream;
|
cleanupStream();
|
||||||
m_stream = NULL;
|
|
||||||
LOG((CLOG_DEBUG1 "connection failed"));
|
LOG((CLOG_DEBUG1 "connection failed"));
|
||||||
sendConnectionFailedEvent(info->m_what.c_str());
|
sendConnectionFailedEvent(info->m_what.c_str());
|
||||||
delete info;
|
delete info;
|
||||||
|
@ -600,8 +619,7 @@ Client::handleConnectTimeout(const Event&, void*)
|
||||||
cleanupTimer();
|
cleanupTimer();
|
||||||
cleanupConnecting();
|
cleanupConnecting();
|
||||||
cleanupConnection();
|
cleanupConnection();
|
||||||
delete m_stream;
|
cleanupStream();
|
||||||
m_stream = NULL;
|
|
||||||
LOG((CLOG_DEBUG1 "connection timed out"));
|
LOG((CLOG_DEBUG1 "connection timed out"));
|
||||||
sendConnectionFailedEvent("Timed out");
|
sendConnectionFailedEvent("Timed out");
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,10 +33,10 @@ class ServerProxy;
|
||||||
class IDataSocket;
|
class IDataSocket;
|
||||||
class ISocketFactory;
|
class ISocketFactory;
|
||||||
namespace synergy { class IStream; }
|
namespace synergy { class IStream; }
|
||||||
class IStreamFilterFactory;
|
|
||||||
class IEventQueue;
|
class IEventQueue;
|
||||||
class CryptoStream;
|
class CryptoStream;
|
||||||
class Thread;
|
class Thread;
|
||||||
|
class TCPSocket;
|
||||||
|
|
||||||
//! Synergy client
|
//! Synergy client
|
||||||
/*!
|
/*!
|
||||||
|
@ -60,7 +60,6 @@ public:
|
||||||
Client(IEventQueue* events,
|
Client(IEventQueue* events,
|
||||||
const String& name, const NetworkAddress& address,
|
const String& name, const NetworkAddress& address,
|
||||||
ISocketFactory* socketFactory,
|
ISocketFactory* socketFactory,
|
||||||
IStreamFilterFactory* streamFilterFactory,
|
|
||||||
synergy::Screen* screen,
|
synergy::Screen* screen,
|
||||||
const CryptoOptions& crypto,
|
const CryptoOptions& crypto,
|
||||||
bool enableDragDrop);
|
bool enableDragDrop);
|
||||||
|
@ -189,6 +188,7 @@ private:
|
||||||
void cleanupConnection();
|
void cleanupConnection();
|
||||||
void cleanupScreen();
|
void cleanupScreen();
|
||||||
void cleanupTimer();
|
void cleanupTimer();
|
||||||
|
void cleanupStream();
|
||||||
void handleConnected(const Event&, void*);
|
void handleConnected(const Event&, void*);
|
||||||
void handleConnectionFailed(const Event&, void*);
|
void handleConnectionFailed(const Event&, void*);
|
||||||
void handleConnectTimeout(const Event&, void*);
|
void handleConnectTimeout(const Event&, void*);
|
||||||
|
@ -210,7 +210,6 @@ private:
|
||||||
String m_name;
|
String m_name;
|
||||||
NetworkAddress m_serverAddress;
|
NetworkAddress m_serverAddress;
|
||||||
ISocketFactory* m_socketFactory;
|
ISocketFactory* m_socketFactory;
|
||||||
IStreamFilterFactory* m_streamFilterFactory;
|
|
||||||
synergy::Screen* m_screen;
|
synergy::Screen* m_screen;
|
||||||
synergy::IStream* m_stream;
|
synergy::IStream* m_stream;
|
||||||
EventQueueTimer* m_timer;
|
EventQueueTimer* m_timer;
|
||||||
|
@ -233,4 +232,6 @@ private:
|
||||||
Thread* m_sendFileThread;
|
Thread* m_sendFileThread;
|
||||||
Thread* m_writeToDropDirThread;
|
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 bool isReady() const;
|
||||||
virtual UInt32 getSize() const;
|
virtual UInt32 getSize() const;
|
||||||
|
|
||||||
protected:
|
|
||||||
//! Get the stream
|
//! Get the stream
|
||||||
/*!
|
/*!
|
||||||
Returns the stream passed to the c'tor.
|
Returns the stream passed to the c'tor.
|
||||||
*/
|
*/
|
||||||
synergy::IStream* getStream() const;
|
synergy::IStream* getStream() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
//! Handle events from source stream
|
//! Handle events from source stream
|
||||||
/*!
|
/*!
|
||||||
Does the event filtering. The default simply dispatches an event
|
Does the event filtering. The default simply dispatches an event
|
||||||
|
|
|
@ -58,7 +58,7 @@ private:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NetworkAddress m_serverAddress;
|
NetworkAddress m_serverAddress;
|
||||||
CTCPSocket m_socket;
|
TCPSocket m_socket;
|
||||||
IpcServerProxy* m_server;
|
IpcServerProxy* m_server;
|
||||||
IEventQueue* m_events;
|
IEventQueue* m_events;
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include "mt/Thread.h"
|
#include "mt/Thread.h"
|
||||||
|
|
||||||
|
#include "net/XSocket.h"
|
||||||
#include "mt/XMT.h"
|
#include "mt/XMT.h"
|
||||||
#include "mt/XThread.h"
|
#include "mt/XThread.h"
|
||||||
#include "arch/Arch.h"
|
#include "arch/Arch.h"
|
||||||
|
@ -158,6 +159,10 @@ Thread::threadFunc(void* vjob)
|
||||||
LOG((CLOG_DEBUG1 "thread 0x%08x exit", id));
|
LOG((CLOG_DEBUG1 "thread 0x%08x exit", id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
catch (XSocket& e) {
|
||||||
|
// client called cancel()
|
||||||
|
LOG((CLOG_DEBUG "%s", e.what()));
|
||||||
|
}
|
||||||
catch (XThreadCancel&) {
|
catch (XThreadCancel&) {
|
||||||
// client called cancel()
|
// client called cancel()
|
||||||
LOG((CLOG_DEBUG1 "caught cancel on thread 0x%08x", id));
|
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.
|
data stream. Returns NULL if no socket is waiting to be accepted.
|
||||||
This is only valid after a call to \c bind().
|
This is only valid after a call to \c bind().
|
||||||
*/
|
*/
|
||||||
virtual IDataSocket* accept() = 0;
|
virtual IDataSocket*
|
||||||
|
accept() = 0;
|
||||||
|
|
||||||
|
//! Delete connection socket
|
||||||
|
/*!
|
||||||
|
This is used when the socket was created but not adopted by a client
|
||||||
|
proxy.
|
||||||
|
*/
|
||||||
|
virtual void deleteSocket(void*) = 0;
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
|
|
|
@ -34,10 +34,10 @@ public:
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
//! Create data socket
|
//! Create data socket
|
||||||
virtual IDataSocket* create() const = 0;
|
virtual IDataSocket* create(bool secure) const = 0;
|
||||||
|
|
||||||
//! Create listen socket
|
//! Create listen socket
|
||||||
virtual IListenSocket* createListen() const = 0;
|
virtual IListenSocket* createListen(bool secure) const = 0;
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
};
|
};
|
||||||
|
|
|
@ -106,5 +106,6 @@ private:
|
||||||
|
|
||||||
SocketJobs m_socketJobs;
|
SocketJobs m_socketJobs;
|
||||||
SocketJobMap m_socketJobMap;
|
SocketJobMap m_socketJobMap;
|
||||||
ISocketMultiplexerJob* m_cursorMark;
|
ISocketMultiplexerJob*
|
||||||
|
m_cursorMark;
|
||||||
};
|
};
|
||||||
|
|
|
@ -110,7 +110,7 @@ TCPListenSocket::accept()
|
||||||
{
|
{
|
||||||
IDataSocket* socket = NULL;
|
IDataSocket* socket = NULL;
|
||||||
try {
|
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) {
|
if (socket != NULL) {
|
||||||
m_socketMultiplexer->addSocket(this,
|
m_socketMultiplexer->addSocket(this,
|
||||||
new TSocketMultiplexerMethodJob<TCPListenSocket>(
|
new TSocketMultiplexerMethodJob<TCPListenSocket>(
|
||||||
|
|
|
@ -33,7 +33,7 @@ A listen socket using TCP.
|
||||||
class TCPListenSocket : public IListenSocket {
|
class TCPListenSocket : public IListenSocket {
|
||||||
public:
|
public:
|
||||||
TCPListenSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer);
|
TCPListenSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer);
|
||||||
~TCPListenSocket();
|
virtual ~TCPListenSocket();
|
||||||
|
|
||||||
// ISocket overrides
|
// ISocket overrides
|
||||||
virtual void bind(const NetworkAddress&);
|
virtual void bind(const NetworkAddress&);
|
||||||
|
@ -41,14 +41,16 @@ public:
|
||||||
virtual void* getEventTarget() const;
|
virtual void* getEventTarget() const;
|
||||||
|
|
||||||
// IListenSocket overrides
|
// IListenSocket overrides
|
||||||
virtual IDataSocket* accept();
|
virtual IDataSocket*
|
||||||
|
accept();
|
||||||
|
virtual void deleteSocket(void*) { }
|
||||||
|
|
||||||
private:
|
public:
|
||||||
ISocketMultiplexerJob*
|
ISocketMultiplexerJob*
|
||||||
serviceListening(ISocketMultiplexerJob*,
|
serviceListening(ISocketMultiplexerJob*,
|
||||||
bool, bool, bool);
|
bool, bool, bool);
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
ArchSocket m_socket;
|
ArchSocket m_socket;
|
||||||
Mutex* m_mutex;
|
Mutex* m_mutex;
|
||||||
IEventQueue* m_events;
|
IEventQueue* m_events;
|
||||||
|
|
|
@ -34,10 +34,10 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
//
|
//
|
||||||
// CTCPSocket
|
// TCPSocket
|
||||||
//
|
//
|
||||||
|
|
||||||
CTCPSocket::CTCPSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer) :
|
TCPSocket::TCPSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer) :
|
||||||
IDataSocket(events),
|
IDataSocket(events),
|
||||||
m_mutex(),
|
m_mutex(),
|
||||||
m_flushed(&m_mutex, true),
|
m_flushed(&m_mutex, true),
|
||||||
|
@ -54,7 +54,7 @@ CTCPSocket::CTCPSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
CTCPSocket::CTCPSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer, ArchSocket socket) :
|
TCPSocket::TCPSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer, ArchSocket socket) :
|
||||||
IDataSocket(events),
|
IDataSocket(events),
|
||||||
m_mutex(),
|
m_mutex(),
|
||||||
m_socket(socket),
|
m_socket(socket),
|
||||||
|
@ -70,7 +70,7 @@ CTCPSocket::CTCPSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer
|
||||||
setJob(newJob());
|
setJob(newJob());
|
||||||
}
|
}
|
||||||
|
|
||||||
CTCPSocket::~CTCPSocket()
|
TCPSocket::~TCPSocket()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
close();
|
close();
|
||||||
|
@ -81,7 +81,7 @@ CTCPSocket::~CTCPSocket()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CTCPSocket::bind(const NetworkAddress& addr)
|
TCPSocket::bind(const NetworkAddress& addr)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
ARCH->bindSocket(m_socket, addr.getAddress());
|
ARCH->bindSocket(m_socket, addr.getAddress());
|
||||||
|
@ -95,7 +95,7 @@ CTCPSocket::bind(const NetworkAddress& addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CTCPSocket::close()
|
TCPSocket::close()
|
||||||
{
|
{
|
||||||
// remove ourself from the multiplexer
|
// remove ourself from the multiplexer
|
||||||
setJob(NULL);
|
setJob(NULL);
|
||||||
|
@ -123,13 +123,13 @@ CTCPSocket::close()
|
||||||
}
|
}
|
||||||
|
|
||||||
void*
|
void*
|
||||||
CTCPSocket::getEventTarget() const
|
TCPSocket::getEventTarget() const
|
||||||
{
|
{
|
||||||
return const_cast<void*>(reinterpret_cast<const void*>(this));
|
return const_cast<void*>(reinterpret_cast<const void*>(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt32
|
UInt32
|
||||||
CTCPSocket::read(void* buffer, UInt32 n)
|
TCPSocket::read(void* buffer, UInt32 n)
|
||||||
{
|
{
|
||||||
// copy data directly from our input buffer
|
// copy data directly from our input buffer
|
||||||
Lock lock(&m_mutex);
|
Lock lock(&m_mutex);
|
||||||
|
@ -152,7 +152,7 @@ CTCPSocket::read(void* buffer, UInt32 n)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CTCPSocket::write(const void* buffer, UInt32 n)
|
TCPSocket::write(const void* buffer, UInt32 n)
|
||||||
{
|
{
|
||||||
bool wasEmpty;
|
bool wasEmpty;
|
||||||
{
|
{
|
||||||
|
@ -184,7 +184,7 @@ CTCPSocket::write(const void* buffer, UInt32 n)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CTCPSocket::flush()
|
TCPSocket::flush()
|
||||||
{
|
{
|
||||||
Lock lock(&m_mutex);
|
Lock lock(&m_mutex);
|
||||||
while (m_flushed == false) {
|
while (m_flushed == false) {
|
||||||
|
@ -193,7 +193,7 @@ CTCPSocket::flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CTCPSocket::shutdownInput()
|
TCPSocket::shutdownInput()
|
||||||
{
|
{
|
||||||
bool useNewJob = false;
|
bool useNewJob = false;
|
||||||
{
|
{
|
||||||
|
@ -220,7 +220,7 @@ CTCPSocket::shutdownInput()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CTCPSocket::shutdownOutput()
|
TCPSocket::shutdownOutput()
|
||||||
{
|
{
|
||||||
bool useNewJob = false;
|
bool useNewJob = false;
|
||||||
{
|
{
|
||||||
|
@ -247,21 +247,21 @@ CTCPSocket::shutdownOutput()
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CTCPSocket::isReady() const
|
TCPSocket::isReady() const
|
||||||
{
|
{
|
||||||
Lock lock(&m_mutex);
|
Lock lock(&m_mutex);
|
||||||
return (m_inputBuffer.getSize() > 0);
|
return (m_inputBuffer.getSize() > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt32
|
UInt32
|
||||||
CTCPSocket::getSize() const
|
TCPSocket::getSize() const
|
||||||
{
|
{
|
||||||
Lock lock(&m_mutex);
|
Lock lock(&m_mutex);
|
||||||
return m_inputBuffer.getSize();
|
return m_inputBuffer.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CTCPSocket::connect(const NetworkAddress& addr)
|
TCPSocket::connect(const NetworkAddress& addr)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
Lock lock(&m_mutex);
|
Lock lock(&m_mutex);
|
||||||
|
@ -290,7 +290,7 @@ CTCPSocket::connect(const NetworkAddress& addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CTCPSocket::init()
|
TCPSocket::init()
|
||||||
{
|
{
|
||||||
// default state
|
// default state
|
||||||
m_connected = false;
|
m_connected = false;
|
||||||
|
@ -316,7 +316,7 @@ CTCPSocket::init()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CTCPSocket::setJob(ISocketMultiplexerJob* job)
|
TCPSocket::setJob(ISocketMultiplexerJob* job)
|
||||||
{
|
{
|
||||||
// multiplexer will delete the old job
|
// multiplexer will delete the old job
|
||||||
if (job == NULL) {
|
if (job == NULL) {
|
||||||
|
@ -328,7 +328,7 @@ CTCPSocket::setJob(ISocketMultiplexerJob* job)
|
||||||
}
|
}
|
||||||
|
|
||||||
ISocketMultiplexerJob*
|
ISocketMultiplexerJob*
|
||||||
CTCPSocket::newJob()
|
TCPSocket::newJob()
|
||||||
{
|
{
|
||||||
// note -- must have m_mutex locked on entry
|
// note -- must have m_mutex locked on entry
|
||||||
|
|
||||||
|
@ -340,23 +340,23 @@ CTCPSocket::newJob()
|
||||||
if (!(m_readable || m_writable)) {
|
if (!(m_readable || m_writable)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return new TSocketMultiplexerMethodJob<CTCPSocket>(
|
return new TSocketMultiplexerMethodJob<TCPSocket>(
|
||||||
this, &CTCPSocket::serviceConnecting,
|
this, &TCPSocket::serviceConnecting,
|
||||||
m_socket, m_readable, m_writable);
|
m_socket, m_readable, m_writable);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!(m_readable || (m_writable && (m_outputBuffer.getSize() > 0)))) {
|
if (!(m_readable || (m_writable && (m_outputBuffer.getSize() > 0)))) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return new TSocketMultiplexerMethodJob<CTCPSocket>(
|
return new TSocketMultiplexerMethodJob<TCPSocket>(
|
||||||
this, &CTCPSocket::serviceConnected,
|
this, &TCPSocket::serviceConnected,
|
||||||
m_socket, m_readable,
|
m_socket, m_readable,
|
||||||
m_writable && (m_outputBuffer.getSize() > 0));
|
m_writable && (m_outputBuffer.getSize() > 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CTCPSocket::sendConnectionFailedEvent(const char* msg)
|
TCPSocket::sendConnectionFailedEvent(const char* msg)
|
||||||
{
|
{
|
||||||
ConnectionFailedInfo* info = new ConnectionFailedInfo(msg);
|
ConnectionFailedInfo* info = new ConnectionFailedInfo(msg);
|
||||||
m_events->addEvent(Event(m_events->forIDataSocket().connectionFailed(),
|
m_events->addEvent(Event(m_events->forIDataSocket().connectionFailed(),
|
||||||
|
@ -364,13 +364,13 @@ CTCPSocket::sendConnectionFailedEvent(const char* msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CTCPSocket::sendEvent(Event::Type type)
|
TCPSocket::sendEvent(Event::Type type)
|
||||||
{
|
{
|
||||||
m_events->addEvent(Event(type, getEventTarget(), NULL));
|
m_events->addEvent(Event(type, getEventTarget(), NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CTCPSocket::onConnected()
|
TCPSocket::onConnected()
|
||||||
{
|
{
|
||||||
m_connected = true;
|
m_connected = true;
|
||||||
m_readable = true;
|
m_readable = true;
|
||||||
|
@ -378,14 +378,14 @@ CTCPSocket::onConnected()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CTCPSocket::onInputShutdown()
|
TCPSocket::onInputShutdown()
|
||||||
{
|
{
|
||||||
m_inputBuffer.pop(m_inputBuffer.getSize());
|
m_inputBuffer.pop(m_inputBuffer.getSize());
|
||||||
m_readable = false;
|
m_readable = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CTCPSocket::onOutputShutdown()
|
TCPSocket::onOutputShutdown()
|
||||||
{
|
{
|
||||||
m_outputBuffer.pop(m_outputBuffer.getSize());
|
m_outputBuffer.pop(m_outputBuffer.getSize());
|
||||||
m_writable = false;
|
m_writable = false;
|
||||||
|
@ -396,7 +396,7 @@ CTCPSocket::onOutputShutdown()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CTCPSocket::onDisconnected()
|
TCPSocket::onDisconnected()
|
||||||
{
|
{
|
||||||
// disconnected
|
// disconnected
|
||||||
onInputShutdown();
|
onInputShutdown();
|
||||||
|
@ -405,7 +405,7 @@ CTCPSocket::onDisconnected()
|
||||||
}
|
}
|
||||||
|
|
||||||
ISocketMultiplexerJob*
|
ISocketMultiplexerJob*
|
||||||
CTCPSocket::serviceConnecting(ISocketMultiplexerJob* job,
|
TCPSocket::serviceConnecting(ISocketMultiplexerJob* job,
|
||||||
bool, bool write, bool error)
|
bool, bool write, bool error)
|
||||||
{
|
{
|
||||||
Lock lock(&m_mutex);
|
Lock lock(&m_mutex);
|
||||||
|
@ -449,7 +449,7 @@ CTCPSocket::serviceConnecting(ISocketMultiplexerJob* job,
|
||||||
}
|
}
|
||||||
|
|
||||||
ISocketMultiplexerJob*
|
ISocketMultiplexerJob*
|
||||||
CTCPSocket::serviceConnected(ISocketMultiplexerJob* job,
|
TCPSocket::serviceConnected(ISocketMultiplexerJob* job,
|
||||||
bool read, bool write, bool error)
|
bool read, bool write, bool error)
|
||||||
{
|
{
|
||||||
Lock lock(&m_mutex);
|
Lock lock(&m_mutex);
|
||||||
|
@ -467,7 +467,17 @@ CTCPSocket::serviceConnected(ISocketMultiplexerJob* job,
|
||||||
// write data
|
// write data
|
||||||
UInt32 n = m_outputBuffer.getSize();
|
UInt32 n = m_outputBuffer.getSize();
|
||||||
const void* buffer = m_outputBuffer.peek(n);
|
const void* buffer = m_outputBuffer.peek(n);
|
||||||
|
if (isSecure()) {
|
||||||
|
if (isSecureReady()) {
|
||||||
|
n = secureWrite(buffer, n);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return job;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
n = (UInt32)ARCH->writeSocket(m_socket, buffer, n);
|
n = (UInt32)ARCH->writeSocket(m_socket, buffer, n);
|
||||||
|
}
|
||||||
|
|
||||||
// discard written data
|
// discard written data
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
|
@ -510,14 +520,34 @@ CTCPSocket::serviceConnected(ISocketMultiplexerJob* job,
|
||||||
if (read && m_readable) {
|
if (read && m_readable) {
|
||||||
try {
|
try {
|
||||||
UInt8 buffer[4096];
|
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) {
|
if (n > 0) {
|
||||||
bool wasEmpty = (m_inputBuffer.getSize() == 0);
|
bool wasEmpty = (m_inputBuffer.getSize() == 0);
|
||||||
|
|
||||||
// slurp up as much as possible
|
// slurp up as much as possible
|
||||||
do {
|
do {
|
||||||
m_inputBuffer.write(buffer, (UInt32)n);
|
m_inputBuffer.write(buffer, (UInt32)n);
|
||||||
|
|
||||||
|
if (isSecure() && isSecureReady()) {
|
||||||
|
n = secureRead(buffer, sizeof(buffer));
|
||||||
|
}
|
||||||
|
else {
|
||||||
n = ARCH->readSocket(m_socket, buffer, sizeof(buffer));
|
n = ARCH->readSocket(m_socket, buffer, sizeof(buffer));
|
||||||
|
}
|
||||||
|
|
||||||
} while (n > 0);
|
} while (n > 0);
|
||||||
|
|
||||||
// send input ready if input buffer was empty
|
// send input ready if input buffer was empty
|
||||||
|
|
|
@ -34,11 +34,11 @@ class SocketMultiplexer;
|
||||||
/*!
|
/*!
|
||||||
A data socket using TCP.
|
A data socket using TCP.
|
||||||
*/
|
*/
|
||||||
class CTCPSocket : public IDataSocket {
|
class TCPSocket : public IDataSocket {
|
||||||
public:
|
public:
|
||||||
CTCPSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer);
|
TCPSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer);
|
||||||
CTCPSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer, ArchSocket socket);
|
TCPSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer, ArchSocket socket);
|
||||||
~CTCPSocket();
|
virtual ~TCPSocket();
|
||||||
|
|
||||||
// ISocket overrides
|
// ISocket overrides
|
||||||
virtual void bind(const NetworkAddress&);
|
virtual void bind(const NetworkAddress&);
|
||||||
|
@ -57,14 +57,31 @@ public:
|
||||||
// IDataSocket overrides
|
// IDataSocket overrides
|
||||||
virtual void connect(const NetworkAddress&);
|
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:
|
private:
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
void setJob(ISocketMultiplexerJob*);
|
|
||||||
ISocketMultiplexerJob* newJob();
|
|
||||||
void sendConnectionFailedEvent(const char*);
|
void sendConnectionFailedEvent(const char*);
|
||||||
void sendEvent(Event::Type);
|
|
||||||
|
|
||||||
void onConnected();
|
void onConnected();
|
||||||
void onInputShutdown();
|
void onInputShutdown();
|
||||||
void onOutputShutdown();
|
void onOutputShutdown();
|
||||||
|
|
|
@ -20,31 +20,65 @@
|
||||||
|
|
||||||
#include "net/TCPSocket.h"
|
#include "net/TCPSocket.h"
|
||||||
#include "net/TCPListenSocket.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_events(events),
|
||||||
m_socketMultiplexer(socketMultiplexer)
|
m_socketMultiplexer(socketMultiplexer)
|
||||||
{
|
{
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
CTCPSocketFactory::~CTCPSocketFactory()
|
TCPSocketFactory::~TCPSocketFactory()
|
||||||
{
|
{
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
IDataSocket*
|
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*
|
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,14 +24,16 @@ class IEventQueue;
|
||||||
class SocketMultiplexer;
|
class SocketMultiplexer;
|
||||||
|
|
||||||
//! Socket factory for TCP sockets
|
//! Socket factory for TCP sockets
|
||||||
class CTCPSocketFactory : public ISocketFactory {
|
class TCPSocketFactory : public ISocketFactory {
|
||||||
public:
|
public:
|
||||||
CTCPSocketFactory(IEventQueue* events, SocketMultiplexer* socketMultiplexer);
|
TCPSocketFactory(IEventQueue* events, SocketMultiplexer* socketMultiplexer);
|
||||||
virtual ~CTCPSocketFactory();
|
virtual ~TCPSocketFactory();
|
||||||
|
|
||||||
// ISocketFactory overrides
|
// ISocketFactory overrides
|
||||||
virtual IDataSocket* create() const;
|
virtual IDataSocket*
|
||||||
virtual IListenSocket* createListen() const;
|
create(bool secure) const;
|
||||||
|
virtual IListenSocket*
|
||||||
|
createListen(bool secure) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IEventQueue* m_events;
|
IEventQueue* m_events;
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
add_subdirectory(ns)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
add_subdirectory(winmmjoy)
|
add_subdirectory(winmmjoy)
|
||||||
endif()
|
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
|
* synergy -- mouse and keyboard sharing utility
|
||||||
* Copyright (C) 2012 Synergy Si Ltd.
|
* Copyright (C) 2015 Synergy Si Ltd.
|
||||||
* Copyright (C) 2002 Chris Schoeneman
|
|
||||||
*
|
*
|
||||||
* This package is free software; you can redistribute it and/or
|
* This package is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -18,21 +17,26 @@
|
||||||
|
|
||||||
#pragma once
|
#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
|
class SecureListenSocket : public TCPListenSocket{
|
||||||
/*!
|
|
||||||
This interface provides factory methods to create stream filters.
|
|
||||||
*/
|
|
||||||
class IStreamFilterFactory : public IInterface {
|
|
||||||
public:
|
public:
|
||||||
//! Create filter
|
SecureListenSocket(IEventQueue* events,
|
||||||
/*!
|
SocketMultiplexer* socketMultiplexer);
|
||||||
Create and return a stream filter on \p stream. The caller must
|
~SecureListenSocket();
|
||||||
delete the returned object.
|
|
||||||
*/
|
// IListenSocket overrides
|
||||||
virtual synergy::IStream*
|
virtual IDataSocket*
|
||||||
create(synergy::IStream* stream, bool adoptStream) = 0;
|
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
|
TARGET winmmjoy
|
||||||
POST_BUILD
|
POST_BUILD
|
||||||
COMMAND xcopy /Y /Q
|
COMMAND xcopy /Y /Q
|
||||||
..\\..\\..\\..\\lib\\${CMAKE_CFG_INTDIR}\\winmmjoy.*
|
..\\..\\..\\..\\..\\lib\\${CMAKE_CFG_INTDIR}\\winmmjoy.*
|
||||||
..\\..\\..\\..\\bin\\${CMAKE_CFG_INTDIR}\\plugins\\
|
..\\..\\..\\..\\..\\bin\\${CMAKE_CFG_INTDIR}\\plugins\\
|
||||||
)
|
)
|
|
@ -36,22 +36,23 @@ static void (*s_log)(const char*) = NULL;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
|
void
|
||||||
|
init(void* log, void* arch)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
init(void (*sendEvent)(const char*, void*), void (*log)(const char*))
|
initEvent(void (*sendEvent)(const char*, void*))
|
||||||
{
|
{
|
||||||
s_sendEvent = sendEvent;
|
s_sendEvent = sendEvent;
|
||||||
s_log = log;
|
|
||||||
LOG("init");
|
|
||||||
CreateThread(NULL, 0, mainLoop, NULL, 0, NULL);
|
CreateThread(NULL, 0, mainLoop, NULL, 0, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
void
|
||||||
cleanup()
|
cleanup()
|
||||||
{
|
{
|
||||||
LOG("cleanup");
|
|
||||||
s_running = false;
|
s_running = false;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -29,8 +29,9 @@
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
WINMMJOY_API int init(void (*sendEvent)(const char*, void*), void (*log)(const char*));
|
WINMMJOY_API void init(void* log, void* arch);
|
||||||
WINMMJOY_API int cleanup();
|
WINMMJOY_API int initEvent(void (*sendEvent)(const char*, void*));
|
||||||
|
WINMMJOY_API void cleanup();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
#include "synergy/IClient.h"
|
#include "synergy/IClient.h"
|
||||||
#include "base/String.h"
|
#include "base/String.h"
|
||||||
|
|
||||||
|
namespace synergy { class IStream; }
|
||||||
|
|
||||||
//! Generic proxy for client or primary
|
//! Generic proxy for client or primary
|
||||||
class BaseClientProxy : public IClient {
|
class BaseClientProxy : public IClient {
|
||||||
public:
|
public:
|
||||||
|
@ -82,6 +84,8 @@ public:
|
||||||
size_t size) = 0;
|
size_t size) = 0;
|
||||||
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize) = 0;
|
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize) = 0;
|
||||||
virtual String getName() const;
|
virtual String getName() const;
|
||||||
|
virtual synergy::IStream*
|
||||||
|
getStream() const = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
String m_name;
|
String m_name;
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
#include "net/XSocket.h"
|
#include "net/XSocket.h"
|
||||||
#include "io/CryptoStream.h"
|
#include "io/CryptoStream.h"
|
||||||
#include "io/CryptoOptions.h"
|
#include "io/CryptoOptions.h"
|
||||||
#include "io/IStreamFilterFactory.h"
|
|
||||||
#include "base/Log.h"
|
#include "base/Log.h"
|
||||||
#include "base/IEventQueue.h"
|
#include "base/IEventQueue.h"
|
||||||
#include "base/TMethodEventJob.h"
|
#include "base/TMethodEventJob.h"
|
||||||
|
@ -36,13 +35,17 @@
|
||||||
// ClientListener
|
// ClientListener
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#if defined _WIN32
|
||||||
|
static const char s_networkSecurity[] = { "ns" };
|
||||||
|
#else
|
||||||
|
static const char s_networkSecurity[] = { "libns" };
|
||||||
|
#endif
|
||||||
|
|
||||||
ClientListener::ClientListener(const NetworkAddress& address,
|
ClientListener::ClientListener(const NetworkAddress& address,
|
||||||
ISocketFactory* socketFactory,
|
ISocketFactory* socketFactory,
|
||||||
IStreamFilterFactory* streamFilterFactory,
|
|
||||||
const CryptoOptions& crypto,
|
const CryptoOptions& crypto,
|
||||||
IEventQueue* events) :
|
IEventQueue* events) :
|
||||||
m_socketFactory(socketFactory),
|
m_socketFactory(socketFactory),
|
||||||
m_streamFilterFactory(streamFilterFactory),
|
|
||||||
m_server(NULL),
|
m_server(NULL),
|
||||||
m_crypto(crypto),
|
m_crypto(crypto),
|
||||||
m_events(events)
|
m_events(events)
|
||||||
|
@ -51,22 +54,21 @@ ClientListener::ClientListener(const NetworkAddress& address,
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// create listen socket
|
// 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
|
// bind listen address
|
||||||
LOG((CLOG_DEBUG1 "binding listen socket"));
|
LOG((CLOG_DEBUG1 "binding listen socket"));
|
||||||
m_listen->bind(address);
|
m_listen->bind(address);
|
||||||
}
|
}
|
||||||
catch (XSocketAddressInUse&) {
|
catch (XSocketAddressInUse&) {
|
||||||
delete m_listen;
|
cleanupListenSocket();
|
||||||
delete m_socketFactory;
|
delete m_socketFactory;
|
||||||
delete m_streamFilterFactory;
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
catch (XBase&) {
|
catch (XBase&) {
|
||||||
delete m_listen;
|
cleanupListenSocket();
|
||||||
delete m_socketFactory;
|
delete m_socketFactory;
|
||||||
delete m_streamFilterFactory;
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
LOG((CLOG_DEBUG1 "listening for clients"));
|
LOG((CLOG_DEBUG1 "listening for clients"));
|
||||||
|
@ -102,9 +104,8 @@ ClientListener::~ClientListener()
|
||||||
}
|
}
|
||||||
|
|
||||||
m_events->removeHandler(m_events->forIListenSocket().connecting(), m_listen);
|
m_events->removeHandler(m_events->forIListenSocket().connecting(), m_listen);
|
||||||
delete m_listen;
|
cleanupListenSocket();
|
||||||
delete m_socketFactory;
|
delete m_socketFactory;
|
||||||
delete m_streamFilterFactory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -114,6 +115,12 @@ ClientListener::setServer(Server* server)
|
||||||
m_server = server;
|
m_server = server;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ClientListener::deleteSocket(void* socket)
|
||||||
|
{
|
||||||
|
m_listen->deleteSocket(socket);
|
||||||
|
}
|
||||||
|
|
||||||
ClientProxy*
|
ClientProxy*
|
||||||
ClientListener::getNextClient()
|
ClientListener::getNextClient()
|
||||||
{
|
{
|
||||||
|
@ -130,17 +137,18 @@ void
|
||||||
ClientListener::handleClientConnecting(const Event&, void*)
|
ClientListener::handleClientConnecting(const Event&, void*)
|
||||||
{
|
{
|
||||||
// accept client connection
|
// accept client connection
|
||||||
synergy::IStream* stream = m_listen->accept();
|
IDataSocket* socket = m_listen->accept();
|
||||||
|
synergy::IStream* stream = socket;
|
||||||
|
|
||||||
if (stream == NULL) {
|
if (stream == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG((CLOG_NOTE "accepted client connection"));
|
LOG((CLOG_NOTE "accepted client connection"));
|
||||||
|
|
||||||
// filter socket messages, including a packetizing filter
|
// filter socket messages, including a packetizing filter
|
||||||
if (m_streamFilterFactory != NULL) {
|
bool adopt = !m_useSecureNetwork;
|
||||||
stream = m_streamFilterFactory->create(stream, true);
|
stream = new PacketStreamFilter(m_events, stream, adopt);
|
||||||
}
|
|
||||||
stream = new PacketStreamFilter(m_events, stream, true);
|
|
||||||
|
|
||||||
if (m_crypto.m_mode != kDisabled) {
|
if (m_crypto.m_mode != kDisabled) {
|
||||||
CryptoStream* cryptoStream = new CryptoStream(
|
CryptoStream* cryptoStream = new CryptoStream(
|
||||||
|
@ -150,6 +158,12 @@ ClientListener::handleClientConnecting(const Event&, void*)
|
||||||
|
|
||||||
assert(m_server != NULL);
|
assert(m_server != NULL);
|
||||||
|
|
||||||
|
if (m_useSecureNetwork) {
|
||||||
|
while(!socket->isReady()) {
|
||||||
|
ARCH->sleep(.5f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// create proxy for unknown client
|
// create proxy for unknown client
|
||||||
ClientProxyUnknown* client = new ClientProxyUnknown(stream, 30.0, m_server, m_events);
|
ClientProxyUnknown* client = new ClientProxyUnknown(stream, 30.0, m_server, m_events);
|
||||||
m_newClients.insert(client);
|
m_newClients.insert(client);
|
||||||
|
@ -174,6 +188,7 @@ ClientListener::handleUnknownClient(const Event&, void* vclient)
|
||||||
|
|
||||||
// get the real client proxy and install it
|
// get the real client proxy and install it
|
||||||
ClientProxy* client = unknownClient->orphanClientProxy();
|
ClientProxy* client = unknownClient->orphanClientProxy();
|
||||||
|
bool handshakeOk = true;
|
||||||
if (client != NULL) {
|
if (client != NULL) {
|
||||||
// handshake was successful
|
// handshake was successful
|
||||||
m_waitingClients.push_back(client);
|
m_waitingClients.push_back(client);
|
||||||
|
@ -185,12 +200,25 @@ ClientListener::handleUnknownClient(const Event&, void* vclient)
|
||||||
&ClientListener::handleClientDisconnected,
|
&ClientListener::handleClientDisconnected,
|
||||||
client));
|
client));
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
handshakeOk = false;
|
||||||
|
}
|
||||||
|
|
||||||
// now finished with unknown client
|
// now finished with unknown client
|
||||||
m_events->removeHandler(m_events->forClientProxyUnknown().success(), client);
|
m_events->removeHandler(m_events->forClientProxyUnknown().success(), client);
|
||||||
m_events->removeHandler(m_events->forClientProxyUnknown().failure(), client);
|
m_events->removeHandler(m_events->forClientProxyUnknown().failure(), client);
|
||||||
m_newClients.erase(unknownClient);
|
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;
|
delete unknownClient;
|
||||||
|
|
||||||
|
if (m_useSecureNetwork && !handshakeOk) {
|
||||||
|
deleteSocket(socket);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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 NetworkAddress;
|
||||||
class IListenSocket;
|
class IListenSocket;
|
||||||
class ISocketFactory;
|
class ISocketFactory;
|
||||||
class IStreamFilterFactory;
|
|
||||||
class Server;
|
class Server;
|
||||||
class IEventQueue;
|
class IEventQueue;
|
||||||
|
|
||||||
|
@ -39,7 +38,6 @@ public:
|
||||||
// The factories are adopted.
|
// The factories are adopted.
|
||||||
ClientListener(const NetworkAddress&,
|
ClientListener(const NetworkAddress&,
|
||||||
ISocketFactory*,
|
ISocketFactory*,
|
||||||
IStreamFilterFactory*,
|
|
||||||
const CryptoOptions& crypto,
|
const CryptoOptions& crypto,
|
||||||
IEventQueue* events);
|
IEventQueue* events);
|
||||||
~ClientListener();
|
~ClientListener();
|
||||||
|
@ -51,6 +49,8 @@ public:
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
|
void deleteSocket(void* socket);
|
||||||
|
|
||||||
//! @name accessors
|
//! @name accessors
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
|
@ -73,16 +73,18 @@ private:
|
||||||
void handleUnknownClient(const Event&, void*);
|
void handleUnknownClient(const Event&, void*);
|
||||||
void handleClientDisconnected(const Event&, void*);
|
void handleClientDisconnected(const Event&, void*);
|
||||||
|
|
||||||
|
void cleanupListenSocket();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::set<ClientProxyUnknown*> NewClients;
|
typedef std::set<ClientProxyUnknown*> NewClients;
|
||||||
typedef std::deque<ClientProxy*> WaitingClients;
|
typedef std::deque<ClientProxy*> WaitingClients;
|
||||||
|
|
||||||
IListenSocket* m_listen;
|
IListenSocket* m_listen;
|
||||||
ISocketFactory* m_socketFactory;
|
ISocketFactory* m_socketFactory;
|
||||||
IStreamFilterFactory* m_streamFilterFactory;
|
|
||||||
NewClients m_newClients;
|
NewClients m_newClients;
|
||||||
WaitingClients m_waitingClients;
|
WaitingClients m_waitingClients;
|
||||||
Server* m_server;
|
Server* m_server;
|
||||||
CryptoOptions m_crypto;
|
CryptoOptions m_crypto;
|
||||||
IEventQueue* m_events;
|
IEventQueue* m_events;
|
||||||
|
bool m_useSecureNetwork;
|
||||||
};
|
};
|
||||||
|
|
|
@ -43,6 +43,9 @@ public:
|
||||||
*/
|
*/
|
||||||
ClientProxy* orphanClientProxy();
|
ClientProxy* orphanClientProxy();
|
||||||
|
|
||||||
|
//! Get the stream
|
||||||
|
synergy::IStream* getStream() { return m_stream; }
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -146,6 +146,9 @@ public:
|
||||||
virtual void sendDragInfo(UInt32 fileCount, const char* info, size_t size);
|
virtual void sendDragInfo(UInt32 fileCount, const char* info, size_t size);
|
||||||
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize);
|
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize);
|
||||||
|
|
||||||
|
virtual synergy::IStream*
|
||||||
|
getStream() const { return NULL; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
synergy::Screen* m_screen;
|
synergy::Screen* m_screen;
|
||||||
bool m_clipboardDirty[kClipboardEnd];
|
bool m_clipboardDirty[kClipboardEnd];
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "server/ClientProxy.h"
|
#include "server/ClientProxy.h"
|
||||||
#include "server/ClientProxyUnknown.h"
|
#include "server/ClientProxyUnknown.h"
|
||||||
#include "server/PrimaryClient.h"
|
#include "server/PrimaryClient.h"
|
||||||
|
#include "server/ClientListener.h"
|
||||||
#include "synergy/IPlatformScreen.h"
|
#include "synergy/IPlatformScreen.h"
|
||||||
#include "synergy/DropHelper.h"
|
#include "synergy/DropHelper.h"
|
||||||
#include "synergy/option_types.h"
|
#include "synergy/option_types.h"
|
||||||
|
@ -30,6 +31,8 @@
|
||||||
#include "synergy/FileChunker.h"
|
#include "synergy/FileChunker.h"
|
||||||
#include "synergy/KeyState.h"
|
#include "synergy/KeyState.h"
|
||||||
#include "synergy/Screen.h"
|
#include "synergy/Screen.h"
|
||||||
|
#include "synergy/PacketStreamFilter.h"
|
||||||
|
#include "net/TCPSocket.h"
|
||||||
#include "net/IDataSocket.h"
|
#include "net/IDataSocket.h"
|
||||||
#include "net/IListenSocket.h"
|
#include "net/IListenSocket.h"
|
||||||
#include "net/XSocket.h"
|
#include "net/XSocket.h"
|
||||||
|
@ -1358,7 +1361,11 @@ Server::handleClientDisconnected(const Event&, void* vclient)
|
||||||
BaseClientProxy* client = reinterpret_cast<BaseClientProxy*>(vclient);
|
BaseClientProxy* client = reinterpret_cast<BaseClientProxy*>(vclient);
|
||||||
removeActiveClient(client);
|
removeActiveClient(client);
|
||||||
removeOldClient(client);
|
removeOldClient(client);
|
||||||
|
|
||||||
|
PacketStreamFilter* streamFileter = dynamic_cast<PacketStreamFilter*>(client->getStream());
|
||||||
|
TCPSocket* socket = dynamic_cast<TCPSocket*>(streamFileter->getStream());
|
||||||
delete client;
|
delete client;
|
||||||
|
m_clientListener->deleteSocket(socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1368,7 +1375,10 @@ Server::handleClientCloseTimeout(const Event&, void* vclient)
|
||||||
BaseClientProxy* client = reinterpret_cast<BaseClientProxy*>(vclient);
|
BaseClientProxy* client = reinterpret_cast<BaseClientProxy*>(vclient);
|
||||||
LOG((CLOG_NOTE "forced disconnection of client \"%s\"", getName(client).c_str()));
|
LOG((CLOG_NOTE "forced disconnection of client \"%s\"", getName(client).c_str()));
|
||||||
removeOldClient(client);
|
removeOldClient(client);
|
||||||
|
PacketStreamFilter* streamFileter = dynamic_cast<PacketStreamFilter*>(client->getStream());
|
||||||
|
TCPSocket* socket = dynamic_cast<TCPSocket*>(streamFileter->getStream());
|
||||||
delete client;
|
delete client;
|
||||||
|
m_clientListener->deleteSocket(socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -39,6 +39,7 @@ class InputFilter;
|
||||||
namespace synergy { class Screen; }
|
namespace synergy { class Screen; }
|
||||||
class IEventQueue;
|
class IEventQueue;
|
||||||
class Thread;
|
class Thread;
|
||||||
|
class ClientListener;
|
||||||
|
|
||||||
//! Synergy server
|
//! Synergy server
|
||||||
/*!
|
/*!
|
||||||
|
@ -155,6 +156,9 @@ public:
|
||||||
//! Received dragging information from client
|
//! Received dragging information from client
|
||||||
void dragInfoReceived(UInt32 fileNum, String content);
|
void dragInfoReceived(UInt32 fileNum, String content);
|
||||||
|
|
||||||
|
//! Store ClientListener pointer
|
||||||
|
void setListener(ClientListener* p) { m_clientListener = p; }
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
//! @name accessors
|
//! @name accessors
|
||||||
//@{
|
//@{
|
||||||
|
@ -474,4 +478,6 @@ private:
|
||||||
|
|
||||||
Thread* m_getDragInfoThread;
|
Thread* m_getDragInfoThread;
|
||||||
bool m_waitDragInfoThread;
|
bool m_waitDragInfoThread;
|
||||||
|
|
||||||
|
ClientListener* m_clientListener;
|
||||||
};
|
};
|
||||||
|
|
|
@ -326,7 +326,7 @@ ClientApp::handleClientDisconnected(const Event&, void*)
|
||||||
m_events->addEvent(Event(Event::kQuit));
|
m_events->addEvent(Event(Event::kQuit));
|
||||||
}
|
}
|
||||||
else if (!m_suspended) {
|
else if (!m_suspended) {
|
||||||
m_client->connect();
|
scheduleClientRestart(nextRestartTimeout());
|
||||||
}
|
}
|
||||||
updateStatus();
|
updateStatus();
|
||||||
}
|
}
|
||||||
|
@ -340,8 +340,7 @@ ClientApp::openClient(const String& name, const NetworkAddress& address,
|
||||||
m_events,
|
m_events,
|
||||||
name,
|
name,
|
||||||
address,
|
address,
|
||||||
new CTCPSocketFactory(m_events, getSocketMultiplexer()),
|
new TCPSocketFactory(m_events, getSocketMultiplexer()),
|
||||||
NULL,
|
|
||||||
screen,
|
screen,
|
||||||
crypto,
|
crypto,
|
||||||
args().m_enableDragDrop);
|
args().m_enableDragDrop);
|
||||||
|
@ -458,6 +457,11 @@ ClientApp::mainLoop()
|
||||||
SocketMultiplexer multiplexer;
|
SocketMultiplexer multiplexer;
|
||||||
setSocketMultiplexer(&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
|
// start client, etc
|
||||||
appUtil().startNode();
|
appUtil().startNode();
|
||||||
|
|
||||||
|
@ -467,8 +471,8 @@ ClientApp::mainLoop()
|
||||||
initIpcClient();
|
initIpcClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// load all available plugins.
|
// init event for all available plugins.
|
||||||
ARCH->plugin().init(m_clientScreen->getEventTarget(), m_events);
|
ARCH->plugin().initEvent(m_clientScreen->getEventTarget(), m_events);
|
||||||
|
|
||||||
// run event loop. if startClient() failed we're supposed to retry
|
// run event loop. if startClient() failed we're supposed to retry
|
||||||
// later. the timer installed by startClient() will take care of
|
// later. the timer installed by startClient() will take care of
|
||||||
|
@ -504,6 +508,9 @@ ClientApp::mainLoop()
|
||||||
cleanupIpcClient();
|
cleanupIpcClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// unload all plugins.
|
||||||
|
ARCH->plugin().unload();
|
||||||
|
|
||||||
return kExitSuccess;
|
return kExitSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,7 @@ DragInformation::getDragFileExtension(String filename)
|
||||||
int
|
int
|
||||||
DragInformation::setupDragInfo(DragFileList& fileList, String& output)
|
DragInformation::setupDragInfo(DragFileList& fileList, String& output)
|
||||||
{
|
{
|
||||||
int size = fileList.size();
|
int size = static_cast<int>(fileList.size());
|
||||||
for (int i = 0; i < size; ++i) {
|
for (int i = 0; i < size; ++i) {
|
||||||
output.append(fileList.at(i).getFilename());
|
output.append(fileList.at(i).getFilename());
|
||||||
output.append(",");
|
output.append(",");
|
||||||
|
|
|
@ -338,8 +338,8 @@ void
|
||||||
ServerApp::stopServer()
|
ServerApp::stopServer()
|
||||||
{
|
{
|
||||||
if (m_serverState == kStarted) {
|
if (m_serverState == kStarted) {
|
||||||
closeClientListener(m_listener);
|
|
||||||
closeServer(m_server);
|
closeServer(m_server);
|
||||||
|
closeClientListener(m_listener);
|
||||||
m_server = NULL;
|
m_server = NULL;
|
||||||
m_listener = NULL;
|
m_listener = NULL;
|
||||||
m_serverState = kInitialized;
|
m_serverState = kInitialized;
|
||||||
|
@ -543,6 +543,7 @@ ServerApp::startServer()
|
||||||
listener = openClientListener(args().m_config->getSynergyAddress());
|
listener = openClientListener(args().m_config->getSynergyAddress());
|
||||||
m_server = openServer(*args().m_config, m_primaryClient);
|
m_server = openServer(*args().m_config, m_primaryClient);
|
||||||
listener->setServer(m_server);
|
listener->setServer(m_server);
|
||||||
|
m_server->setListener(listener);
|
||||||
m_listener = listener;
|
m_listener = listener;
|
||||||
updateStatus();
|
updateStatus();
|
||||||
LOG((CLOG_NOTE "started server, waiting for clients"));
|
LOG((CLOG_NOTE "started server, waiting for clients"));
|
||||||
|
@ -631,8 +632,7 @@ ServerApp::openClientListener(const NetworkAddress& address)
|
||||||
{
|
{
|
||||||
ClientListener* listen = new ClientListener(
|
ClientListener* listen = new ClientListener(
|
||||||
address,
|
address,
|
||||||
new CTCPSocketFactory(m_events, getSocketMultiplexer()),
|
new TCPSocketFactory(m_events, getSocketMultiplexer()),
|
||||||
NULL,
|
|
||||||
args().m_crypto,
|
args().m_crypto,
|
||||||
m_events);
|
m_events);
|
||||||
|
|
||||||
|
@ -707,6 +707,11 @@ ServerApp::mainLoop()
|
||||||
return kExitFailed;
|
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
|
// start server, etc
|
||||||
appUtil().startNode();
|
appUtil().startNode();
|
||||||
|
|
||||||
|
@ -716,8 +721,8 @@ ServerApp::mainLoop()
|
||||||
initIpcClient();
|
initIpcClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// load all available plugins.
|
// init event for all available plugins.
|
||||||
ARCH->plugin().init(m_serverScreen->getEventTarget(), m_events);
|
ARCH->plugin().initEvent(m_serverScreen->getEventTarget(), m_events);
|
||||||
|
|
||||||
// handle hangup signal by reloading the server's configuration
|
// handle hangup signal by reloading the server's configuration
|
||||||
ARCH->setSignalHandler(Arch::kHANGUP, &reloadSignalHandler, NULL);
|
ARCH->setSignalHandler(Arch::kHANGUP, &reloadSignalHandler, NULL);
|
||||||
|
@ -775,6 +780,9 @@ ServerApp::mainLoop()
|
||||||
cleanupIpcClient();
|
cleanupIpcClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// unload all plugins.
|
||||||
|
ARCH->plugin().unload();
|
||||||
|
|
||||||
return kExitSuccess;
|
return kExitSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -115,8 +115,8 @@ TEST_F(NetworkTests, sendToClient_mockData)
|
||||||
|
|
||||||
// server
|
// server
|
||||||
SocketMultiplexer serverSocketMultiplexer;
|
SocketMultiplexer serverSocketMultiplexer;
|
||||||
CTCPSocketFactory* serverSocketFactory = new CTCPSocketFactory(&m_events, &serverSocketMultiplexer);
|
TCPSocketFactory* serverSocketFactory = new TCPSocketFactory(&m_events, &serverSocketMultiplexer);
|
||||||
ClientListener listener(serverAddress, serverSocketFactory, NULL, cryptoOptions, &m_events);
|
ClientListener listener(serverAddress, serverSocketFactory, cryptoOptions, &m_events);
|
||||||
NiceMock<MockScreen> serverScreen;
|
NiceMock<MockScreen> serverScreen;
|
||||||
NiceMock<MockPrimaryClient> primaryClient;
|
NiceMock<MockPrimaryClient> primaryClient;
|
||||||
NiceMock<MockConfig> serverConfig;
|
NiceMock<MockConfig> serverConfig;
|
||||||
|
@ -137,12 +137,12 @@ TEST_F(NetworkTests, sendToClient_mockData)
|
||||||
// client
|
// client
|
||||||
NiceMock<MockScreen> clientScreen;
|
NiceMock<MockScreen> clientScreen;
|
||||||
SocketMultiplexer clientSocketMultiplexer;
|
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, getShape(_, _, _, _)).WillByDefault(Invoke(getScreenShape));
|
||||||
ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos));
|
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.adoptHandler(
|
||||||
m_events.forIScreen().fileRecieveCompleted(), &client,
|
m_events.forIScreen().fileRecieveCompleted(), &client,
|
||||||
|
@ -168,8 +168,8 @@ TEST_F(NetworkTests, sendToClient_mockFile)
|
||||||
|
|
||||||
// server
|
// server
|
||||||
SocketMultiplexer serverSocketMultiplexer;
|
SocketMultiplexer serverSocketMultiplexer;
|
||||||
CTCPSocketFactory* serverSocketFactory = new CTCPSocketFactory(&m_events, &serverSocketMultiplexer);
|
TCPSocketFactory* serverSocketFactory = new TCPSocketFactory(&m_events, &serverSocketMultiplexer);
|
||||||
ClientListener listener(serverAddress, serverSocketFactory, NULL, cryptoOptions, &m_events);
|
ClientListener listener(serverAddress, serverSocketFactory, cryptoOptions, &m_events);
|
||||||
NiceMock<MockScreen> serverScreen;
|
NiceMock<MockScreen> serverScreen;
|
||||||
NiceMock<MockPrimaryClient> primaryClient;
|
NiceMock<MockPrimaryClient> primaryClient;
|
||||||
NiceMock<MockConfig> serverConfig;
|
NiceMock<MockConfig> serverConfig;
|
||||||
|
@ -190,12 +190,12 @@ TEST_F(NetworkTests, sendToClient_mockFile)
|
||||||
// client
|
// client
|
||||||
NiceMock<MockScreen> clientScreen;
|
NiceMock<MockScreen> clientScreen;
|
||||||
SocketMultiplexer clientSocketMultiplexer;
|
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, getShape(_, _, _, _)).WillByDefault(Invoke(getScreenShape));
|
||||||
ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos));
|
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.adoptHandler(
|
||||||
m_events.forIScreen().fileRecieveCompleted(), &client,
|
m_events.forIScreen().fileRecieveCompleted(), &client,
|
||||||
|
@ -221,8 +221,8 @@ TEST_F(NetworkTests, sendToServer_mockData)
|
||||||
|
|
||||||
// server
|
// server
|
||||||
SocketMultiplexer serverSocketMultiplexer;
|
SocketMultiplexer serverSocketMultiplexer;
|
||||||
CTCPSocketFactory* serverSocketFactory = new CTCPSocketFactory(&m_events, &serverSocketMultiplexer);
|
TCPSocketFactory* serverSocketFactory = new TCPSocketFactory(&m_events, &serverSocketMultiplexer);
|
||||||
ClientListener listener(serverAddress, serverSocketFactory, NULL, cryptoOptions, &m_events);
|
ClientListener listener(serverAddress, serverSocketFactory, cryptoOptions, &m_events);
|
||||||
NiceMock<MockScreen> serverScreen;
|
NiceMock<MockScreen> serverScreen;
|
||||||
NiceMock<MockPrimaryClient> primaryClient;
|
NiceMock<MockPrimaryClient> primaryClient;
|
||||||
NiceMock<MockConfig> serverConfig;
|
NiceMock<MockConfig> serverConfig;
|
||||||
|
@ -238,12 +238,12 @@ TEST_F(NetworkTests, sendToServer_mockData)
|
||||||
// client
|
// client
|
||||||
NiceMock<MockScreen> clientScreen;
|
NiceMock<MockScreen> clientScreen;
|
||||||
SocketMultiplexer clientSocketMultiplexer;
|
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, getShape(_, _, _, _)).WillByDefault(Invoke(getScreenShape));
|
||||||
ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos));
|
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.adoptHandler(
|
||||||
m_events.forClientListener().connected(), &listener,
|
m_events.forClientListener().connected(), &listener,
|
||||||
|
@ -274,8 +274,8 @@ TEST_F(NetworkTests, sendToServer_mockFile)
|
||||||
|
|
||||||
// server
|
// server
|
||||||
SocketMultiplexer serverSocketMultiplexer;
|
SocketMultiplexer serverSocketMultiplexer;
|
||||||
CTCPSocketFactory* serverSocketFactory = new CTCPSocketFactory(&m_events, &serverSocketMultiplexer);
|
TCPSocketFactory* serverSocketFactory = new TCPSocketFactory(&m_events, &serverSocketMultiplexer);
|
||||||
ClientListener listener(serverAddress, serverSocketFactory, NULL, cryptoOptions, &m_events);
|
ClientListener listener(serverAddress, serverSocketFactory, cryptoOptions, &m_events);
|
||||||
NiceMock<MockScreen> serverScreen;
|
NiceMock<MockScreen> serverScreen;
|
||||||
NiceMock<MockPrimaryClient> primaryClient;
|
NiceMock<MockPrimaryClient> primaryClient;
|
||||||
NiceMock<MockConfig> serverConfig;
|
NiceMock<MockConfig> serverConfig;
|
||||||
|
@ -291,12 +291,12 @@ TEST_F(NetworkTests, sendToServer_mockFile)
|
||||||
// client
|
// client
|
||||||
NiceMock<MockScreen> clientScreen;
|
NiceMock<MockScreen> clientScreen;
|
||||||
SocketMultiplexer clientSocketMultiplexer;
|
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, getShape(_, _, _, _)).WillByDefault(Invoke(getScreenShape));
|
||||||
ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos));
|
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.adoptHandler(
|
||||||
m_events.forClientListener().connected(), &listener,
|
m_events.forClientListener().connected(), &listener,
|
||||||
|
|
Loading…
Reference in New Issue