From 1d7eb3f5cbf35bf69b6b8c47daa2e55775482ea7 Mon Sep 17 00:00:00 2001 From: XinyuHou Date: Fri, 9 Jan 2015 13:46:35 +0000 Subject: [PATCH] updated pluging loader for Windows #4313 --- src/lib/arch/IArchPlugin.h | 27 +++++++++- src/lib/arch/win32/ArchPluginWindows.cpp | 68 +++++++++++++++++++----- src/lib/arch/win32/ArchPluginWindows.h | 10 +++- src/lib/base/String.cpp | 11 ++++ src/lib/base/String.h | 6 +++ src/lib/client/Client.cpp | 15 +++++- src/lib/client/Client.h | 2 + src/lib/synergy/ClientApp.cpp | 5 +- src/plugin/ns/SecureSocket.cpp | 38 ++++++------- src/plugin/ns/SecureSocket.h | 12 ++--- src/plugin/ns/ns.cpp | 24 ++++++++- src/plugin/ns/ns.h | 10 +++- 12 files changed, 180 insertions(+), 48 deletions(-) diff --git a/src/lib/arch/IArchPlugin.h b/src/lib/arch/IArchPlugin.h index d45e7426..68938848 100644 --- a/src/lib/arch/IArchPlugin.h +++ b/src/lib/arch/IArchPlugin.h @@ -21,6 +21,8 @@ #define PLUGINS_DIR "plugins" #include "common/IInterface.h" +#include "common/stdmap.h" +#include "base/String.h" class IEventQueue; @@ -34,11 +36,34 @@ public: //! @name manipulators //@{ - //! Load plugins + //!Load plugins /*! Scan the plugins dir and load plugins. */ + virtual void load() = 0; + + //! Init plugins + /*! + Initializes loaded plugins. + */ virtual void init(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 PluginTable; }; diff --git a/src/lib/arch/win32/ArchPluginWindows.cpp b/src/lib/arch/win32/ArchPluginWindows.cpp index d12445f8..c9f8cee8 100644 --- a/src/lib/arch/win32/ArchPluginWindows.cpp +++ b/src/lib/arch/win32/ArchPluginWindows.cpp @@ -28,6 +28,7 @@ #include typedef int (*initFunc)(void (*sendEvent)(const char*, void*), void (*log)(const char*)); +typedef void* (*invokeFunc)(const char*, void*); void* g_eventTarget = NULL; IEventQueue* g_events = NULL; @@ -41,11 +42,8 @@ ArchPluginWindows::~ArchPluginWindows() } void -ArchPluginWindows::init(void* eventTarget, IEventQueue* events) +ArchPluginWindows::load() { - g_eventTarget = eventTarget; - g_events = events; - String dir = getPluginsDir(); LOG((CLOG_DEBUG "plugins dir: %s", dir.c_str())); @@ -54,21 +52,63 @@ ArchPluginWindows::init(void* eventTarget, IEventQueue* events) getFilenames(pattern, plugins); std::vector::iterator it; - for (it = plugins.begin(); it != plugins.end(); ++it) - load(*it); + for (it = plugins.begin(); it != plugins.end(); ++it) { + LOG((CLOG_DEBUG "loading plugin: %s", (*it).c_str())); + String path = String(getPluginsDir()).append("\\").append(*it); + HINSTANCE library = LoadLibrary(path.c_str()); + + if (library == NULL) { + throw XArch(new XArchEvalWindows); + } + + void* lib = reinterpret_cast(library); + String filename = synergy::string::removeFileExt(*it); + m_pluginTable.insert(std::make_pair(filename, lib)); + } } void -ArchPluginWindows::load(const String& dllFilename) +ArchPluginWindows::init(void* eventTarget, IEventQueue* events) { - LOG((CLOG_DEBUG "loading plugin: %s", dllFilename.c_str())); - String path = String(getPluginsDir()).append("\\").append(dllFilename); - HINSTANCE library = LoadLibrary(path.c_str()); - if (library == NULL) - throw XArch(new XArchEvalWindows); + g_eventTarget = eventTarget; + g_events = events; - initFunc initPlugin = (initFunc)GetProcAddress(library, "init"); - initPlugin(&sendEvent, &log); + PluginTable::iterator it; + HINSTANCE lib; + for (it = m_pluginTable.begin(); it != m_pluginTable.end(); it++) { + lib = reinterpret_cast(it->second); + initFunc initPlugin = (initFunc)GetProcAddress(lib, "init"); + initPlugin(&sendEvent, &log); + } +} + + +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(it->second); + invokeFunc invokePlugin = (invokeFunc)GetProcAddress(lib, "invoke"); + return invokePlugin(command, args); + } + else { + LOG((CLOG_DEBUG "invoke command failed, plugin: %s command: %s", + plugin, command)); + return NULL; + } } String diff --git a/src/lib/arch/win32/ArchPluginWindows.h b/src/lib/arch/win32/ArchPluginWindows.h index a49178c0..53490506 100644 --- a/src/lib/arch/win32/ArchPluginWindows.h +++ b/src/lib/arch/win32/ArchPluginWindows.h @@ -19,7 +19,6 @@ #pragma once #include "arch/IArchPlugin.h" -#include "base/String.h" #include @@ -35,13 +34,20 @@ public: virtual ~ArchPluginWindows(); // IArchPlugin overrides + void load(); void init(void* eventTarget, IEventQueue* events); + bool exists(const char* name); + void* invoke(const char* pluginName, + const char* functionName, + void* args); private: String getModuleDir(); void getFilenames(const String& pattern, std::vector& filenames); - void load(const String& dllPath); String getPluginsDir(); + +private: + PluginTable m_pluginTable; }; void sendEvent(const char* text, void* data); diff --git a/src/lib/base/String.cpp b/src/lib/base/String.cpp index 590b660a..c981eae9 100644 --- a/src/lib/base/String.cpp +++ b/src/lib/base/String.cpp @@ -168,6 +168,17 @@ findReplaceAll( } } +String +removeFileExt(String filename) +{ + unsigned dot = filename.find_last_of('.'); + + if (dot == String::npos) { + return filename; + } + + return filename.substr(0, dot); +} // // CaselessCmp diff --git a/src/lib/base/String.h b/src/lib/base/String.h index e0e3b7c6..9d137143 100644 --- a/src/lib/base/String.h +++ b/src/lib/base/String.h @@ -64,6 +64,12 @@ Finds \c find inside \c subject and replaces it with \c replace */ void findReplaceAll(String& subject, const String& find, const String& replace); +//! Remove file extension +/*! +Finds the last dot and remove all characters from the dot to the end +*/ +String removeFileExt(String filename); + //! Case-insensitive comparisons /*! This class provides case-insensitve comparison functions. diff --git a/src/lib/client/Client.cpp b/src/lib/client/Client.cpp index 4620116d..77e38c3d 100644 --- a/src/lib/client/Client.cpp +++ b/src/lib/client/Client.cpp @@ -18,6 +18,7 @@ #include "client/Client.h" +#include "../plugin/ns/SecureSocket.h" #include "client/ServerProxy.h" #include "synergy/Screen.h" #include "synergy/Clipboard.h" @@ -45,6 +46,12 @@ #include #include +#if defined _WIN32 +static const char s_networkSecurity[] = { "ns" }; +#else +static const char s_networkSecurity[] = { "libns" }; +#endif + // // Client // @@ -75,7 +82,8 @@ Client::Client( m_crypto(crypto), m_sendFileThread(NULL), m_writeToDropDirThread(NULL), - m_enableDragDrop(enableDragDrop) + m_enableDragDrop(enableDragDrop), + m_secureSocket(NULL) { assert(m_socketFactory != NULL); assert(m_screen != NULL); @@ -100,6 +108,11 @@ Client::Client( new TMethodEventJob(this, &Client::handleFileRecieveCompleted)); } + + if (ARCH->plugin().exists(s_networkSecurity)) { + m_secureSocket = static_cast( + ARCH->plugin().invoke("ns", "getSecureSocket", NULL)); + } } Client::~Client() diff --git a/src/lib/client/Client.h b/src/lib/client/Client.h index 144d007d..3145a948 100644 --- a/src/lib/client/Client.h +++ b/src/lib/client/Client.h @@ -37,6 +37,7 @@ class IStreamFilterFactory; class IEventQueue; class CryptoStream; class Thread; +class SecureSocket; //! Synergy client /*! @@ -233,4 +234,5 @@ private: Thread* m_sendFileThread; Thread* m_writeToDropDirThread; bool m_enableDragDrop; + SecureSocket* m_secureSocket; }; diff --git a/src/lib/synergy/ClientApp.cpp b/src/lib/synergy/ClientApp.cpp index 530dd525..24d100ce 100644 --- a/src/lib/synergy/ClientApp.cpp +++ b/src/lib/synergy/ClientApp.cpp @@ -458,6 +458,9 @@ ClientApp::mainLoop() SocketMultiplexer multiplexer; setSocketMultiplexer(&multiplexer); + // load all available plugins. + ARCH->plugin().load(); + // start client, etc appUtil().startNode(); @@ -467,7 +470,7 @@ ClientApp::mainLoop() initIpcClient(); } - // load all available plugins. + // init all available plugins. ARCH->plugin().init(m_clientScreen->getEventTarget(), m_events); // run event loop. if startClient() failed we're supposed to retry diff --git a/src/plugin/ns/SecureSocket.cpp b/src/plugin/ns/SecureSocket.cpp index 50e5f506..b0bb2629 100644 --- a/src/plugin/ns/SecureSocket.cpp +++ b/src/plugin/ns/SecureSocket.cpp @@ -1,6 +1,6 @@ /* * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2014 Bolton Software Ltd. + * 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 @@ -24,21 +24,22 @@ // // SecureSocket // -struct CSsl { +struct Ssl { SSL_CTX* m_context; SSL* m_ssl; }; -CSecureSocket::CSecureSocket() : + +SecureSocket::SecureSocket() : m_ready(false), m_errorSize(65535) { - m_ssl = new CSsl(); + m_ssl = new Ssl(); m_ssl->m_context = NULL; m_ssl->m_ssl = NULL; m_error = new char[m_errorSize]; } -CSecureSocket::~CSecureSocket() +SecureSocket::~SecureSocket() { if (m_ssl->m_ssl != NULL) { SSL_free(m_ssl->m_ssl); @@ -51,7 +52,7 @@ CSecureSocket::~CSecureSocket() } void -CSecureSocket::initContext(bool server) +SecureSocket::initContext(bool server) { SSL_library_init(); @@ -80,7 +81,7 @@ CSecureSocket::initContext(bool server) } void -CSecureSocket::loadCertificates(const char* filename) +SecureSocket::loadCertificates(const char* filename) { int r = 0; r = SSL_CTX_use_certificate_file(m_ssl->m_context, filename, SSL_FILETYPE_PEM); @@ -100,7 +101,7 @@ CSecureSocket::loadCertificates(const char* filename) } } void -CSecureSocket::createSSL() +SecureSocket::createSSL() { // I assume just one instance is needed // get new SSL state with context @@ -110,7 +111,7 @@ CSecureSocket::createSSL() } void -CSecureSocket::accept(int socket) +SecureSocket::accept(int socket) { createSSL(); @@ -131,7 +132,7 @@ CSecureSocket::accept(int socket) } void -CSecureSocket::connect(int socket) +SecureSocket::connect(int socket) { createSSL(); @@ -152,7 +153,7 @@ CSecureSocket::connect(int socket) } size_t -CSecureSocket::write(const void* buffer, int size) +SecureSocket::write(const void* buffer, int size) { bool retry = false; int n = 0; @@ -168,7 +169,7 @@ CSecureSocket::write(const void* buffer, int size) } size_t -CSecureSocket::read(void* buffer, int size) +SecureSocket::read(void* buffer, int size) { bool retry = false; int n = 0; @@ -184,7 +185,7 @@ CSecureSocket::read(void* buffer, int size) } void -CSecureSocket::showCertificate() +SecureSocket::showCertificate() { X509* cert; char* line; @@ -207,7 +208,7 @@ CSecureSocket::showCertificate() } bool -CSecureSocket::checkResult(int n) +SecureSocket::checkResult(int n) { bool retry = false; int errorCode = SSL_get_error(m_ssl->m_ssl, n); @@ -253,16 +254,15 @@ CSecureSocket::checkResult(int n) } void -CSecureSocket::showError() +SecureSocket::showError() { if (getError()) { LOG((CLOG_ERR "secure socket error: %s", m_error)); } } - void -CSecureSocket::throwError(const char* reason) +SecureSocket::throwError(const char* reason) { if (getError()) { throw XSecureSocket(synergy::string::sprintf( @@ -271,7 +271,7 @@ CSecureSocket::throwError(const char* reason) } bool -CSecureSocket::getError() +SecureSocket::getError() { unsigned long e = ERR_get_error(); bool errorUpdated = false; @@ -288,7 +288,7 @@ CSecureSocket::getError() } bool -CSecureSocket::isReady() +SecureSocket::isReady() { return m_ready; } diff --git a/src/plugin/ns/SecureSocket.h b/src/plugin/ns/SecureSocket.h index cd7800be..73b3a0e0 100644 --- a/src/plugin/ns/SecureSocket.h +++ b/src/plugin/ns/SecureSocket.h @@ -1,6 +1,6 @@ /* * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2014 Bolton Software Ltd. + * 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 @@ -28,12 +28,12 @@ XBASE_SUBCLASS(XSecureSocket, XBase); Secure socket layer using OpenSSL. */ -struct CSsl; +struct Ssl; -class CSecureSocket { +class SecureSocket { public: - CSecureSocket(); - ~CSecureSocket(); + SecureSocket(); + ~SecureSocket(); void initContext(bool server); void loadCertificates(const char* CertFile); @@ -52,7 +52,7 @@ private: bool getError(); private: - CSsl* m_ssl; + Ssl* m_ssl; bool m_ready; char* m_error; const size_t m_errorSize; diff --git a/src/plugin/ns/ns.cpp b/src/plugin/ns/ns.cpp index 6819043a..16eb872d 100644 --- a/src/plugin/ns/ns.cpp +++ b/src/plugin/ns/ns.cpp @@ -17,21 +17,41 @@ #include "ns.h" +#include "SecureSocket.h" + #include +SecureSocket* g_secureSocket = NULL; + extern "C" { int init(void (*sendEvent)(const char*, void*), void (*log)(const char*)) { - std::cout << "hello world" << std::endl; return 0; } +void* +invoke(const char* command, void* args) +{ + if (strcmp(command, "getSecureSocket") == 0) { + if (g_secureSocket == NULL) { + g_secureSocket = new SecureSocket(); + } + return g_secureSocket; + } + else { + return NULL; + } +} + int cleanup() { - std::cout << "goodbye world" << std::endl; + if (g_secureSocket != NULL) { + delete g_secureSocket; + } + return 0; } diff --git a/src/plugin/ns/ns.h b/src/plugin/ns/ns.h index 2beeee36..582275e4 100644 --- a/src/plugin/ns/ns.h +++ b/src/plugin/ns/ns.h @@ -17,6 +17,7 @@ #pragma once +#if defined _WIN32 #define WIN32_LEAN_AND_MEAN #include @@ -26,9 +27,14 @@ #define NS_API __declspec(dllimport) #endif +#else +#define NS_API +#endif + extern "C" { -NS_API int init(void (*sendEvent)(const char*, void*), void (*log)(const char*)); -NS_API int cleanup(); +NS_API int init(void (*sendEvent)(const char*, void*), void (*log)(const char*)); +NS_API void* invoke(const char* command, void* args); +NS_API int cleanup(); }