updated pluging loader for Windows #4313

This commit is contained in:
XinyuHou 2015-01-09 13:46:35 +00:00
parent de8fe7e2a5
commit 1d7eb3f5cb
12 changed files with 180 additions and 48 deletions

View File

@ -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,30 @@ public:
/*! /*!
Scan the plugins dir and 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; 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<String, void*> PluginTable;
}; };

View File

@ -28,6 +28,7 @@
#include <iostream> #include <iostream>
typedef int (*initFunc)(void (*sendEvent)(const char*, void*), void (*log)(const char*)); typedef int (*initFunc)(void (*sendEvent)(const char*, void*), void (*log)(const char*));
typedef void* (*invokeFunc)(const char*, void*);
void* g_eventTarget = NULL; void* g_eventTarget = NULL;
IEventQueue* g_events = NULL; IEventQueue* g_events = NULL;
@ -41,11 +42,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,22 +52,64 @@ 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::init(void* eventTarget, IEventQueue* events)
{ {
LOG((CLOG_DEBUG "loading plugin: %s", dllFilename.c_str())); g_eventTarget = eventTarget;
String path = String(getPluginsDir()).append("\\").append(dllFilename); g_events = events;
HINSTANCE library = LoadLibrary(path.c_str());
if (library == NULL)
throw XArch(new XArchEvalWindows);
initFunc initPlugin = (initFunc)GetProcAddress(library, "init"); 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");
initPlugin(&sendEvent, &log); 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<HINSTANCE>(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 String
ArchPluginWindows::getModuleDir() ArchPluginWindows::getModuleDir()

View File

@ -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,20 @@ public:
virtual ~ArchPluginWindows(); virtual ~ArchPluginWindows();
// IArchPlugin overrides // IArchPlugin overrides
void load();
void init(void* eventTarget, IEventQueue* events); void init(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);

View File

@ -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 // CaselessCmp

View File

@ -64,6 +64,12 @@ Finds \c find inside \c subject and replaces it with \c replace
*/ */
void findReplaceAll(String& subject, const String& find, const String& replace); 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.

View File

@ -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"
@ -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
// //
@ -75,7 +82,8 @@ 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_secureSocket(NULL)
{ {
assert(m_socketFactory != NULL); assert(m_socketFactory != NULL);
assert(m_screen != NULL); assert(m_screen != NULL);
@ -100,6 +108,11 @@ Client::Client(
new TMethodEventJob<Client>(this, new TMethodEventJob<Client>(this,
&Client::handleFileRecieveCompleted)); &Client::handleFileRecieveCompleted));
} }
if (ARCH->plugin().exists(s_networkSecurity)) {
m_secureSocket = static_cast<SecureSocket*>(
ARCH->plugin().invoke("ns", "getSecureSocket", NULL));
}
} }
Client::~Client() Client::~Client()

View File

@ -37,6 +37,7 @@ class IStreamFilterFactory;
class IEventQueue; class IEventQueue;
class CryptoStream; class CryptoStream;
class Thread; class Thread;
class SecureSocket;
//! Synergy client //! Synergy client
/*! /*!
@ -233,4 +234,5 @@ private:
Thread* m_sendFileThread; Thread* m_sendFileThread;
Thread* m_writeToDropDirThread; Thread* m_writeToDropDirThread;
bool m_enableDragDrop; bool m_enableDragDrop;
SecureSocket* m_secureSocket;
}; };

View File

@ -458,6 +458,9 @@ ClientApp::mainLoop()
SocketMultiplexer multiplexer; SocketMultiplexer multiplexer;
setSocketMultiplexer(&multiplexer); setSocketMultiplexer(&multiplexer);
// load all available plugins.
ARCH->plugin().load();
// start client, etc // start client, etc
appUtil().startNode(); appUtil().startNode();
@ -467,7 +470,7 @@ ClientApp::mainLoop()
initIpcClient(); initIpcClient();
} }
// load all available plugins. // init all available plugins.
ARCH->plugin().init(m_clientScreen->getEventTarget(), m_events); ARCH->plugin().init(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

View File

@ -1,6 +1,6 @@
/* /*
* synergy -- mouse and keyboard sharing utility * 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 * 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
@ -24,21 +24,22 @@
// //
// SecureSocket // SecureSocket
// //
struct CSsl { struct Ssl {
SSL_CTX* m_context; SSL_CTX* m_context;
SSL* m_ssl; SSL* m_ssl;
}; };
CSecureSocket::CSecureSocket() :
SecureSocket::SecureSocket() :
m_ready(false), m_ready(false),
m_errorSize(65535) m_errorSize(65535)
{ {
m_ssl = new CSsl(); m_ssl = new Ssl();
m_ssl->m_context = NULL; m_ssl->m_context = NULL;
m_ssl->m_ssl = NULL; m_ssl->m_ssl = NULL;
m_error = new char[m_errorSize]; m_error = new char[m_errorSize];
} }
CSecureSocket::~CSecureSocket() SecureSocket::~SecureSocket()
{ {
if (m_ssl->m_ssl != NULL) { if (m_ssl->m_ssl != NULL) {
SSL_free(m_ssl->m_ssl); SSL_free(m_ssl->m_ssl);
@ -51,7 +52,7 @@ CSecureSocket::~CSecureSocket()
} }
void void
CSecureSocket::initContext(bool server) SecureSocket::initContext(bool server)
{ {
SSL_library_init(); SSL_library_init();
@ -80,7 +81,7 @@ CSecureSocket::initContext(bool server)
} }
void void
CSecureSocket::loadCertificates(const char* filename) SecureSocket::loadCertificates(const char* filename)
{ {
int r = 0; int r = 0;
r = SSL_CTX_use_certificate_file(m_ssl->m_context, filename, SSL_FILETYPE_PEM); r = SSL_CTX_use_certificate_file(m_ssl->m_context, filename, SSL_FILETYPE_PEM);
@ -100,7 +101,7 @@ CSecureSocket::loadCertificates(const char* filename)
} }
} }
void void
CSecureSocket::createSSL() SecureSocket::createSSL()
{ {
// I assume just one instance is needed // I assume just one instance is needed
// get new SSL state with context // get new SSL state with context
@ -110,7 +111,7 @@ CSecureSocket::createSSL()
} }
void void
CSecureSocket::accept(int socket) SecureSocket::accept(int socket)
{ {
createSSL(); createSSL();
@ -131,7 +132,7 @@ CSecureSocket::accept(int socket)
} }
void void
CSecureSocket::connect(int socket) SecureSocket::connect(int socket)
{ {
createSSL(); createSSL();
@ -152,7 +153,7 @@ CSecureSocket::connect(int socket)
} }
size_t size_t
CSecureSocket::write(const void* buffer, int size) SecureSocket::write(const void* buffer, int size)
{ {
bool retry = false; bool retry = false;
int n = 0; int n = 0;
@ -168,7 +169,7 @@ CSecureSocket::write(const void* buffer, int size)
} }
size_t size_t
CSecureSocket::read(void* buffer, int size) SecureSocket::read(void* buffer, int size)
{ {
bool retry = false; bool retry = false;
int n = 0; int n = 0;
@ -184,7 +185,7 @@ CSecureSocket::read(void* buffer, int size)
} }
void void
CSecureSocket::showCertificate() SecureSocket::showCertificate()
{ {
X509* cert; X509* cert;
char* line; char* line;
@ -207,7 +208,7 @@ CSecureSocket::showCertificate()
} }
bool bool
CSecureSocket::checkResult(int n) SecureSocket::checkResult(int n)
{ {
bool retry = false; bool retry = false;
int errorCode = SSL_get_error(m_ssl->m_ssl, n); int errorCode = SSL_get_error(m_ssl->m_ssl, n);
@ -253,16 +254,15 @@ CSecureSocket::checkResult(int n)
} }
void void
CSecureSocket::showError() SecureSocket::showError()
{ {
if (getError()) { if (getError()) {
LOG((CLOG_ERR "secure socket error: %s", m_error)); LOG((CLOG_ERR "secure socket error: %s", m_error));
} }
} }
void void
CSecureSocket::throwError(const char* reason) SecureSocket::throwError(const char* reason)
{ {
if (getError()) { if (getError()) {
throw XSecureSocket(synergy::string::sprintf( throw XSecureSocket(synergy::string::sprintf(
@ -271,7 +271,7 @@ CSecureSocket::throwError(const char* reason)
} }
bool bool
CSecureSocket::getError() SecureSocket::getError()
{ {
unsigned long e = ERR_get_error(); unsigned long e = ERR_get_error();
bool errorUpdated = false; bool errorUpdated = false;
@ -288,7 +288,7 @@ CSecureSocket::getError()
} }
bool bool
CSecureSocket::isReady() SecureSocket::isReady()
{ {
return m_ready; return m_ready;
} }

View File

@ -1,6 +1,6 @@
/* /*
* synergy -- mouse and keyboard sharing utility * 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 * 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
@ -28,12 +28,12 @@ XBASE_SUBCLASS(XSecureSocket, XBase);
Secure socket layer using OpenSSL. Secure socket layer using OpenSSL.
*/ */
struct CSsl; struct Ssl;
class CSecureSocket { class SecureSocket {
public: public:
CSecureSocket(); SecureSocket();
~CSecureSocket(); ~SecureSocket();
void initContext(bool server); void initContext(bool server);
void loadCertificates(const char* CertFile); void loadCertificates(const char* CertFile);
@ -52,7 +52,7 @@ private:
bool getError(); bool getError();
private: private:
CSsl* m_ssl; Ssl* m_ssl;
bool m_ready; bool m_ready;
char* m_error; char* m_error;
const size_t m_errorSize; const size_t m_errorSize;

View File

@ -17,21 +17,41 @@
#include "ns.h" #include "ns.h"
#include "SecureSocket.h"
#include <iostream> #include <iostream>
SecureSocket* g_secureSocket = NULL;
extern "C" { extern "C" {
int int
init(void (*sendEvent)(const char*, void*), void (*log)(const char*)) init(void (*sendEvent)(const char*, void*), void (*log)(const char*))
{ {
std::cout << "hello world" << std::endl;
return 0; 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 int
cleanup() cleanup()
{ {
std::cout << "goodbye world" << std::endl; if (g_secureSocket != NULL) {
delete g_secureSocket;
}
return 0; return 0;
} }

View File

@ -17,6 +17,7 @@
#pragma once #pragma once
#if defined _WIN32
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <Windows.h> #include <Windows.h>
@ -26,9 +27,14 @@
#define NS_API __declspec(dllimport) #define NS_API __declspec(dllimport)
#endif #endif
#else
#define NS_API
#endif
extern "C" { extern "C" {
NS_API int init(void (*sendEvent)(const char*, void*), void (*log)(const char*)); 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(); NS_API int cleanup();
} }