Patch by Jerry:
- Fixed line endings - Integ test for file transfer - Fixed crashed problem when log info is larger than 2048 bytes - Fixed compile error caused by std exception (by Feng ye) - Fixed include path on Mac and linux (by Feng ye)
This commit is contained in:
parent
c368013f13
commit
394ece004a
|
@ -174,35 +174,35 @@ if (UNIX)
|
||||||
|
|
||||||
else()
|
else()
|
||||||
|
|
||||||
# add include dir for bsd (posix uses /usr/include/)
|
# add include dir for bsd (posix uses /usr/include/)
|
||||||
set(CMAKE_INCLUDE_PATH "${CMAKE_INCLUDE_PATH}:/usr/local/include")
|
set(CMAKE_INCLUDE_PATH "${CMAKE_INCLUDE_PATH}:/usr/local/include")
|
||||||
|
|
||||||
set(XKBlib "X11/Xlib.h;X11/XKBlib.h")
|
set(XKBlib "X11/Xlib.h;X11/XKBlib.h")
|
||||||
check_symbol_exists("XRRNotifyEvent" "${XKBlib};X11/extensions/Xrandr.h" HAVE_X11_EXTENSIONS_XRANDR_H)
|
check_symbol_exists("XRRNotifyEvent" "${XKBlib};X11/extensions/Xrandr.h" HAVE_X11_EXTENSIONS_XRANDR_H)
|
||||||
|
|
||||||
check_include_files("${XKBlib};X11/extensions/dpms.h" HAVE_X11_EXTENSIONS_DPMS_H)
|
check_include_files("${XKBlib};X11/extensions/dpms.h" HAVE_X11_EXTENSIONS_DPMS_H)
|
||||||
check_include_files("X11/extensions/Xinerama.h" HAVE_X11_EXTENSIONS_XINERAMA_H)
|
check_include_files("X11/extensions/Xinerama.h" HAVE_X11_EXTENSIONS_XINERAMA_H)
|
||||||
check_include_files("${XKBlib};X11/extensions/XKBstr.h" HAVE_X11_EXTENSIONS_XKBSTR_H)
|
check_include_files("${XKBlib};X11/extensions/XKBstr.h" HAVE_X11_EXTENSIONS_XKBSTR_H)
|
||||||
check_include_files("X11/extensions/XKB.h" HAVE_XKB_EXTENSION)
|
check_include_files("X11/extensions/XKB.h" HAVE_XKB_EXTENSION)
|
||||||
check_include_files("X11/extensions/XTest.h" HAVE_X11_EXTENSIONS_XTEST_H)
|
check_include_files("X11/extensions/XTest.h" HAVE_X11_EXTENSIONS_XTEST_H)
|
||||||
check_include_files("${XKBlib}" HAVE_X11_XKBLIB_H)
|
check_include_files("${XKBlib}" HAVE_X11_XKBLIB_H)
|
||||||
check_include_files("X11/extensions/XInput2.h" HAVE_XI2)
|
check_include_files("X11/extensions/XInput2.h" HAVE_XI2)
|
||||||
|
|
||||||
if (HAVE_X11_EXTENSIONS_DPMS_H)
|
if (HAVE_X11_EXTENSIONS_DPMS_H)
|
||||||
# Assume that function prototypes declared, when include exists.
|
# Assume that function prototypes declared, when include exists.
|
||||||
set(HAVE_DPMS_PROTOTYPES 1)
|
set(HAVE_DPMS_PROTOTYPES 1)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT HAVE_X11_XKBLIB_H)
|
if (NOT HAVE_X11_XKBLIB_H)
|
||||||
message(FATAL_ERROR "Missing header: " ${XKBlib})
|
message(FATAL_ERROR "Missing header: " ${XKBlib})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
check_library_exists("SM;ICE" IceConnectionNumber "" HAVE_ICE)
|
check_library_exists("SM;ICE" IceConnectionNumber "" HAVE_ICE)
|
||||||
check_library_exists("Xext;X11" DPMSQueryExtension "" HAVE_Xext)
|
check_library_exists("Xext;X11" DPMSQueryExtension "" HAVE_Xext)
|
||||||
check_library_exists("Xtst;Xext;X11" XTestQueryExtension "" HAVE_Xtst)
|
check_library_exists("Xtst;Xext;X11" XTestQueryExtension "" HAVE_Xtst)
|
||||||
check_library_exists("Xinerama" XineramaQueryExtension "" HAVE_Xinerama)
|
check_library_exists("Xinerama" XineramaQueryExtension "" HAVE_Xinerama)
|
||||||
check_library_exists("Xi" XISelectEvents "" HAVE_Xi)
|
check_library_exists("Xi" XISelectEvents "" HAVE_Xi)
|
||||||
check_library_exists("Xrandr" XRRQueryExtension "" HAVE_Xrandr)
|
check_library_exists("Xrandr" XRRQueryExtension "" HAVE_Xrandr)
|
||||||
|
|
||||||
if (HAVE_ICE)
|
if (HAVE_ICE)
|
||||||
|
|
||||||
|
@ -213,13 +213,13 @@ if (UNIX)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (HAVE_Xtst)
|
if (HAVE_Xtst)
|
||||||
|
|
||||||
# Xtxt depends on X11.
|
# Xtxt depends on X11.
|
||||||
set(HAVE_X11)
|
set(HAVE_X11)
|
||||||
list(APPEND libs Xtst X11)
|
list(APPEND libs Xtst X11)
|
||||||
|
|
||||||
else()
|
else()
|
||||||
|
|
||||||
message(FATAL_ERROR "Missing library: Xtst")
|
message(FATAL_ERROR "Missing library: Xtst")
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
@ -229,14 +229,14 @@ if (UNIX)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (HAVE_Xinerama)
|
if (HAVE_Xinerama)
|
||||||
list(APPEND libs Xinerama)
|
list(APPEND libs Xinerama)
|
||||||
else (HAVE_Xinerama)
|
else (HAVE_Xinerama)
|
||||||
if (HAVE_X11_EXTENSIONS_XINERAMA_H)
|
if (HAVE_X11_EXTENSIONS_XINERAMA_H)
|
||||||
set(HAVE_X11_EXTENSIONS_XINERAMA_H 0)
|
set(HAVE_X11_EXTENSIONS_XINERAMA_H 0)
|
||||||
message(WARNING "Old Xinerama implementation detected, disabled")
|
message(WARNING "Old Xinerama implementation detected, disabled")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (HAVE_Xrandr)
|
if (HAVE_Xrandr)
|
||||||
list(APPEND libs Xrandr)
|
list(APPEND libs Xrandr)
|
||||||
endif()
|
endif()
|
||||||
|
@ -382,13 +382,13 @@ if (CONF_DOXYGEN)
|
||||||
set(VERSION, "${VERSION}")
|
set(VERSION, "${VERSION}")
|
||||||
|
|
||||||
# For doxygen.cfg, save the results based on a template (doxygen.cfg.in).
|
# For doxygen.cfg, save the results based on a template (doxygen.cfg.in).
|
||||||
configure_file(${cmake_dir}/doxygen.cfg.in ${doc_dir}/doxygen.cfg)
|
configure_file(${cmake_dir}/doxygen.cfg.in ${doc_dir}/doxygen.cfg)
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (${CMAKE_SYSTEM_NAME} MATCHES "IRIX")
|
if (${CMAKE_SYSTEM_NAME} MATCHES "IRIX")
|
||||||
set_target_properties(synergys PROPERTIES LINK_FLAGS "-all -woff 33 -woff 84 -woff 15")
|
set_target_properties(synergys PROPERTIES LINK_FLAGS "-all -woff 33 -woff 84 -woff 15")
|
||||||
set_target_properties(synergyc PROPERTIES LINK_FLAGS "-all -woff 33 -woff 84 -woff 15")
|
set_target_properties(synergyc PROPERTIES LINK_FLAGS "-all -woff 33 -woff 84 -woff 15")
|
||||||
set_target_properties(synergyd PROPERTIES LINK_FLAGS "-all -woff 33 -woff 84 -woff 15")
|
set_target_properties(synergyd PROPERTIES LINK_FLAGS "-all -woff 33 -woff 84 -woff 15")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
|
@ -13,11 +13,11 @@
|
||||||
#
|
#
|
||||||
# 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(lib)
|
add_subdirectory(lib)
|
||||||
add_subdirectory(cmd)
|
add_subdirectory(cmd)
|
||||||
if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "IRIX")
|
if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "IRIX")
|
||||||
add_subdirectory(test)
|
add_subdirectory(test)
|
||||||
endif()
|
endif()
|
||||||
add_subdirectory(plugin)
|
add_subdirectory(plugin)
|
||||||
add_subdirectory(micro)
|
add_subdirectory(micro)
|
||||||
|
|
|
@ -64,17 +64,17 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdSh
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!server && !client) {
|
if (!server && !client) {
|
||||||
MessageBox(NULL,
|
MessageBox(NULL,
|
||||||
"Either the --server argument or the --client argument must be provided.",
|
"Either the --server argument or the --client argument must be provided.",
|
||||||
"Server or client?", MB_OK);
|
"Server or client?", MB_OK);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc <= 2) {
|
if (argc <= 2) {
|
||||||
MessageBox(NULL,
|
MessageBox(NULL,
|
||||||
"No additional arguments were provided. Append the --help argument for help.\n\n"
|
"No additional arguments were provided. Append the --help argument for help.\n\n"
|
||||||
"Hint: Create a shortcut and append the \"Target\" field with the arguments.",
|
"Hint: Create a shortcut and append the \"Target\" field with the arguments.",
|
||||||
"No additional arguments", MB_OK);
|
"No additional arguments", MB_OK);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
/*
|
/*
|
||||||
* synergy -- mouse and keyboard sharing utility
|
* synergy -- mouse and keyboard sharing utility
|
||||||
* Copyright (C) 2013 Bolton Software Ltd.
|
* Copyright (C) 2013 Bolton Software 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
|
||||||
* found in the file COPYING that should have accompanied this file.
|
* found in the file COPYING that should have accompanied this file.
|
||||||
*
|
*
|
||||||
* This package is distributed in the hope that it will be useful,
|
* This package is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* 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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
enum CryptoMode {
|
enum CryptoMode {
|
||||||
Disabled,
|
Disabled,
|
||||||
OFB,
|
OFB,
|
||||||
CFB,
|
CFB,
|
||||||
CTR,
|
CTR,
|
||||||
GCM
|
GCM
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
/*
|
/*
|
||||||
* synergy -- mouse and keyboard sharing utility
|
* synergy -- mouse and keyboard sharing utility
|
||||||
* Copyright (C) 2012 Bolton Software Ltd.
|
* Copyright (C) 2012 Bolton Software Ltd.
|
||||||
* Copyright (C) 2012 Nick Bolton
|
* Copyright (C) 2012 Nick Bolton
|
||||||
*
|
*
|
||||||
* 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
|
||||||
* found in the file COPYING that should have accompanied this file.
|
* found in the file COPYING that should have accompanied this file.
|
||||||
*
|
*
|
||||||
* This package is distributed in the hope that it will be useful,
|
* This package is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* 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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// this class is a duplicate of /src/lib/ipc/Ipc.cpp
|
// this class is a duplicate of /src/lib/ipc/Ipc.cpp
|
||||||
|
|
||||||
#include "Ipc.h"
|
#include "Ipc.h"
|
||||||
|
|
||||||
const char* kIpcMsgHello = "IHEL%1i";
|
const char* kIpcMsgHello = "IHEL%1i";
|
||||||
const char* kIpcMsgLogLine = "ILOG%s";
|
const char* kIpcMsgLogLine = "ILOG%s";
|
||||||
const char* kIpcMsgCommand = "ICMD%s%1i";
|
const char* kIpcMsgCommand = "ICMD%s%1i";
|
||||||
const char* kIpcMsgShutdown = "ISDN";
|
const char* kIpcMsgShutdown = "ISDN";
|
||||||
|
|
|
@ -1,42 +1,42 @@
|
||||||
/*
|
/*
|
||||||
* synergy -- mouse and keyboard sharing utility
|
* synergy -- mouse and keyboard sharing utility
|
||||||
* Copyright (C) 2012 Bolton Software Ltd.
|
* Copyright (C) 2012 Bolton Software Ltd.
|
||||||
* Copyright (C) 2012 Nick Bolton
|
* Copyright (C) 2012 Nick Bolton
|
||||||
*
|
*
|
||||||
* 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
|
||||||
* found in the file COPYING that should have accompanied this file.
|
* found in the file COPYING that should have accompanied this file.
|
||||||
*
|
*
|
||||||
* This package is distributed in the hope that it will be useful,
|
* This package is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* 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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// this class is a duplicate of /src/lib/ipc/Ipc.h
|
// this class is a duplicate of /src/lib/ipc/Ipc.h
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define IPC_HOST "127.0.0.1"
|
#define IPC_HOST "127.0.0.1"
|
||||||
#define IPC_PORT 24801
|
#define IPC_PORT 24801
|
||||||
|
|
||||||
enum qIpcMessageType {
|
enum qIpcMessageType {
|
||||||
kIpcHello,
|
kIpcHello,
|
||||||
kIpcLogLine,
|
kIpcLogLine,
|
||||||
kIpcCommand,
|
kIpcCommand,
|
||||||
kIpcShutdown,
|
kIpcShutdown,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum qIpcClientType {
|
enum qIpcClientType {
|
||||||
kIpcClientUnknown,
|
kIpcClientUnknown,
|
||||||
kIpcClientGui,
|
kIpcClientGui,
|
||||||
kIpcClientNode,
|
kIpcClientNode,
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const char* kIpcMsgHello;
|
extern const char* kIpcMsgHello;
|
||||||
extern const char* kIpcMsgLogLine;
|
extern const char* kIpcMsgLogLine;
|
||||||
extern const char* kIpcMsgCommand;
|
extern const char* kIpcMsgCommand;
|
||||||
extern const char* kIpcMsgShutdown;
|
extern const char* kIpcMsgShutdown;
|
||||||
|
|
|
@ -1,147 +1,147 @@
|
||||||
/*
|
/*
|
||||||
* synergy -- mouse and keyboard sharing utility
|
* synergy -- mouse and keyboard sharing utility
|
||||||
* Copyright (C) 2012 Bolton Software Ltd.
|
* Copyright (C) 2012 Bolton Software Ltd.
|
||||||
* Copyright (C) 2012 Nick Bolton
|
* Copyright (C) 2012 Nick Bolton
|
||||||
*
|
*
|
||||||
* 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
|
||||||
* found in the file COPYING that should have accompanied this file.
|
* found in the file COPYING that should have accompanied this file.
|
||||||
*
|
*
|
||||||
* This package is distributed in the hope that it will be useful,
|
* This package is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* 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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "IpcClient.h"
|
#include "IpcClient.h"
|
||||||
#include <QTcpSocket>
|
#include <QTcpSocket>
|
||||||
#include <QHostAddress>
|
#include <QHostAddress>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include "IpcReader.h"
|
#include "IpcReader.h"
|
||||||
#include "Ipc.h"
|
#include "Ipc.h"
|
||||||
|
|
||||||
IpcClient::IpcClient() :
|
IpcClient::IpcClient() :
|
||||||
m_ReaderStarted(false),
|
m_ReaderStarted(false),
|
||||||
m_Enabled(false)
|
m_Enabled(false)
|
||||||
{
|
{
|
||||||
m_Socket = new QTcpSocket(this);
|
m_Socket = new QTcpSocket(this);
|
||||||
connect(m_Socket, SIGNAL(connected()), this, SLOT(connected()));
|
connect(m_Socket, SIGNAL(connected()), this, SLOT(connected()));
|
||||||
connect(m_Socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error(QAbstractSocket::SocketError)));
|
connect(m_Socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error(QAbstractSocket::SocketError)));
|
||||||
|
|
||||||
m_Reader = new IpcReader(m_Socket);
|
m_Reader = new IpcReader(m_Socket);
|
||||||
connect(m_Reader, SIGNAL(readLogLine(const QString&)), this, SLOT(handleReadLogLine(const QString&)));
|
connect(m_Reader, SIGNAL(readLogLine(const QString&)), this, SLOT(handleReadLogLine(const QString&)));
|
||||||
}
|
}
|
||||||
|
|
||||||
IpcClient::~IpcClient()
|
IpcClient::~IpcClient()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void IpcClient::connected()
|
void IpcClient::connected()
|
||||||
{
|
{
|
||||||
char typeBuf[1];
|
char typeBuf[1];
|
||||||
typeBuf[0] = kIpcClientGui;
|
typeBuf[0] = kIpcClientGui;
|
||||||
sendHello();
|
sendHello();
|
||||||
|
|
||||||
infoMessage("connection established");
|
infoMessage("connection established");
|
||||||
}
|
}
|
||||||
|
|
||||||
void IpcClient::connectToHost()
|
void IpcClient::connectToHost()
|
||||||
{
|
{
|
||||||
m_Enabled = true;
|
m_Enabled = true;
|
||||||
|
|
||||||
infoMessage("connecting to service...");
|
infoMessage("connecting to service...");
|
||||||
m_Socket->connectToHost(QHostAddress(QHostAddress::LocalHost), IPC_PORT);
|
m_Socket->connectToHost(QHostAddress(QHostAddress::LocalHost), IPC_PORT);
|
||||||
|
|
||||||
if (!m_ReaderStarted) {
|
if (!m_ReaderStarted) {
|
||||||
m_Reader->start();
|
m_Reader->start();
|
||||||
m_ReaderStarted = true;
|
m_ReaderStarted = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IpcClient::disconnectFromHost()
|
void IpcClient::disconnectFromHost()
|
||||||
{
|
{
|
||||||
infoMessage("service disconnect");
|
infoMessage("service disconnect");
|
||||||
m_Reader->stop();
|
m_Reader->stop();
|
||||||
m_Socket->close();
|
m_Socket->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IpcClient::error(QAbstractSocket::SocketError error)
|
void IpcClient::error(QAbstractSocket::SocketError error)
|
||||||
{
|
{
|
||||||
QString text;
|
QString text;
|
||||||
switch (error) {
|
switch (error) {
|
||||||
case 0: text = "connection refused"; break;
|
case 0: text = "connection refused"; break;
|
||||||
case 1: text = "remote host closed"; break;
|
case 1: text = "remote host closed"; break;
|
||||||
default: text = QString("code=%1").arg(error); break;
|
default: text = QString("code=%1").arg(error); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
errorMessage(QString("ipc connection error, %1").arg(text));
|
errorMessage(QString("ipc connection error, %1").arg(text));
|
||||||
|
|
||||||
QTimer::singleShot(1000, this, SLOT(retryConnect()));
|
QTimer::singleShot(1000, this, SLOT(retryConnect()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void IpcClient::retryConnect()
|
void IpcClient::retryConnect()
|
||||||
{
|
{
|
||||||
if (m_Enabled) {
|
if (m_Enabled) {
|
||||||
connectToHost();
|
connectToHost();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IpcClient::sendHello()
|
void IpcClient::sendHello()
|
||||||
{
|
{
|
||||||
QDataStream stream(m_Socket);
|
QDataStream stream(m_Socket);
|
||||||
stream.writeRawData(kIpcMsgHello, 4);
|
stream.writeRawData(kIpcMsgHello, 4);
|
||||||
|
|
||||||
char typeBuf[1];
|
char typeBuf[1];
|
||||||
typeBuf[0] = kIpcClientGui;
|
typeBuf[0] = kIpcClientGui;
|
||||||
stream.writeRawData(typeBuf, 1);
|
stream.writeRawData(typeBuf, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IpcClient::sendCommand(const QString& command, bool elevate)
|
void IpcClient::sendCommand(const QString& command, bool elevate)
|
||||||
{
|
{
|
||||||
QDataStream stream(m_Socket);
|
QDataStream stream(m_Socket);
|
||||||
|
|
||||||
stream.writeRawData(kIpcMsgCommand, 4);
|
stream.writeRawData(kIpcMsgCommand, 4);
|
||||||
|
|
||||||
std::string stdStringCommand = command.toStdString();
|
std::string stdStringCommand = command.toStdString();
|
||||||
const char* charCommand = stdStringCommand.c_str();
|
const char* charCommand = stdStringCommand.c_str();
|
||||||
int length = strlen(charCommand);
|
int length = strlen(charCommand);
|
||||||
|
|
||||||
char lenBuf[4];
|
char lenBuf[4];
|
||||||
intToBytes(length, lenBuf, 4);
|
intToBytes(length, lenBuf, 4);
|
||||||
stream.writeRawData(lenBuf, 4);
|
stream.writeRawData(lenBuf, 4);
|
||||||
stream.writeRawData(charCommand, length);
|
stream.writeRawData(charCommand, length);
|
||||||
|
|
||||||
char elevateBuf[1];
|
char elevateBuf[1];
|
||||||
elevateBuf[0] = elevate ? 1 : 0;
|
elevateBuf[0] = elevate ? 1 : 0;
|
||||||
stream.writeRawData(elevateBuf, 1);
|
stream.writeRawData(elevateBuf, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IpcClient::handleReadLogLine(const QString& text)
|
void IpcClient::handleReadLogLine(const QString& text)
|
||||||
{
|
{
|
||||||
readLogLine(text);
|
readLogLine(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: qt must have a built in way of converting int to bytes.
|
// TODO: qt must have a built in way of converting int to bytes.
|
||||||
void IpcClient::intToBytes(int value, char *buffer, int size)
|
void IpcClient::intToBytes(int value, char *buffer, int size)
|
||||||
{
|
{
|
||||||
if (size == 1) {
|
if (size == 1) {
|
||||||
buffer[0] = value & 0xff;
|
buffer[0] = value & 0xff;
|
||||||
}
|
}
|
||||||
else if (size == 2) {
|
else if (size == 2) {
|
||||||
buffer[0] = (value >> 8) & 0xff;
|
buffer[0] = (value >> 8) & 0xff;
|
||||||
buffer[1] = value & 0xff;
|
buffer[1] = value & 0xff;
|
||||||
}
|
}
|
||||||
else if (size == 4) {
|
else if (size == 4) {
|
||||||
buffer[0] = (value >> 24) & 0xff;
|
buffer[0] = (value >> 24) & 0xff;
|
||||||
buffer[1] = (value >> 16) & 0xff;
|
buffer[1] = (value >> 16) & 0xff;
|
||||||
buffer[2] = (value >> 8) & 0xff;
|
buffer[2] = (value >> 8) & 0xff;
|
||||||
buffer[3] = value & 0xff;
|
buffer[3] = value & 0xff;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// TODO: other sizes, if needed.
|
// TODO: other sizes, if needed.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,61 +1,61 @@
|
||||||
/*
|
/*
|
||||||
* synergy -- mouse and keyboard sharing utility
|
* synergy -- mouse and keyboard sharing utility
|
||||||
* Copyright (C) 2012 Bolton Software Ltd.
|
* Copyright (C) 2012 Bolton Software Ltd.
|
||||||
* Copyright (C) 2012 Nick Bolton
|
* Copyright (C) 2012 Nick Bolton
|
||||||
*
|
*
|
||||||
* 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
|
||||||
* found in the file COPYING that should have accompanied this file.
|
* found in the file COPYING that should have accompanied this file.
|
||||||
*
|
*
|
||||||
* This package is distributed in the hope that it will be useful,
|
* This package is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* 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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QAbstractSocket>
|
#include <QAbstractSocket>
|
||||||
|
|
||||||
class QTcpSocket;
|
class QTcpSocket;
|
||||||
class IpcReader;
|
class IpcReader;
|
||||||
|
|
||||||
class IpcClient : public QObject
|
class IpcClient : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IpcClient();
|
IpcClient();
|
||||||
virtual ~IpcClient();
|
virtual ~IpcClient();
|
||||||
|
|
||||||
void sendHello();
|
void sendHello();
|
||||||
void sendCommand(const QString& command, bool elevate);
|
void sendCommand(const QString& command, bool elevate);
|
||||||
void connectToHost();
|
void connectToHost();
|
||||||
void disconnectFromHost();
|
void disconnectFromHost();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void retryConnect();
|
void retryConnect();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void intToBytes(int value, char* buffer, int size);
|
void intToBytes(int value, char* buffer, int size);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void connected();
|
void connected();
|
||||||
void error(QAbstractSocket::SocketError error);
|
void error(QAbstractSocket::SocketError error);
|
||||||
void handleReadLogLine(const QString& text);
|
void handleReadLogLine(const QString& text);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void readLogLine(const QString& text);
|
void readLogLine(const QString& text);
|
||||||
void infoMessage(const QString& text);
|
void infoMessage(const QString& text);
|
||||||
void errorMessage(const QString& text);
|
void errorMessage(const QString& text);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QTcpSocket* m_Socket;
|
QTcpSocket* m_Socket;
|
||||||
IpcReader* m_Reader;
|
IpcReader* m_Reader;
|
||||||
bool m_ReaderStarted;
|
bool m_ReaderStarted;
|
||||||
bool m_Enabled;
|
bool m_Enabled;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,131 +1,131 @@
|
||||||
/*
|
/*
|
||||||
* synergy -- mouse and keyboard sharing utility
|
* synergy -- mouse and keyboard sharing utility
|
||||||
* Copyright (C) 2012 Bolton Software Ltd.
|
* Copyright (C) 2012 Bolton Software Ltd.
|
||||||
* Copyright (C) 2012 Nick Bolton
|
* Copyright (C) 2012 Nick Bolton
|
||||||
*
|
*
|
||||||
* 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
|
||||||
* found in the file COPYING that should have accompanied this file.
|
* found in the file COPYING that should have accompanied this file.
|
||||||
*
|
*
|
||||||
* This package is distributed in the hope that it will be useful,
|
* This package is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* 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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "IpcReader.h"
|
#include "IpcReader.h"
|
||||||
#include <QTcpSocket>
|
#include <QTcpSocket>
|
||||||
#include "Ipc.h"
|
#include "Ipc.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
|
|
||||||
IpcReader::IpcReader(QTcpSocket* socket) :
|
IpcReader::IpcReader(QTcpSocket* socket) :
|
||||||
m_Socket(socket)
|
m_Socket(socket)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
IpcReader::~IpcReader()
|
IpcReader::~IpcReader()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void IpcReader::start()
|
void IpcReader::start()
|
||||||
{
|
{
|
||||||
connect(m_Socket, SIGNAL(readyRead()), this, SLOT(read()));
|
connect(m_Socket, SIGNAL(readyRead()), this, SLOT(read()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void IpcReader::stop()
|
void IpcReader::stop()
|
||||||
{
|
{
|
||||||
disconnect(m_Socket, SIGNAL(readyRead()), this, SLOT(read()));
|
disconnect(m_Socket, SIGNAL(readyRead()), this, SLOT(read()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void IpcReader::read()
|
void IpcReader::read()
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&m_Mutex);
|
QMutexLocker locker(&m_Mutex);
|
||||||
std::cout << "ready read" << std::endl;
|
std::cout << "ready read" << std::endl;
|
||||||
|
|
||||||
while (m_Socket->bytesAvailable()) {
|
while (m_Socket->bytesAvailable()) {
|
||||||
std::cout << "bytes available" << std::endl;
|
std::cout << "bytes available" << std::endl;
|
||||||
|
|
||||||
char codeBuf[5];
|
char codeBuf[5];
|
||||||
readStream(codeBuf, 4);
|
readStream(codeBuf, 4);
|
||||||
codeBuf[4] = 0;
|
codeBuf[4] = 0;
|
||||||
std::cout << "ipc read: " << codeBuf << std::endl;
|
std::cout << "ipc read: " << codeBuf << std::endl;
|
||||||
|
|
||||||
if (memcmp(codeBuf, kIpcMsgLogLine, 4) == 0) {
|
if (memcmp(codeBuf, kIpcMsgLogLine, 4) == 0) {
|
||||||
std::cout << "reading log line" << std::endl;
|
std::cout << "reading log line" << std::endl;
|
||||||
|
|
||||||
char lenBuf[4];
|
char lenBuf[4];
|
||||||
readStream(lenBuf, 4);
|
readStream(lenBuf, 4);
|
||||||
int len = bytesToInt(lenBuf, 4);
|
int len = bytesToInt(lenBuf, 4);
|
||||||
|
|
||||||
char* data = new char[len];
|
char* data = new char[len];
|
||||||
readStream(data, len);
|
readStream(data, len);
|
||||||
QString line = QString::fromUtf8(data, len);
|
QString line = QString::fromUtf8(data, len);
|
||||||
delete data;
|
delete data;
|
||||||
|
|
||||||
readLogLine(line);
|
readLogLine(line);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
std::cerr << "aborting, message invalid" << std::endl;
|
std::cerr << "aborting, message invalid" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "read done" << std::endl;
|
std::cout << "read done" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IpcReader::readStream(char* buffer, int length)
|
bool IpcReader::readStream(char* buffer, int length)
|
||||||
{
|
{
|
||||||
std::cout << "reading stream" << std::endl;
|
std::cout << "reading stream" << std::endl;
|
||||||
|
|
||||||
int read = 0;
|
int read = 0;
|
||||||
while (read < length) {
|
while (read < length) {
|
||||||
int ask = length - read;
|
int ask = length - read;
|
||||||
if (m_Socket->bytesAvailable() < ask) {
|
if (m_Socket->bytesAvailable() < ask) {
|
||||||
std::cout << "buffer too short, waiting" << std::endl;
|
std::cout << "buffer too short, waiting" << std::endl;
|
||||||
m_Socket->waitForReadyRead(-1);
|
m_Socket->waitForReadyRead(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int got = m_Socket->read(buffer, ask);
|
int got = m_Socket->read(buffer, ask);
|
||||||
read += got;
|
read += got;
|
||||||
|
|
||||||
std::cout << "> ask=" << ask << " got=" << got
|
std::cout << "> ask=" << ask << " got=" << got
|
||||||
<< " read=" << read << std::endl;
|
<< " read=" << read << std::endl;
|
||||||
|
|
||||||
if (got == -1) {
|
if (got == -1) {
|
||||||
std::cout << "socket ended, aborting" << std::endl;
|
std::cout << "socket ended, aborting" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (length - read > 0) {
|
else if (length - read > 0) {
|
||||||
std::cout << "more remains, seek to " << got << std::endl;
|
std::cout << "more remains, seek to " << got << std::endl;
|
||||||
buffer += got;
|
buffer += got;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int IpcReader::bytesToInt(const char *buffer, int size)
|
int IpcReader::bytesToInt(const char *buffer, int size)
|
||||||
{
|
{
|
||||||
if (size == 1) {
|
if (size == 1) {
|
||||||
return (unsigned char)buffer[0];
|
return (unsigned char)buffer[0];
|
||||||
}
|
}
|
||||||
else if (size == 2) {
|
else if (size == 2) {
|
||||||
return
|
return
|
||||||
(((unsigned char)buffer[0]) << 8) +
|
(((unsigned char)buffer[0]) << 8) +
|
||||||
(unsigned char)buffer[1];
|
(unsigned char)buffer[1];
|
||||||
}
|
}
|
||||||
else if (size == 4) {
|
else if (size == 4) {
|
||||||
return
|
return
|
||||||
(((unsigned char)buffer[0]) << 24) +
|
(((unsigned char)buffer[0]) << 24) +
|
||||||
(((unsigned char)buffer[1]) << 16) +
|
(((unsigned char)buffer[1]) << 16) +
|
||||||
(((unsigned char)buffer[2]) << 8) +
|
(((unsigned char)buffer[2]) << 8) +
|
||||||
(unsigned char)buffer[3];
|
(unsigned char)buffer[3];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,49 +1,49 @@
|
||||||
/*
|
/*
|
||||||
* synergy -- mouse and keyboard sharing utility
|
* synergy -- mouse and keyboard sharing utility
|
||||||
* Copyright (C) 2012 Bolton Software Ltd.
|
* Copyright (C) 2012 Bolton Software Ltd.
|
||||||
* Copyright (C) 2012 Nick Bolton
|
* Copyright (C) 2012 Nick Bolton
|
||||||
*
|
*
|
||||||
* 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
|
||||||
* found in the file COPYING that should have accompanied this file.
|
* found in the file COPYING that should have accompanied this file.
|
||||||
*
|
*
|
||||||
* This package is distributed in the hope that it will be useful,
|
* This package is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* 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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
|
|
||||||
class QTcpSocket;
|
class QTcpSocket;
|
||||||
|
|
||||||
class IpcReader : public QObject
|
class IpcReader : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT;
|
Q_OBJECT;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IpcReader(QTcpSocket* socket);
|
IpcReader(QTcpSocket* socket);
|
||||||
virtual ~IpcReader();
|
virtual ~IpcReader();
|
||||||
void start();
|
void start();
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void readLogLine(const QString& text);
|
void readLogLine(const QString& text);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool readStream(char* buffer, int length);
|
bool readStream(char* buffer, int length);
|
||||||
int bytesToInt(const char* buffer, int size);
|
int bytesToInt(const char* buffer, int size);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void read();
|
void read();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QTcpSocket* m_Socket;
|
QTcpSocket* m_Socket;
|
||||||
QMutex m_Mutex;
|
QMutex m_Mutex;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,51 +1,51 @@
|
||||||
/*
|
/*
|
||||||
* synergy -- mouse and keyboard sharing utility
|
* synergy -- mouse and keyboard sharing utility
|
||||||
* Copyright (C) 2013 Bolton Software Ltd.
|
* Copyright (C) 2013 Bolton Software 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
|
||||||
* found in the file COPYING that should have accompanied this file.
|
* found in the file COPYING that should have accompanied this file.
|
||||||
*
|
*
|
||||||
* This package is distributed in the hope that it will be useful,
|
* This package is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* 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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "QUtility.h"
|
#include "QUtility.h"
|
||||||
|
|
||||||
void setIndexFromItemData(QComboBox* comboBox, const QVariant& itemData)
|
void setIndexFromItemData(QComboBox* comboBox, const QVariant& itemData)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < comboBox->count(); ++i)
|
for (int i = 0; i < comboBox->count(); ++i)
|
||||||
{
|
{
|
||||||
if (comboBox->itemData(i) == itemData)
|
if (comboBox->itemData(i) == itemData)
|
||||||
{
|
{
|
||||||
comboBox->setCurrentIndex(i);
|
comboBox->setCurrentIndex(i);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString hash(const QString& string)
|
QString hash(const QString& string)
|
||||||
{
|
{
|
||||||
QByteArray data = string.toUtf8();
|
QByteArray data = string.toUtf8();
|
||||||
QByteArray hash = QCryptographicHash::hash(data, QCryptographicHash::Md5);
|
QByteArray hash = QCryptographicHash::hash(data, QCryptographicHash::Md5);
|
||||||
return hash.toHex();
|
return hash.toHex();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString getFirstMacAddress()
|
QString getFirstMacAddress()
|
||||||
{
|
{
|
||||||
QString mac;
|
QString mac;
|
||||||
foreach (const QNetworkInterface &interface, QNetworkInterface::allInterfaces())
|
foreach (const QNetworkInterface &interface, QNetworkInterface::allInterfaces())
|
||||||
{
|
{
|
||||||
mac = interface.hardwareAddress();
|
mac = interface.hardwareAddress();
|
||||||
if (mac.size() != 0)
|
if (mac.size() != 0)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return mac;
|
return mac;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +1,27 @@
|
||||||
/*
|
/*
|
||||||
* synergy -- mouse and keyboard sharing utility
|
* synergy -- mouse and keyboard sharing utility
|
||||||
* Copyright (C) 2013 Bolton Software Ltd.
|
* Copyright (C) 2013 Bolton Software 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
|
||||||
* found in the file COPYING that should have accompanied this file.
|
* found in the file COPYING that should have accompanied this file.
|
||||||
*
|
*
|
||||||
* This package is distributed in the hope that it will be useful,
|
* This package is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* 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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include <QCryptographicHash>
|
#include <QCryptographicHash>
|
||||||
#include <QNetworkInterface>
|
#include <QNetworkInterface>
|
||||||
|
|
||||||
void setIndexFromItemData(QComboBox* comboBox, const QVariant& itemData);
|
void setIndexFromItemData(QComboBox* comboBox, const QVariant& itemData);
|
||||||
QString hash(const QString& string);
|
QString hash(const QString& string);
|
||||||
QString getFirstMacAddress();
|
QString getFirstMacAddress();
|
||||||
|
|
|
@ -1,334 +1,334 @@
|
||||||
/*
|
/*
|
||||||
* synergy -- mouse and keyboard sharing utility
|
* synergy -- mouse and keyboard sharing utility
|
||||||
* Copyright (C) 2012 Bolton Software Ltd.
|
* Copyright (C) 2012 Bolton Software 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
|
||||||
* found in the file COPYING that should have accompanied this file.
|
* found in the file COPYING that should have accompanied this file.
|
||||||
*
|
*
|
||||||
* This package is distributed in the hope that it will be useful,
|
* This package is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* 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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "SetupWizard.h"
|
#include "SetupWizard.h"
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
#include "QSynergyApplication.h"
|
#include "QSynergyApplication.h"
|
||||||
#include "QUtility.h"
|
#include "QUtility.h"
|
||||||
|
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
|
|
||||||
//#define PREMIUM_AUTH_URL "http://localhost/synergy/premium/json/auth/"
|
//#define PREMIUM_AUTH_URL "http://localhost/synergy/premium/json/auth/"
|
||||||
#define PREMIUM_AUTH_URL "https://synergy-foss.org/premium/json/auth/"
|
#define PREMIUM_AUTH_URL "https://synergy-foss.org/premium/json/auth/"
|
||||||
#define PREMIUM_REGISTER_URL "https://synergy-foss.org/premium/register/?source=gui-wizard"
|
#define PREMIUM_REGISTER_URL "https://synergy-foss.org/premium/register/?source=gui-wizard"
|
||||||
|
|
||||||
SetupWizard::SetupWizard(MainWindow& mainWindow, bool startMain) :
|
SetupWizard::SetupWizard(MainWindow& mainWindow, bool startMain) :
|
||||||
m_MainWindow(mainWindow),
|
m_MainWindow(mainWindow),
|
||||||
m_StartMain(startMain)
|
m_StartMain(startMain)
|
||||||
{
|
{
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
|
|
||||||
#if defined(Q_OS_MAC)
|
#if defined(Q_OS_MAC)
|
||||||
|
|
||||||
// the mac style needs a little more room because of the
|
// the mac style needs a little more room because of the
|
||||||
// graphic on the left.
|
// graphic on the left.
|
||||||
resize(600, 500);
|
resize(600, 500);
|
||||||
setMinimumSize(size());
|
setMinimumSize(size());
|
||||||
|
|
||||||
#elif defined(Q_OS_WIN)
|
#elif defined(Q_OS_WIN)
|
||||||
|
|
||||||
// when areo is disabled on windows, the next/back buttons
|
// when areo is disabled on windows, the next/back buttons
|
||||||
// are hidden (must be a qt bug) -- resizing the window
|
// are hidden (must be a qt bug) -- resizing the window
|
||||||
// to +1 of the original height seems to fix this.
|
// to +1 of the original height seems to fix this.
|
||||||
// NOTE: calling setMinimumSize after this will break
|
// NOTE: calling setMinimumSize after this will break
|
||||||
// it again, so don't do that.
|
// it again, so don't do that.
|
||||||
resize(size().width(), size().height() + 1);
|
resize(size().width(), size().height() + 1);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
connect(m_pServerRadioButton, SIGNAL(toggled(bool)), m_MainWindow.m_pGroupServer, SLOT(setChecked(bool)));
|
connect(m_pServerRadioButton, SIGNAL(toggled(bool)), m_MainWindow.m_pGroupServer, SLOT(setChecked(bool)));
|
||||||
connect(m_pClientRadioButton, SIGNAL(toggled(bool)), m_MainWindow.m_pGroupClient, SLOT(setChecked(bool)));
|
connect(m_pClientRadioButton, SIGNAL(toggled(bool)), m_MainWindow.m_pGroupClient, SLOT(setChecked(bool)));
|
||||||
|
|
||||||
m_Locale.fillLanguageComboBox(m_pComboLanguage);
|
m_Locale.fillLanguageComboBox(m_pComboLanguage);
|
||||||
setIndexFromItemData(m_pComboLanguage, m_MainWindow.appConfig().language());
|
setIndexFromItemData(m_pComboLanguage, m_MainWindow.appConfig().language());
|
||||||
AppConfig& appConfig = m_MainWindow.appConfig();
|
AppConfig& appConfig = m_MainWindow.appConfig();
|
||||||
QString premiumEmail = appConfig.premiumEmail();
|
QString premiumEmail = appConfig.premiumEmail();
|
||||||
if (!premiumEmail.isEmpty())
|
if (!premiumEmail.isEmpty())
|
||||||
{
|
{
|
||||||
m_pRadioButtonPremiumLogin->setChecked(true);
|
m_pRadioButtonPremiumLogin->setChecked(true);
|
||||||
m_pLineEditPremiumEmail->setText(premiumEmail);
|
m_pLineEditPremiumEmail->setText(premiumEmail);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SetupWizard::~SetupWizard()
|
SetupWizard::~SetupWizard()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SetupWizard::validateCurrentPage()
|
bool SetupWizard::validateCurrentPage()
|
||||||
{
|
{
|
||||||
QMessageBox message;
|
QMessageBox message;
|
||||||
message.setWindowTitle(tr("Setup Synergy"));
|
message.setWindowTitle(tr("Setup Synergy"));
|
||||||
message.setIcon(QMessageBox::Information);
|
message.setIcon(QMessageBox::Information);
|
||||||
|
|
||||||
if (currentPage() == m_pNodePage)
|
if (currentPage() == m_pNodePage)
|
||||||
{
|
{
|
||||||
bool result = m_pClientRadioButton->isChecked() ||
|
bool result = m_pClientRadioButton->isChecked() ||
|
||||||
m_pServerRadioButton->isChecked();
|
m_pServerRadioButton->isChecked();
|
||||||
|
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
message.setText(tr("Please select an option."));
|
message.setText(tr("Please select an option."));
|
||||||
message.exec();
|
message.exec();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (currentPage() == m_pPremiumUserPage)
|
else if (currentPage() == m_pPremiumUserPage)
|
||||||
{
|
{
|
||||||
if (m_pRadioButtonPremiumLogin->isChecked())
|
if (m_pRadioButtonPremiumLogin->isChecked())
|
||||||
{
|
{
|
||||||
if (m_pLineEditPremiumEmail->text().isEmpty() ||
|
if (m_pLineEditPremiumEmail->text().isEmpty() ||
|
||||||
m_pLineEditPremiumPassword->text().isEmpty())
|
m_pLineEditPremiumPassword->text().isEmpty())
|
||||||
{
|
{
|
||||||
message.setText(tr("Please enter your email address and password."));
|
message.setText(tr("Please enter your email address and password."));
|
||||||
message.exec();
|
message.exec();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (!isPremiumLoginValid(message))
|
else if (!isPremiumLoginValid(message))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_pComboCryptoMode->setCurrentIndex(0);
|
m_pComboCryptoMode->setCurrentIndex(0);
|
||||||
m_pComboCryptoMode->setEnabled(true);
|
m_pComboCryptoMode->setEnabled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (m_pRadioButtonPremiumRegister->isChecked())
|
else if (m_pRadioButtonPremiumRegister->isChecked())
|
||||||
{
|
{
|
||||||
const QUrl url(QString(PREMIUM_REGISTER_URL));
|
const QUrl url(QString(PREMIUM_REGISTER_URL));
|
||||||
QDesktopServices::openUrl(url);
|
QDesktopServices::openUrl(url);
|
||||||
m_pRadioButtonPremiumLogin->setChecked(true);
|
m_pRadioButtonPremiumLogin->setChecked(true);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (m_pRadioButtonPremiumLater->isChecked())
|
else if (m_pRadioButtonPremiumLater->isChecked())
|
||||||
{
|
{
|
||||||
int size = m_pComboCryptoMode->count();
|
int size = m_pComboCryptoMode->count();
|
||||||
m_pComboCryptoMode->setCurrentIndex(size - 1);
|
m_pComboCryptoMode->setCurrentIndex(size - 1);
|
||||||
m_pComboCryptoMode->setEnabled(false);
|
m_pComboCryptoMode->setEnabled(false);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
message.setText(tr("Please select an option."));
|
message.setText(tr("Please select an option."));
|
||||||
message.exec();
|
message.exec();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (currentPage() == m_pCryptoPage)
|
else if (currentPage() == m_pCryptoPage)
|
||||||
{
|
{
|
||||||
QString modeText = m_pComboCryptoMode->currentText();
|
QString modeText = m_pComboCryptoMode->currentText();
|
||||||
if (modeText.isEmpty())
|
if (modeText.isEmpty())
|
||||||
{
|
{
|
||||||
message.setText(tr("Encryption mode required."));
|
message.setText(tr("Encryption mode required."));
|
||||||
message.exec();
|
message.exec();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parseCryptoMode(modeText) != Disabled)
|
if (parseCryptoMode(modeText) != Disabled)
|
||||||
{
|
{
|
||||||
if (m_pLineEditCryptoPassword1->text().isEmpty())
|
if (m_pLineEditCryptoPassword1->text().isEmpty())
|
||||||
{
|
{
|
||||||
message.setText(tr("Encryption password required."));
|
message.setText(tr("Encryption password required."));
|
||||||
message.exec();
|
message.exec();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_pLineEditCryptoPassword1->text() != m_pLineEditCryptoPassword2->text())
|
if (m_pLineEditCryptoPassword1->text() != m_pLineEditCryptoPassword2->text())
|
||||||
{
|
{
|
||||||
message.setText(tr("Encryption password and confirmation do not match."));
|
message.setText(tr("Encryption password and confirmation do not match."));
|
||||||
message.exec();
|
message.exec();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupWizard::changeEvent(QEvent* event)
|
void SetupWizard::changeEvent(QEvent* event)
|
||||||
{
|
{
|
||||||
if (event != 0)
|
if (event != 0)
|
||||||
{
|
{
|
||||||
switch (event->type())
|
switch (event->type())
|
||||||
{
|
{
|
||||||
case QEvent::LanguageChange:
|
case QEvent::LanguageChange:
|
||||||
{
|
{
|
||||||
m_pComboLanguage->blockSignals(true);
|
m_pComboLanguage->blockSignals(true);
|
||||||
retranslateUi(this);
|
retranslateUi(this);
|
||||||
m_pComboLanguage->blockSignals(false);
|
m_pComboLanguage->blockSignals(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
QWizard::changeEvent(event);
|
QWizard::changeEvent(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupWizard::accept()
|
void SetupWizard::accept()
|
||||||
{
|
{
|
||||||
AppConfig& appConfig = m_MainWindow.appConfig();
|
AppConfig& appConfig = m_MainWindow.appConfig();
|
||||||
|
|
||||||
appConfig.setCryptoMode(parseCryptoMode(m_pComboCryptoMode->currentText()));
|
appConfig.setCryptoMode(parseCryptoMode(m_pComboCryptoMode->currentText()));
|
||||||
appConfig.setCryptoPass(m_pLineEditCryptoPassword1->text());
|
appConfig.setCryptoPass(m_pLineEditCryptoPassword1->text());
|
||||||
appConfig.setLanguage(m_pComboLanguage->itemData(m_pComboLanguage->currentIndex()).toString());
|
appConfig.setLanguage(m_pComboLanguage->itemData(m_pComboLanguage->currentIndex()).toString());
|
||||||
appConfig.setPremiumEmail(m_pLineEditPremiumEmail->text());
|
appConfig.setPremiumEmail(m_pLineEditPremiumEmail->text());
|
||||||
|
|
||||||
if (!m_pRadioButtonPremiumLogin->isChecked())
|
if (!m_pRadioButtonPremiumLogin->isChecked())
|
||||||
{
|
{
|
||||||
appConfig.setPremiumToken("");
|
appConfig.setPremiumToken("");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QString mac = getFirstMacAddress();
|
QString mac = getFirstMacAddress();
|
||||||
QString hashSrc = m_pLineEditPremiumEmail->text() + mac;
|
QString hashSrc = m_pLineEditPremiumEmail->text() + mac;
|
||||||
QString hashResult = hash(hashSrc);
|
QString hashResult = hash(hashSrc);
|
||||||
appConfig.setPremiumToken(hashResult);
|
appConfig.setPremiumToken(hashResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
appConfig.setWizardHasRun();
|
appConfig.setWizardHasRun();
|
||||||
appConfig.saveSettings();
|
appConfig.saveSettings();
|
||||||
|
|
||||||
QSettings& settings = m_MainWindow.settings();
|
QSettings& settings = m_MainWindow.settings();
|
||||||
if (m_pServerRadioButton->isChecked())
|
if (m_pServerRadioButton->isChecked())
|
||||||
{
|
{
|
||||||
settings.setValue("groupServerChecked", true);
|
settings.setValue("groupServerChecked", true);
|
||||||
settings.setValue("groupClientChecked", false);
|
settings.setValue("groupClientChecked", false);
|
||||||
}
|
}
|
||||||
if (m_pClientRadioButton->isChecked())
|
if (m_pClientRadioButton->isChecked())
|
||||||
{
|
{
|
||||||
settings.setValue("groupClientChecked", true);
|
settings.setValue("groupClientChecked", true);
|
||||||
settings.setValue("groupServerChecked", false);
|
settings.setValue("groupServerChecked", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
settings.sync();
|
settings.sync();
|
||||||
|
|
||||||
if (m_StartMain)
|
if (m_StartMain)
|
||||||
{
|
{
|
||||||
m_MainWindow.start(true);
|
m_MainWindow.start(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
QWizard::accept();
|
QWizard::accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupWizard::reject()
|
void SetupWizard::reject()
|
||||||
{
|
{
|
||||||
QSynergyApplication::getInstance()->switchTranslator(m_MainWindow.appConfig().language());
|
QSynergyApplication::getInstance()->switchTranslator(m_MainWindow.appConfig().language());
|
||||||
|
|
||||||
if (m_StartMain)
|
if (m_StartMain)
|
||||||
{
|
{
|
||||||
m_MainWindow.start(true);
|
m_MainWindow.start(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
QWizard::reject();
|
QWizard::reject();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupWizard::on_m_pComboCryptoMode_currentIndexChanged(int index)
|
void SetupWizard::on_m_pComboCryptoMode_currentIndexChanged(int index)
|
||||||
{
|
{
|
||||||
bool enabled = parseCryptoMode(m_pComboCryptoMode->currentText()) != Disabled;
|
bool enabled = parseCryptoMode(m_pComboCryptoMode->currentText()) != Disabled;
|
||||||
m_pLineEditCryptoPassword1->setEnabled(enabled);
|
m_pLineEditCryptoPassword1->setEnabled(enabled);
|
||||||
m_pLineEditCryptoPassword2->setEnabled(enabled);
|
m_pLineEditCryptoPassword2->setEnabled(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
CryptoMode SetupWizard::parseCryptoMode(const QString& s)
|
CryptoMode SetupWizard::parseCryptoMode(const QString& s)
|
||||||
{
|
{
|
||||||
if (s.startsWith("OFB"))
|
if (s.startsWith("OFB"))
|
||||||
{
|
{
|
||||||
return OFB;
|
return OFB;
|
||||||
}
|
}
|
||||||
else if (s.startsWith("CFB"))
|
else if (s.startsWith("CFB"))
|
||||||
{
|
{
|
||||||
return CFB;
|
return CFB;
|
||||||
}
|
}
|
||||||
else if (s.startsWith("CTR"))
|
else if (s.startsWith("CTR"))
|
||||||
{
|
{
|
||||||
return CTR;
|
return CTR;
|
||||||
}
|
}
|
||||||
else if (s.startsWith("GCM"))
|
else if (s.startsWith("GCM"))
|
||||||
{
|
{
|
||||||
return GCM;
|
return GCM;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Disabled;
|
return Disabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupWizard::on_m_pComboLanguage_currentIndexChanged(int index)
|
void SetupWizard::on_m_pComboLanguage_currentIndexChanged(int index)
|
||||||
{
|
{
|
||||||
QString ietfCode = m_pComboLanguage->itemData(index).toString();
|
QString ietfCode = m_pComboLanguage->itemData(index).toString();
|
||||||
QSynergyApplication::getInstance()->switchTranslator(ietfCode);
|
QSynergyApplication::getInstance()->switchTranslator(ietfCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupWizard::on_m_pRadioButtonPremiumLogin_toggled(bool checked)
|
void SetupWizard::on_m_pRadioButtonPremiumLogin_toggled(bool checked)
|
||||||
{
|
{
|
||||||
m_pLineEditPremiumEmail->setEnabled(checked);
|
m_pLineEditPremiumEmail->setEnabled(checked);
|
||||||
m_pLineEditPremiumPassword->setEnabled(checked);
|
m_pLineEditPremiumPassword->setEnabled(checked);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SetupWizard::isPremiumLoginValid(QMessageBox& message)
|
bool SetupWizard::isPremiumLoginValid(QMessageBox& message)
|
||||||
{
|
{
|
||||||
QString email = m_pLineEditPremiumEmail->text();
|
QString email = m_pLineEditPremiumEmail->text();
|
||||||
QString password = m_pLineEditPremiumPassword->text();
|
QString password = m_pLineEditPremiumPassword->text();
|
||||||
|
|
||||||
QString requestJson = "{\"email\":\"" + email + "\",\"password\":\"" + password + "\"}";
|
QString requestJson = "{\"email\":\"" + email + "\",\"password\":\"" + password + "\"}";
|
||||||
QByteArray requestData(requestJson.toStdString().c_str());
|
QByteArray requestData(requestJson.toStdString().c_str());
|
||||||
|
|
||||||
QString version = m_MainWindow.versionChecker().getVersion();
|
QString version = m_MainWindow.versionChecker().getVersion();
|
||||||
QString userAgent = "Synergy GUI " + version;
|
QString userAgent = "Synergy GUI " + version;
|
||||||
QByteArray userAgentData(userAgent.toStdString().c_str());
|
QByteArray userAgentData(userAgent.toStdString().c_str());
|
||||||
|
|
||||||
QNetworkRequest request(QUrl(PREMIUM_AUTH_URL));
|
QNetworkRequest request(QUrl(PREMIUM_AUTH_URL));
|
||||||
request.setRawHeader("User-Agent", userAgentData);
|
request.setRawHeader("User-Agent", userAgentData);
|
||||||
|
|
||||||
QUrl params;
|
QUrl params;
|
||||||
params.addEncodedQueryItem("json", requestData);
|
params.addEncodedQueryItem("json", requestData);
|
||||||
QNetworkReply* reply = m_Network.post(request, params.encodedQuery());
|
QNetworkReply* reply = m_Network.post(request, params.encodedQuery());
|
||||||
|
|
||||||
// use loop instead of waitForReadyRead (which doesnt seem to work).
|
// use loop instead of waitForReadyRead (which doesnt seem to work).
|
||||||
QEventLoop loop;
|
QEventLoop loop;
|
||||||
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
|
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
|
||||||
loop.exec();
|
loop.exec();
|
||||||
|
|
||||||
if (reply->error() != QNetworkReply::NoError) {
|
if (reply->error() != QNetworkReply::NoError) {
|
||||||
message.setText(tr("Login failed, an error occurred.\n\nError: %1").arg(reply->errorString()));
|
message.setText(tr("Login failed, an error occurred.\n\nError: %1").arg(reply->errorString()));
|
||||||
message.exec();
|
message.exec();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray responseData = reply->readAll();
|
QByteArray responseData = reply->readAll();
|
||||||
QString responseJson(responseData);
|
QString responseJson(responseData);
|
||||||
|
|
||||||
// this feels like a lot of work, but its cheaper than getting a json
|
// this feels like a lot of work, but its cheaper than getting a json
|
||||||
// parsing library involved.
|
// parsing library involved.
|
||||||
QRegExp regex(".*\"result\":\\s*([^,}\\s]+).*");
|
QRegExp regex(".*\"result\":\\s*([^,}\\s]+).*");
|
||||||
if (regex.exactMatch(responseJson)) {
|
if (regex.exactMatch(responseJson)) {
|
||||||
QString boolString = regex.cap(1);
|
QString boolString = regex.cap(1);
|
||||||
if (boolString == "true") {
|
if (boolString == "true") {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (boolString == "false") {
|
else if (boolString == "false") {
|
||||||
message.setText(tr("Login failed, invalid email or password."));
|
message.setText(tr("Login failed, invalid email or password."));
|
||||||
message.exec();
|
message.exec();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
message.setText(tr("Login failed, an error occurred.\n\nServer response:\n\n%1").arg(responseJson.trimmed()));
|
message.setText(tr("Login failed, an error occurred.\n\nServer response:\n\n%1").arg(responseJson.trimmed()));
|
||||||
message.exec();
|
message.exec();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,57 +1,57 @@
|
||||||
/*
|
/*
|
||||||
* synergy -- mouse and keyboard sharing utility
|
* synergy -- mouse and keyboard sharing utility
|
||||||
* Copyright (C) 2012 Bolton Software Ltd.
|
* Copyright (C) 2012 Bolton Software 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
|
||||||
* found in the file COPYING that should have accompanied this file.
|
* found in the file COPYING that should have accompanied this file.
|
||||||
*
|
*
|
||||||
* This package is distributed in the hope that it will be useful,
|
* This package is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* 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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ui_SetupWizardBase.h"
|
#include "ui_SetupWizardBase.h"
|
||||||
#include "CryptoMode.h"
|
#include "CryptoMode.h"
|
||||||
#include "SynergyLocale.h"
|
#include "SynergyLocale.h"
|
||||||
|
|
||||||
#include <QWizard>
|
#include <QWizard>
|
||||||
#include <QNetworkAccessManager>
|
#include <QNetworkAccessManager>
|
||||||
|
|
||||||
class MainWindow;
|
class MainWindow;
|
||||||
class QMessageBox;
|
class QMessageBox;
|
||||||
|
|
||||||
class SetupWizard : public QWizard, public Ui::SetupWizardBase
|
class SetupWizard : public QWizard, public Ui::SetupWizardBase
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
SetupWizard(MainWindow& mainWindow, bool startMain);
|
SetupWizard(MainWindow& mainWindow, bool startMain);
|
||||||
virtual ~SetupWizard();
|
virtual ~SetupWizard();
|
||||||
bool validateCurrentPage();
|
bool validateCurrentPage();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void changeEvent(QEvent* event);
|
void changeEvent(QEvent* event);
|
||||||
void accept();
|
void accept();
|
||||||
void reject();
|
void reject();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CryptoMode parseCryptoMode(const QString& s);
|
CryptoMode parseCryptoMode(const QString& s);
|
||||||
bool isPremiumLoginValid(QMessageBox& message);
|
bool isPremiumLoginValid(QMessageBox& message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MainWindow& m_MainWindow;
|
MainWindow& m_MainWindow;
|
||||||
bool m_StartMain;
|
bool m_StartMain;
|
||||||
SynergyLocale m_Locale;
|
SynergyLocale m_Locale;
|
||||||
QNetworkAccessManager m_Network;
|
QNetworkAccessManager m_Network;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_m_pComboCryptoMode_currentIndexChanged(int index);
|
void on_m_pComboCryptoMode_currentIndexChanged(int index);
|
||||||
void on_m_pComboLanguage_currentIndexChanged(int index);
|
void on_m_pComboLanguage_currentIndexChanged(int index);
|
||||||
void on_m_pRadioButtonPremiumLogin_toggled(bool checked);
|
void on_m_pRadioButtonPremiumLogin_toggled(bool checked);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,68 +1,68 @@
|
||||||
/*
|
/*
|
||||||
* synergy -- mouse and keyboard sharing utility
|
* synergy -- mouse and keyboard sharing utility
|
||||||
* Copyright (C) 2013 Bolton Software Ltd.
|
* Copyright (C) 2013 Bolton Software 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
|
||||||
* found in the file COPYING that should have accompanied this file.
|
* found in the file COPYING that should have accompanied this file.
|
||||||
*
|
*
|
||||||
* This package is distributed in the hope that it will be useful,
|
* This package is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* 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/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "SynergyLocale.h"
|
#include "SynergyLocale.h"
|
||||||
|
|
||||||
#include <QResource>
|
#include <QResource>
|
||||||
#include <QtXml/QXmlStreamReader>
|
#include <QtXml/QXmlStreamReader>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
SynergyLocale::SynergyLocale()
|
SynergyLocale::SynergyLocale()
|
||||||
{
|
{
|
||||||
loadLanguages();
|
loadLanguages();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SynergyLocale::loadLanguages()
|
void SynergyLocale::loadLanguages()
|
||||||
{
|
{
|
||||||
QResource resource(":/res/lang/Languages.xml");
|
QResource resource(":/res/lang/Languages.xml");
|
||||||
QByteArray bytes(reinterpret_cast<const char*>(resource.data()), resource.size());
|
QByteArray bytes(reinterpret_cast<const char*>(resource.data()), resource.size());
|
||||||
QXmlStreamReader xml(bytes);
|
QXmlStreamReader xml(bytes);
|
||||||
|
|
||||||
while (!xml.atEnd())
|
while (!xml.atEnd())
|
||||||
{
|
{
|
||||||
QXmlStreamReader::TokenType token = xml.readNext();
|
QXmlStreamReader::TokenType token = xml.readNext();
|
||||||
if (xml.hasError())
|
if (xml.hasError())
|
||||||
{
|
{
|
||||||
qCritical() << xml.errorString();
|
qCritical() << xml.errorString();
|
||||||
throw std::exception();
|
throw std::exception();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xml.name() == "language" && token == QXmlStreamReader::StartElement)
|
if (xml.name() == "language" && token == QXmlStreamReader::StartElement)
|
||||||
{
|
{
|
||||||
QXmlStreamAttributes attributes = xml.attributes();
|
QXmlStreamAttributes attributes = xml.attributes();
|
||||||
addLanguage(
|
addLanguage(
|
||||||
attributes.value("ietfCode").toString(),
|
attributes.value("ietfCode").toString(),
|
||||||
attributes.value("name").toString());
|
attributes.value("name").toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SynergyLocale::addLanguage(const QString& ietfCode, const QString& name)
|
void SynergyLocale::addLanguage(const QString& ietfCode, const QString& name)
|
||||||
{
|
{
|
||||||
m_Languages.push_back(SynergyLocale::Language(ietfCode, name));
|
m_Languages.push_back(SynergyLocale::Language(ietfCode, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SynergyLocale::fillLanguageComboBox(QComboBox* comboBox)
|
void SynergyLocale::fillLanguageComboBox(QComboBox* comboBox)
|
||||||
{
|
{
|
||||||
comboBox->blockSignals(true);
|
comboBox->blockSignals(true);
|
||||||
QVector<SynergyLocale::Language>::iterator it;
|
QVector<SynergyLocale::Language>::iterator it;
|
||||||
for (it = m_Languages.begin(); it != m_Languages.end(); ++it)
|
for (it = m_Languages.begin(); it != m_Languages.end(); ++it)
|
||||||
{
|
{
|
||||||
comboBox->addItem((*it).m_Name, (*it).m_IetfCode);
|
comboBox->addItem((*it).m_Name, (*it).m_IetfCode);
|
||||||
}
|
}
|
||||||
comboBox->blockSignals(false);
|
comboBox->blockSignals(false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,48 +1,48 @@
|
||||||
/*
|
/*
|
||||||
* synergy -- mouse and keyboard sharing utility
|
* synergy -- mouse and keyboard sharing utility
|
||||||
* Copyright (C) 2013 Bolton Software Ltd.
|
* Copyright (C) 2013 Bolton Software 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
|
||||||
* found in the file COPYING that should have accompanied this file.
|
* found in the file COPYING that should have accompanied this file.
|
||||||
*
|
*
|
||||||
* This package is distributed in the hope that it will be useful,
|
* This package is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* 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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
|
|
||||||
class SynergyLocale
|
class SynergyLocale
|
||||||
{
|
{
|
||||||
class Language
|
class Language
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Language() { }
|
Language() { }
|
||||||
Language(const QString& IetfCode, const QString& name)
|
Language(const QString& IetfCode, const QString& name)
|
||||||
: m_IetfCode(IetfCode), m_Name(name) { }
|
: m_IetfCode(IetfCode), m_Name(name) { }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QString m_IetfCode;
|
QString m_IetfCode;
|
||||||
QString m_Name;
|
QString m_Name;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SynergyLocale();
|
SynergyLocale();
|
||||||
void fillLanguageComboBox(QComboBox* comboBox);
|
void fillLanguageComboBox(QComboBox* comboBox);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void loadLanguages();
|
void loadLanguages();
|
||||||
void addLanguage(const QString& IetfCode, const QString& name);
|
void addLanguage(const QString& IetfCode, const QString& name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QVector<Language> m_Languages;
|
QVector<Language> m_Languages;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,30 +1,30 @@
|
||||||
/*
|
/*
|
||||||
* synergy -- mouse and keyboard sharing utility
|
* synergy -- mouse and keyboard sharing utility
|
||||||
* Copyright (C) 2012 Bolton Software Ltd.
|
* Copyright (C) 2012 Bolton Software Ltd.
|
||||||
* Copyright (C) 2012 Nick Bolton
|
* Copyright (C) 2012 Nick Bolton
|
||||||
*
|
*
|
||||||
* 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
|
||||||
* found in the file COPYING that should have accompanied this file.
|
* found in the file COPYING that should have accompanied this file.
|
||||||
*
|
*
|
||||||
* This package is distributed in the hope that it will be useful,
|
* This package is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* 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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "TcpSocketReader.h"
|
#include "TcpSocketReader.h"
|
||||||
#include <QTcpSocket>
|
#include <QTcpSocket>
|
||||||
|
|
||||||
IpcReader::IpcReader(QTcpSocket& socket) :
|
IpcReader::IpcReader(QTcpSocket& socket) :
|
||||||
m_Socket(socket)
|
m_Socket(socket)
|
||||||
{
|
{
|
||||||
connect(m_Socket, SIGNAL(readyRead()), this, SLOT(read()));
|
connect(m_Socket, SIGNAL(readyRead()), this, SLOT(read()));
|
||||||
}
|
}
|
||||||
|
|
||||||
IpcReader::~IpcReader()
|
IpcReader::~IpcReader()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,103 +1,103 @@
|
||||||
/*
|
/*
|
||||||
* synergy -- mouse and keyboard sharing utility
|
* synergy -- mouse and keyboard sharing utility
|
||||||
* Copyright (C) 2012 Bolton Software Ltd.
|
* Copyright (C) 2012 Bolton Software Ltd.
|
||||||
* Copyright (C) 2012 Nick Bolton
|
* Copyright (C) 2012 Nick Bolton
|
||||||
*
|
*
|
||||||
* 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
|
||||||
* found in the file COPYING that should have accompanied this file.
|
* found in the file COPYING that should have accompanied this file.
|
||||||
*
|
*
|
||||||
* This package is distributed in the hope that it will be useful,
|
* This package is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* 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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "VersionChecker.h"
|
#include "VersionChecker.h"
|
||||||
|
|
||||||
#include <QNetworkAccessManager>
|
#include <QNetworkAccessManager>
|
||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QLocale>
|
#include <QLocale>
|
||||||
|
|
||||||
#define VERSION_REGEX "(\\d+\\.\\d+\\.\\d+)"
|
#define VERSION_REGEX "(\\d+\\.\\d+\\.\\d+)"
|
||||||
#define VERSION_URL "http://synergy-foss.org/version/"
|
#define VERSION_URL "http://synergy-foss.org/version/"
|
||||||
|
|
||||||
VersionChecker::VersionChecker()
|
VersionChecker::VersionChecker()
|
||||||
{
|
{
|
||||||
m_manager = new QNetworkAccessManager(this);
|
m_manager = new QNetworkAccessManager(this);
|
||||||
|
|
||||||
connect(m_manager, SIGNAL(finished(QNetworkReply*)),
|
connect(m_manager, SIGNAL(finished(QNetworkReply*)),
|
||||||
this, SLOT(replyFinished(QNetworkReply*)));
|
this, SLOT(replyFinished(QNetworkReply*)));
|
||||||
}
|
}
|
||||||
|
|
||||||
VersionChecker::~VersionChecker()
|
VersionChecker::~VersionChecker()
|
||||||
{
|
{
|
||||||
delete m_manager;
|
delete m_manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VersionChecker::checkLatest()
|
void VersionChecker::checkLatest()
|
||||||
{
|
{
|
||||||
m_manager->get(QNetworkRequest(QUrl(VERSION_URL)));
|
m_manager->get(QNetworkRequest(QUrl(VERSION_URL)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void VersionChecker::replyFinished(QNetworkReply* reply)
|
void VersionChecker::replyFinished(QNetworkReply* reply)
|
||||||
{
|
{
|
||||||
QString newestVersion = QString(reply->readAll());
|
QString newestVersion = QString(reply->readAll());
|
||||||
if (!newestVersion.isEmpty())
|
if (!newestVersion.isEmpty())
|
||||||
{
|
{
|
||||||
QString currentVersion = getVersion();
|
QString currentVersion = getVersion();
|
||||||
if (compareVersions(currentVersion, newestVersion) > 0)
|
if (compareVersions(currentVersion, newestVersion) > 0)
|
||||||
emit updateFound(newestVersion);
|
emit updateFound(newestVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int VersionChecker::compareVersions(const QString& left, const QString& right)
|
int VersionChecker::compareVersions(const QString& left, const QString& right)
|
||||||
{
|
{
|
||||||
if (left.compare(right) == 0)
|
if (left.compare(right) == 0)
|
||||||
return 0; // versions are same.
|
return 0; // versions are same.
|
||||||
|
|
||||||
QStringList leftSplit = left.split(QRegExp("\\."));
|
QStringList leftSplit = left.split(QRegExp("\\."));
|
||||||
if (leftSplit.size() != 3)
|
if (leftSplit.size() != 3)
|
||||||
return 1; // assume right wins.
|
return 1; // assume right wins.
|
||||||
|
|
||||||
QStringList rightSplit = right.split(QRegExp("\\."));
|
QStringList rightSplit = right.split(QRegExp("\\."));
|
||||||
if (rightSplit.size() != 3)
|
if (rightSplit.size() != 3)
|
||||||
return -1; // assume left wins.
|
return -1; // assume left wins.
|
||||||
|
|
||||||
int leftMajor = leftSplit.at(0).toInt();
|
int leftMajor = leftSplit.at(0).toInt();
|
||||||
int leftMinor = leftSplit.at(1).toInt();
|
int leftMinor = leftSplit.at(1).toInt();
|
||||||
int leftRev = leftSplit.at(2).toInt();
|
int leftRev = leftSplit.at(2).toInt();
|
||||||
|
|
||||||
int rightMajor = rightSplit.at(0).toInt();
|
int rightMajor = rightSplit.at(0).toInt();
|
||||||
int rightMinor = rightSplit.at(1).toInt();
|
int rightMinor = rightSplit.at(1).toInt();
|
||||||
int rightRev = rightSplit.at(2).toInt();
|
int rightRev = rightSplit.at(2).toInt();
|
||||||
|
|
||||||
bool rightWins =
|
bool rightWins =
|
||||||
(rightMajor > leftMajor) ||
|
(rightMajor > leftMajor) ||
|
||||||
((rightMajor >= leftMajor) && (rightMinor > leftMinor)) ||
|
((rightMajor >= leftMajor) && (rightMinor > leftMinor)) ||
|
||||||
((rightMajor >= leftMajor) && (rightMinor >= leftMinor) && (rightRev > leftRev));
|
((rightMajor >= leftMajor) && (rightMinor >= leftMinor) && (rightRev > leftRev));
|
||||||
|
|
||||||
return rightWins ? 1 : -1;
|
return rightWins ? 1 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString VersionChecker::getVersion()
|
QString VersionChecker::getVersion()
|
||||||
{
|
{
|
||||||
QProcess process;
|
QProcess process;
|
||||||
process.start(m_app, QStringList() << "--version");
|
process.start(m_app, QStringList() << "--version");
|
||||||
|
|
||||||
process.setReadChannel(QProcess::StandardOutput);
|
process.setReadChannel(QProcess::StandardOutput);
|
||||||
if (process.waitForStarted() && process.waitForFinished())
|
if (process.waitForStarted() && process.waitForFinished())
|
||||||
{
|
{
|
||||||
QRegExp rx(VERSION_REGEX);
|
QRegExp rx(VERSION_REGEX);
|
||||||
QString text = process.readLine();
|
QString text = process.readLine();
|
||||||
if (rx.indexIn(text) != -1)
|
if (rx.indexIn(text) != -1)
|
||||||
return rx.cap(1);
|
return rx.cap(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return tr("Unknown");
|
return tr("Unknown");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,44 +1,44 @@
|
||||||
/*
|
/*
|
||||||
* synergy -- mouse and keyboard sharing utility
|
* synergy -- mouse and keyboard sharing utility
|
||||||
* Copyright (C) 2012 Bolton Software Ltd.
|
* Copyright (C) 2012 Bolton Software Ltd.
|
||||||
* Copyright (C) 2012 Nick Bolton
|
* Copyright (C) 2012 Nick Bolton
|
||||||
*
|
*
|
||||||
* 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
|
||||||
* found in the file COPYING that should have accompanied this file.
|
* found in the file COPYING that should have accompanied this file.
|
||||||
*
|
*
|
||||||
* This package is distributed in the hope that it will be useful,
|
* This package is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* 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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
class QNetworkAccessManager;
|
class QNetworkAccessManager;
|
||||||
class QNetworkReply;
|
class QNetworkReply;
|
||||||
|
|
||||||
class VersionChecker : public QObject
|
class VersionChecker : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
VersionChecker();
|
VersionChecker();
|
||||||
virtual ~VersionChecker();
|
virtual ~VersionChecker();
|
||||||
void checkLatest();
|
void checkLatest();
|
||||||
QString getVersion();
|
QString getVersion();
|
||||||
void setApp(const QString& app) { m_app = app; }
|
void setApp(const QString& app) { m_app = app; }
|
||||||
int compareVersions(const QString& left, const QString& right);
|
int compareVersions(const QString& left, const QString& right);
|
||||||
public slots:
|
public slots:
|
||||||
void replyFinished(QNetworkReply* reply);
|
void replyFinished(QNetworkReply* reply);
|
||||||
signals:
|
signals:
|
||||||
void updateFound(const QString& version);
|
void updateFound(const QString& version);
|
||||||
private:
|
private:
|
||||||
QNetworkAccessManager* m_manager;
|
QNetworkAccessManager* m_manager;
|
||||||
QString m_app;
|
QString m_app;
|
||||||
};
|
};
|
||||||
|
|
|
@ -83,26 +83,26 @@ inet_aton(const char* cp, struct in_addr* inp)
|
||||||
//
|
//
|
||||||
// CArchNetworkBSD
|
// CArchNetworkBSD
|
||||||
//
|
//
|
||||||
|
|
||||||
CArchNetworkBSD::CArchNetworkBSD()
|
CArchNetworkBSD::CArchNetworkBSD()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CArchNetworkBSD::~CArchNetworkBSD()
|
CArchNetworkBSD::~CArchNetworkBSD()
|
||||||
|
{
|
||||||
|
ARCH->closeMutex(m_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CArchNetworkBSD::init()
|
||||||
|
{
|
||||||
|
// create mutex to make some calls thread safe
|
||||||
|
m_mutex = ARCH->newMutex();
|
||||||
|
}
|
||||||
|
|
||||||
|
CArchSocket
|
||||||
|
CArchNetworkBSD::newSocket(EAddressFamily family, ESocketType type)
|
||||||
{
|
{
|
||||||
ARCH->closeMutex(m_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CArchNetworkBSD::init()
|
|
||||||
{
|
|
||||||
// create mutex to make some calls thread safe
|
|
||||||
m_mutex = ARCH->newMutex();
|
|
||||||
}
|
|
||||||
|
|
||||||
CArchSocket
|
|
||||||
CArchNetworkBSD::newSocket(EAddressFamily family, ESocketType type)
|
|
||||||
{
|
|
||||||
// create socket
|
// create socket
|
||||||
int fd = socket(s_family[family], s_type[type], 0);
|
int fd = socket(s_family[family], s_type[type], 0);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
|
|
|
@ -57,13 +57,13 @@ public:
|
||||||
//! Berkeley (BSD) sockets implementation of IArchNetwork
|
//! Berkeley (BSD) sockets implementation of IArchNetwork
|
||||||
class CArchNetworkBSD : public IArchNetwork {
|
class CArchNetworkBSD : public IArchNetwork {
|
||||||
public:
|
public:
|
||||||
CArchNetworkBSD();
|
CArchNetworkBSD();
|
||||||
virtual ~CArchNetworkBSD();
|
virtual ~CArchNetworkBSD();
|
||||||
|
|
||||||
virtual void init();
|
virtual void init();
|
||||||
|
|
||||||
// IArchNetwork overrides
|
// IArchNetwork overrides
|
||||||
virtual CArchSocket newSocket(EAddressFamily, ESocketType);
|
virtual CArchSocket newSocket(EAddressFamily, ESocketType);
|
||||||
virtual CArchSocket copySocket(CArchSocket s); virtual void closeSocket(CArchSocket s);
|
virtual CArchSocket copySocket(CArchSocket s); virtual void closeSocket(CArchSocket s);
|
||||||
virtual void closeSocketForRead(CArchSocket s);
|
virtual void closeSocketForRead(CArchSocket s);
|
||||||
virtual void closeSocketForWrite(CArchSocket s);
|
virtual void closeSocketForWrite(CArchSocket s);
|
||||||
|
|
|
@ -60,7 +60,7 @@ interrupt(CArch::ESignal, void* data)
|
||||||
|
|
||||||
CEventQueue::CEventQueue() :
|
CEventQueue::CEventQueue() :
|
||||||
m_systemTarget(0),
|
m_systemTarget(0),
|
||||||
m_nextType(CEvent::kLast),
|
m_nextType(CEvent::kLast),
|
||||||
m_typesForCClient(NULL),
|
m_typesForCClient(NULL),
|
||||||
m_typesForIStream(NULL),
|
m_typesForIStream(NULL),
|
||||||
m_typesForCIpcClient(NULL),
|
m_typesForCIpcClient(NULL),
|
||||||
|
|
|
@ -178,7 +178,7 @@ CLog::print(const char* file, int line, const char* fmt, ...)
|
||||||
// do not prefix time and file for kPRINT (CLOG_PRINT)
|
// do not prefix time and file for kPRINT (CLOG_PRINT)
|
||||||
if (priority != kPRINT) {
|
if (priority != kPRINT) {
|
||||||
|
|
||||||
char message[2048];
|
char message[kLogMessageLength];
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
struct tm *tm;
|
struct tm *tm;
|
||||||
|
|
|
@ -137,6 +137,8 @@ private:
|
||||||
int m_maxPriority;
|
int m_maxPriority;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const UInt16 kLogMessageLength = 2048;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\def LOG(arg)
|
\def LOG(arg)
|
||||||
Write to the log. Because macros cannot accept variable arguments, this
|
Write to the log. Because macros cannot accept variable arguments, this
|
||||||
|
|
|
@ -33,14 +33,20 @@
|
||||||
#include "CArch.h"
|
#include "CArch.h"
|
||||||
#include "IPlatformScreen.h"
|
#include "IPlatformScreen.h"
|
||||||
#include "CCryptoStream.h"
|
#include "CCryptoStream.h"
|
||||||
|
#include "CThread.h"
|
||||||
|
#include "TMethodJob.h"
|
||||||
|
#include "CFileChunker.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
//
|
//
|
||||||
// CClient
|
// CClient
|
||||||
//
|
//
|
||||||
|
|
||||||
|
const size_t CClient::m_chunkSize = 1024 * 512; // 512kb
|
||||||
|
|
||||||
CClient::CClient(IEventQueue* events,
|
CClient::CClient(IEventQueue* events,
|
||||||
const CString& name, const CNetworkAddress& address,
|
const CString& name, const CNetworkAddress& address,
|
||||||
ISocketFactory* socketFactory,
|
ISocketFactory* socketFactory,
|
||||||
|
@ -438,6 +444,17 @@ CClient::sendConnectionFailedEvent(const char* msg)
|
||||||
m_events->addEvent(event);
|
m_events->addEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CClient::sendFileChunk(const void* data)
|
||||||
|
{
|
||||||
|
CFileChunker::CFileChunk* fileChunk = reinterpret_cast<CFileChunker::CFileChunk*>(const_cast<void*>(data));
|
||||||
|
LOG((CLOG_DEBUG1 "sendFileChunk"));
|
||||||
|
assert(m_server != NULL);
|
||||||
|
|
||||||
|
// relay
|
||||||
|
m_server->fileChunkSending(fileChunk->m_chunk[0], &(fileChunk->m_chunk[1]), fileChunk->m_dataSize);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CClient::setupConnecting()
|
CClient::setupConnecting()
|
||||||
{
|
{
|
||||||
|
@ -737,6 +754,7 @@ CClient::handleGameDeviceFeedback(const CEvent& event, void*)
|
||||||
void
|
void
|
||||||
CClient::handleFileChunkSending(const CEvent& event, void*)
|
CClient::handleFileChunkSending(const CEvent& event, void*)
|
||||||
{
|
{
|
||||||
|
sendFileChunk(event.getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -763,3 +781,24 @@ CClient::isReceivedFileSizeValid()
|
||||||
{
|
{
|
||||||
return m_expectedFileSize == m_receivedFileData.size();
|
return m_expectedFileSize == m_receivedFileData.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CClient::sendFileToServer(const char* filename)
|
||||||
|
{
|
||||||
|
CThread* thread = new CThread(
|
||||||
|
new TMethodJob<CClient>(
|
||||||
|
this, &CClient::sendFileThread,
|
||||||
|
reinterpret_cast<void*>(const_cast<char*>(filename))));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CClient::sendFileThread(void* filename)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
char* name = reinterpret_cast<char*>(filename);
|
||||||
|
CFileChunker::sendFileChunks(name, m_events, this);
|
||||||
|
}
|
||||||
|
catch (std::runtime_error error) {
|
||||||
|
LOG((CLOG_ERR "failed sending file chunks: %s", error.what()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -100,9 +100,9 @@ public:
|
||||||
|
|
||||||
//! Received a chunk of file data
|
//! Received a chunk of file data
|
||||||
void fileChunkReceived(CString data);
|
void fileChunkReceived(CString data);
|
||||||
|
|
||||||
//! Return true if recieved file size is valid
|
//! Create a new thread and use it to send file to Server
|
||||||
bool isReceivedFileSizeValid();
|
void sendFileToServer(const char* filename);
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
//! @name accessors
|
//! @name accessors
|
||||||
|
@ -128,6 +128,9 @@ public:
|
||||||
*/
|
*/
|
||||||
CNetworkAddress getServerAddress() const;
|
CNetworkAddress getServerAddress() const;
|
||||||
|
|
||||||
|
//! Return true if recieved file size is valid
|
||||||
|
bool isReceivedFileSizeValid();
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
// IScreen overrides
|
// IScreen overrides
|
||||||
|
@ -167,6 +170,8 @@ private:
|
||||||
void sendClipboard(ClipboardID);
|
void sendClipboard(ClipboardID);
|
||||||
void sendEvent(CEvent::Type, void*);
|
void sendEvent(CEvent::Type, void*);
|
||||||
void sendConnectionFailedEvent(const char* msg);
|
void sendConnectionFailedEvent(const char* msg);
|
||||||
|
void sendFileChunk(const void* data);
|
||||||
|
void sendFileThread(void*);
|
||||||
void setupConnecting();
|
void setupConnecting();
|
||||||
void setupConnection();
|
void setupConnection();
|
||||||
void setupScreen();
|
void setupScreen();
|
||||||
|
@ -188,7 +193,7 @@ private:
|
||||||
void handleGameDeviceTimingResp(const CEvent& event, void*);
|
void handleGameDeviceTimingResp(const CEvent& event, void*);
|
||||||
void handleGameDeviceFeedback(const CEvent& event, void*);
|
void handleGameDeviceFeedback(const CEvent& event, void*);
|
||||||
void handleFileChunkSending(const CEvent&, void*);
|
void handleFileChunkSending(const CEvent&, void*);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool m_mock;
|
bool m_mock;
|
||||||
|
|
||||||
|
@ -214,6 +219,7 @@ private:
|
||||||
CCryptoOptions m_crypto;
|
CCryptoOptions m_crypto;
|
||||||
std::size_t m_expectedFileSize;
|
std::size_t m_expectedFileSize;
|
||||||
CString m_receivedFileData;
|
CString m_receivedFileData;
|
||||||
|
static const size_t m_chunkSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -935,7 +935,8 @@ CServerProxy::infoAcknowledgment()
|
||||||
m_ignoreMouse = false;
|
m_ignoreMouse = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CServerProxy::fileChunkReceived()
|
void
|
||||||
|
CServerProxy::fileChunkReceived()
|
||||||
{
|
{
|
||||||
// parse
|
// parse
|
||||||
UInt8 mark;
|
UInt8 mark;
|
||||||
|
@ -943,20 +944,42 @@ void CServerProxy::fileChunkReceived()
|
||||||
CProtocolUtil::readf(m_stream, kMsgDFileTransfer + 4, &mark, &content);
|
CProtocolUtil::readf(m_stream, kMsgDFileTransfer + 4, &mark, &content);
|
||||||
|
|
||||||
switch (mark) {
|
switch (mark) {
|
||||||
case '0':
|
case kFileStart:
|
||||||
LOG((CLOG_DEBUG2 "recv file data: file size = %s", content));
|
LOG((CLOG_DEBUG2 "recv file data from server: size=%s", content.c_str()));
|
||||||
m_client->clearReceivedFileData();
|
m_client->clearReceivedFileData();
|
||||||
m_client->setExpectedFileSize(content);
|
m_client->setExpectedFileSize(content);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '1':
|
case kFileChunk:
|
||||||
LOG((CLOG_DEBUG2 "recv file data: chunck size = %i", content.size()));
|
LOG((CLOG_DEBUG2 "recv file data from server: size=%i", content.size()));
|
||||||
m_client->fileChunkReceived(content);
|
m_client->fileChunkReceived(content);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '2':
|
case kFileEnd:
|
||||||
LOG((CLOG_DEBUG2 "file data transfer finished"));
|
LOG((CLOG_DEBUG2 "file data transfer finished"));
|
||||||
m_events->addEvent(CEvent(m_events->forIScreen().fileRecieveComplete(), m_client));
|
m_events->addEvent(CEvent(m_events->forIScreen().fileRecieveComplete(), m_client));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CServerProxy::fileChunkSending(UInt8 mark, char* data, size_t dataSize)
|
||||||
|
{
|
||||||
|
CString chunk(data, dataSize);
|
||||||
|
|
||||||
|
switch (mark) {
|
||||||
|
case kFileStart:
|
||||||
|
LOG((CLOG_DEBUG2 "file sending start: size=%s", data));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kFileChunk:
|
||||||
|
LOG((CLOG_DEBUG2 "file chunk sending: size=%i", chunk.size()));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kFileEnd:
|
||||||
|
LOG((CLOG_DEBUG2 "file sending finished"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
CProtocolUtil::writef(m_stream, kMsgDFileTransfer, mark, &chunk);
|
||||||
|
}
|
||||||
|
|
|
@ -56,6 +56,14 @@ public:
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
|
//! @file transfer
|
||||||
|
//@{
|
||||||
|
|
||||||
|
//! sending file chunk to server
|
||||||
|
void fileChunkSending(UInt8 mark, char* data, size_t dataSize);
|
||||||
|
|
||||||
|
//@}
|
||||||
|
|
||||||
#ifdef TEST_ENV
|
#ifdef TEST_ENV
|
||||||
void handleDataForTest() { handleData(CEvent(), NULL); }
|
void handleDataForTest() { handleData(CEvent(), NULL); }
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,39 +1,39 @@
|
||||||
/*
|
/*
|
||||||
* synergy -- mouse and keyboard sharing utility
|
* synergy -- mouse and keyboard sharing utility
|
||||||
* Copyright (C) 2012 Bolton Software Ltd.
|
* Copyright (C) 2012 Bolton Software Ltd.
|
||||||
* Copyright (C) 2012 Nick Bolton
|
* Copyright (C) 2012 Nick Bolton
|
||||||
*
|
*
|
||||||
* 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
|
||||||
* found in the file COPYING that should have accompanied this file.
|
* found in the file COPYING that should have accompanied this file.
|
||||||
*
|
*
|
||||||
* This package is distributed in the hope that it will be useful,
|
* This package is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* 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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ILogOutputter.h"
|
#include "ILogOutputter.h"
|
||||||
|
|
||||||
//! Write log to debugger
|
//! Write log to debugger
|
||||||
/*!
|
/*!
|
||||||
This outputter writes output to the debugger. In Visual Studio, this
|
This outputter writes output to the debugger. In Visual Studio, this
|
||||||
can be seen in the Output window.
|
can be seen in the Output window.
|
||||||
*/
|
*/
|
||||||
class CMSWindowsDebugOutputter : public ILogOutputter {
|
class CMSWindowsDebugOutputter : public ILogOutputter {
|
||||||
public:
|
public:
|
||||||
CMSWindowsDebugOutputter();
|
CMSWindowsDebugOutputter();
|
||||||
virtual ~CMSWindowsDebugOutputter();
|
virtual ~CMSWindowsDebugOutputter();
|
||||||
|
|
||||||
// ILogOutputter overrides
|
// ILogOutputter overrides
|
||||||
virtual void open(const char* title);
|
virtual void open(const char* title);
|
||||||
virtual void close();
|
virtual void close();
|
||||||
virtual void show(bool showIfEmpty);
|
virtual void show(bool showIfEmpty);
|
||||||
virtual bool write(ELevel level, const char* message);
|
virtual bool write(ELevel level, const char* message);
|
||||||
virtual void flush();
|
virtual void flush();
|
||||||
};
|
};
|
||||||
|
|
|
@ -203,7 +203,7 @@ CMSWindowsRelauncher::duplicateProcessToken(HANDLE process, LPSECURITY_ATTRIBUTE
|
||||||
LOG((CLOG_ERR "could not open token, process handle: %d (error: %i)", process, GetLastError()));
|
LOG((CLOG_ERR "could not open token, process handle: %d (error: %i)", process, GetLastError()));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG((CLOG_DEBUG "got token %i, duplicating", sourceToken));
|
LOG((CLOG_DEBUG "got token %i, duplicating", sourceToken));
|
||||||
|
|
||||||
HANDLE newToken;
|
HANDLE newToken;
|
||||||
|
@ -216,7 +216,7 @@ CMSWindowsRelauncher::duplicateProcessToken(HANDLE process, LPSECURITY_ATTRIBUTE
|
||||||
sourceToken, GetLastError()));
|
sourceToken, GetLastError()));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG((CLOG_DEBUG "duplicated, new token: %i", newToken));
|
LOG((CLOG_DEBUG "duplicated, new token: %i", newToken));
|
||||||
return newToken;
|
return newToken;
|
||||||
}
|
}
|
||||||
|
@ -265,7 +265,7 @@ CMSWindowsRelauncher::getSessionToken(DWORD sessionId, LPSECURITY_ATTRIBUTES sec
|
||||||
LOG((CLOG_ERR "could not duplicate token (error: %i)", GetLastError()));
|
LOG((CLOG_ERR "could not duplicate token (error: %i)", GetLastError()));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG((CLOG_DEBUG "duplicated, new token: %i", newToken));
|
LOG((CLOG_DEBUG "duplicated, new token: %i", newToken));
|
||||||
return newToken;
|
return newToken;
|
||||||
}
|
}
|
||||||
|
@ -284,10 +284,10 @@ CMSWindowsRelauncher::mainLoop(void*)
|
||||||
|
|
||||||
DWORD sessionId = -1;
|
DWORD sessionId = -1;
|
||||||
bool launched = false;
|
bool launched = false;
|
||||||
|
|
||||||
SECURITY_ATTRIBUTES saAttr;
|
SECURITY_ATTRIBUTES saAttr;
|
||||||
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||||
saAttr.bInheritHandle = TRUE;
|
saAttr.bInheritHandle = TRUE;
|
||||||
saAttr.lpSecurityDescriptor = NULL;
|
saAttr.lpSecurityDescriptor = NULL;
|
||||||
|
|
||||||
if (!CreatePipe(&m_stdOutRead, &m_stdOutWrite, &saAttr, 0)) {
|
if (!CreatePipe(&m_stdOutRead, &m_stdOutWrite, &saAttr, 0)) {
|
||||||
|
@ -308,27 +308,27 @@ CMSWindowsRelauncher::mainLoop(void*)
|
||||||
sendSasEvent = CreateEvent(NULL, FALSE, FALSE, "Global\\SendSAS");
|
sendSasEvent = CreateEvent(NULL, FALSE, FALSE, "Global\\SendSAS");
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD newSessionId = getSessionId();
|
DWORD newSessionId = getSessionId();
|
||||||
|
|
||||||
bool running = false;
|
bool running = false;
|
||||||
if (launched) {
|
if (launched) {
|
||||||
|
|
||||||
DWORD exitCode;
|
DWORD exitCode;
|
||||||
GetExitCodeProcess(pi.hProcess, &exitCode);
|
GetExitCodeProcess(pi.hProcess, &exitCode);
|
||||||
running = (exitCode == STILL_ACTIVE);
|
running = (exitCode == STILL_ACTIVE);
|
||||||
|
|
||||||
if (!running) {
|
if (!running) {
|
||||||
failures++;
|
failures++;
|
||||||
LOG((CLOG_INFO "detected application not running, pid=%d, failures=%d", pi.dwProcessId, failures));
|
LOG((CLOG_INFO "detected application not running, pid=%d, failures=%d", pi.dwProcessId, failures));
|
||||||
|
|
||||||
// increasing backoff period, maximum of 10 seconds.
|
// increasing backoff period, maximum of 10 seconds.
|
||||||
int timeout = (failures * 2) < 10 ? (failures * 2) : 10;
|
int timeout = (failures * 2) < 10 ? (failures * 2) : 10;
|
||||||
LOG((CLOG_DEBUG "waiting, backoff period is %d seconds", timeout));
|
LOG((CLOG_DEBUG "waiting, backoff period is %d seconds", timeout));
|
||||||
ARCH->sleep(timeout);
|
ARCH->sleep(timeout);
|
||||||
|
|
||||||
// double check, in case process started after we waited.
|
// double check, in case process started after we waited.
|
||||||
GetExitCodeProcess(pi.hProcess, &exitCode);
|
GetExitCodeProcess(pi.hProcess, &exitCode);
|
||||||
running = (exitCode == STILL_ACTIVE);
|
running = (exitCode == STILL_ACTIVE);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// reset failures when running.
|
// reset failures when running.
|
||||||
|
@ -383,7 +383,7 @@ CMSWindowsRelauncher::mainLoop(void*)
|
||||||
si.cb = sizeof(STARTUPINFO);
|
si.cb = sizeof(STARTUPINFO);
|
||||||
si.lpDesktop = "winsta0\\Default"; // TODO: maybe this should be \winlogon if we have logonui.exe?
|
si.lpDesktop = "winsta0\\Default"; // TODO: maybe this should be \winlogon if we have logonui.exe?
|
||||||
si.hStdError = m_stdOutWrite;
|
si.hStdError = m_stdOutWrite;
|
||||||
si.hStdOutput = m_stdOutWrite;
|
si.hStdOutput = m_stdOutWrite;
|
||||||
si.dwFlags |= STARTF_USESTDHANDLES;
|
si.dwFlags |= STARTF_USESTDHANDLES;
|
||||||
|
|
||||||
LPVOID environment;
|
LPVOID environment;
|
||||||
|
@ -502,45 +502,45 @@ CMSWindowsRelauncher::outputLoop(void*)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CMSWindowsRelauncher::shutdownProcess(HANDLE handle, DWORD pid, int timeout)
|
CMSWindowsRelauncher::shutdownProcess(HANDLE handle, DWORD pid, int timeout)
|
||||||
{
|
{
|
||||||
DWORD exitCode;
|
DWORD exitCode;
|
||||||
GetExitCodeProcess(handle, &exitCode);
|
GetExitCodeProcess(handle, &exitCode);
|
||||||
if (exitCode != STILL_ACTIVE)
|
if (exitCode != STILL_ACTIVE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CIpcShutdownMessage shutdown;
|
CIpcShutdownMessage shutdown;
|
||||||
m_ipcServer.send(shutdown, kIpcClientNode);
|
m_ipcServer.send(shutdown, kIpcClientNode);
|
||||||
|
|
||||||
// wait for process to exit gracefully.
|
// wait for process to exit gracefully.
|
||||||
double start = ARCH->time();
|
double start = ARCH->time();
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
GetExitCodeProcess(handle, &exitCode);
|
GetExitCodeProcess(handle, &exitCode);
|
||||||
if (exitCode != STILL_ACTIVE) {
|
if (exitCode != STILL_ACTIVE) {
|
||||||
// yay, we got a graceful shutdown. there should be no hook in use errors!
|
// yay, we got a graceful shutdown. there should be no hook in use errors!
|
||||||
LOG((CLOG_INFO "process %d was shutdown gracefully", pid));
|
LOG((CLOG_INFO "process %d was shutdown gracefully", pid));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
double elapsed = (ARCH->time() - start);
|
double elapsed = (ARCH->time() - start);
|
||||||
if (elapsed > timeout) {
|
if (elapsed > timeout) {
|
||||||
// if timeout reached, kill forcefully.
|
// if timeout reached, kill forcefully.
|
||||||
// calling TerminateProcess on synergy is very bad!
|
// calling TerminateProcess on synergy is very bad!
|
||||||
// it causes the hook DLL to stay loaded in some apps,
|
// it causes the hook DLL to stay loaded in some apps,
|
||||||
// making it impossible to start synergy again.
|
// making it impossible to start synergy again.
|
||||||
LOG((CLOG_WARN "shutdown timed out after %d secs, forcefully terminating", (int)elapsed));
|
LOG((CLOG_WARN "shutdown timed out after %d secs, forcefully terminating", (int)elapsed));
|
||||||
TerminateProcess(handle, kExitSuccess);
|
TerminateProcess(handle, kExitSuccess);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ARCH->sleep(1);
|
ARCH->sleep(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -597,4 +597,4 @@ CMSWindowsRelauncher::shutdownExistingProcesses()
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseHandle(snapshot);
|
CloseHandle(snapshot);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1477,16 +1477,16 @@ CXWindowsUtil::mapKeySymToKeyID(KeySym k)
|
||||||
case XK_ISO_Left_Tab:
|
case XK_ISO_Left_Tab:
|
||||||
return kKeyLeftTab;
|
return kKeyLeftTab;
|
||||||
|
|
||||||
case XK_ISO_Level3_Shift:
|
case XK_ISO_Level3_Shift:
|
||||||
return kKeyAltGr;
|
return kKeyAltGr;
|
||||||
|
|
||||||
#ifdef XK_ISO_Level5_Shift
|
#ifdef XK_ISO_Level5_Shift
|
||||||
case XK_ISO_Level5_Shift:
|
case XK_ISO_Level5_Shift:
|
||||||
return XK_ISO_Level5_Shift; //FIXME: there is no "usual" key for this...
|
return XK_ISO_Level5_Shift; //FIXME: there is no "usual" key for this...
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case XK_ISO_Next_Group:
|
case XK_ISO_Next_Group:
|
||||||
return kKeyNextGroup;
|
return kKeyNextGroup;
|
||||||
|
|
||||||
case XK_ISO_Prev_Group:
|
case XK_ISO_Prev_Group:
|
||||||
return kKeyPrevGroup;
|
return kKeyPrevGroup;
|
||||||
|
@ -1582,16 +1582,16 @@ CXWindowsUtil::getModifierBitForKeySym(KeySym keysym)
|
||||||
return kKeyModifierBitSuper;
|
return kKeyModifierBitSuper;
|
||||||
|
|
||||||
case XK_Mode_switch:
|
case XK_Mode_switch:
|
||||||
case XK_ISO_Level3_Shift:
|
case XK_ISO_Level3_Shift:
|
||||||
return kKeyModifierBitAltGr;
|
return kKeyModifierBitAltGr;
|
||||||
|
|
||||||
#ifdef XK_ISO_Level5_Shift
|
#ifdef XK_ISO_Level5_Shift
|
||||||
case XK_ISO_Level5_Shift:
|
case XK_ISO_Level5_Shift:
|
||||||
return kKeyModifierBitLevel5Lock;
|
return kKeyModifierBitLevel5Lock;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case XK_Caps_Lock:
|
case XK_Caps_Lock:
|
||||||
return kKeyModifierBitCapsLock;
|
return kKeyModifierBitCapsLock;
|
||||||
|
|
||||||
case XK_Num_Lock:
|
case XK_Num_Lock:
|
||||||
return kKeyModifierBitNumLock;
|
return kKeyModifierBitNumLock;
|
||||||
|
|
|
@ -14,329 +14,329 @@
|
||||||
*
|
*
|
||||||
* 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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------------------------------------
|
/*--------------------------------------------------------------------------------------------------------
|
||||||
Original comment:
|
Original comment:
|
||||||
|
|
||||||
APIHIJACK.CPP - Based on DelayLoadProfileDLL.CPP, by Matt Pietrek for MSJ February 2000.
|
APIHIJACK.CPP - Based on DelayLoadProfileDLL.CPP, by Matt Pietrek for MSJ February 2000.
|
||||||
http://msdn.microsoft.com/library/periodic/period00/hood0200.htm
|
http://msdn.microsoft.com/library/periodic/period00/hood0200.htm
|
||||||
Adapted by Wade Brainerd, wadeb@wadeb.com
|
Adapted by Wade Brainerd, wadeb@wadeb.com
|
||||||
--------------------------------------------------------------------------------------------------------*/
|
--------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "HookDLL.h"
|
#include "HookDLL.h"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
std::stringstream _hookDllLogStream;
|
std::stringstream _hookDllLogStream;
|
||||||
#define LOG(s) \
|
#define LOG(s) \
|
||||||
_hookDllLogStream.str(""); \
|
_hookDllLogStream.str(""); \
|
||||||
_hookDllLogStream << "Synergy HookDLL: " << s << std::endl; \
|
_hookDllLogStream << "Synergy HookDLL: " << s << std::endl; \
|
||||||
OutputDebugString( _hookDllLogStream.str().c_str() );
|
OutputDebugString( _hookDllLogStream.str().c_str() );
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
// Called from the DLPD_IAT_STUB stubs. Increments "count" field of the stub
|
// Called from the DLPD_IAT_STUB stubs. Increments "count" field of the stub
|
||||||
|
|
||||||
void __cdecl DefaultHook( PVOID dummy )
|
void __cdecl DefaultHook( PVOID dummy )
|
||||||
{
|
{
|
||||||
// asm only supported on 32-bit
|
// asm only supported on 32-bit
|
||||||
#ifdef _M_IX86
|
#ifdef _M_IX86
|
||||||
__asm pushad // Save all general purpose registers
|
__asm pushad // Save all general purpose registers
|
||||||
|
|
||||||
// Get return address, then subtract 5 (size of a CALL X instruction)
|
// Get return address, then subtract 5 (size of a CALL X instruction)
|
||||||
// The result points at a DLPD_IAT_STUB
|
// The result points at a DLPD_IAT_STUB
|
||||||
|
|
||||||
// pointer math! &dummy-1 really subtracts sizeof(PVOID)
|
// pointer math! &dummy-1 really subtracts sizeof(PVOID)
|
||||||
PDWORD pRetAddr = (PDWORD)(&dummy - 1);
|
PDWORD pRetAddr = (PDWORD)(&dummy - 1);
|
||||||
|
|
||||||
DLPD_IAT_STUB * pDLPDStub = (DLPD_IAT_STUB *)(*pRetAddr - 5);
|
DLPD_IAT_STUB * pDLPDStub = (DLPD_IAT_STUB *)(*pRetAddr - 5);
|
||||||
|
|
||||||
pDLPDStub->count++;
|
pDLPDStub->count++;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// Remove the above conditional to get a cheezy API trace from
|
// Remove the above conditional to get a cheezy API trace from
|
||||||
// the loader process. It's slow!
|
// the loader process. It's slow!
|
||||||
if ( !IMAGE_SNAP_BY_ORDINAL( pDLPDStub->pszNameOrOrdinal) )
|
if ( !IMAGE_SNAP_BY_ORDINAL( pDLPDStub->pszNameOrOrdinal) )
|
||||||
{
|
{
|
||||||
LOG( "Called hooked function: " );
|
LOG( "Called hooked function: " );
|
||||||
LOG( (PSTR)pDLPDStub->pszNameOrOrdinal );
|
LOG( (PSTR)pDLPDStub->pszNameOrOrdinal );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__asm popad // Restore all general purpose registers
|
__asm popad // Restore all general purpose registers
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function must be __cdecl!!!
|
// This function must be __cdecl!!!
|
||||||
void __cdecl DelayLoadProfileDLL_UpdateCount( PVOID dummy );
|
void __cdecl DelayLoadProfileDLL_UpdateCount( PVOID dummy );
|
||||||
|
|
||||||
PIMAGE_IMPORT_DESCRIPTOR g_pFirstImportDesc;
|
PIMAGE_IMPORT_DESCRIPTOR g_pFirstImportDesc;
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
// Given an HMODULE, returns a pointer to the PE header
|
// Given an HMODULE, returns a pointer to the PE header
|
||||||
|
|
||||||
PIMAGE_NT_HEADERS PEHeaderFromHModule(HMODULE hModule)
|
PIMAGE_NT_HEADERS PEHeaderFromHModule(HMODULE hModule)
|
||||||
{
|
{
|
||||||
PIMAGE_NT_HEADERS pNTHeader = 0;
|
PIMAGE_NT_HEADERS pNTHeader = 0;
|
||||||
|
|
||||||
__try
|
__try
|
||||||
{
|
{
|
||||||
if ( PIMAGE_DOS_HEADER(hModule)->e_magic != IMAGE_DOS_SIGNATURE )
|
if ( PIMAGE_DOS_HEADER(hModule)->e_magic != IMAGE_DOS_SIGNATURE )
|
||||||
__leave;
|
__leave;
|
||||||
|
|
||||||
pNTHeader = PIMAGE_NT_HEADERS(PBYTE(hModule)
|
pNTHeader = PIMAGE_NT_HEADERS(PBYTE(hModule)
|
||||||
+ PIMAGE_DOS_HEADER(hModule)->e_lfanew);
|
+ PIMAGE_DOS_HEADER(hModule)->e_lfanew);
|
||||||
|
|
||||||
if ( pNTHeader->Signature != IMAGE_NT_SIGNATURE )
|
if ( pNTHeader->Signature != IMAGE_NT_SIGNATURE )
|
||||||
pNTHeader = 0;
|
pNTHeader = 0;
|
||||||
}
|
}
|
||||||
__except( EXCEPTION_EXECUTE_HANDLER )
|
__except( EXCEPTION_EXECUTE_HANDLER )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
return pNTHeader;
|
return pNTHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
// Builds stubs for and redirects the IAT for one DLL (pImportDesc)
|
// Builds stubs for and redirects the IAT for one DLL (pImportDesc)
|
||||||
|
|
||||||
bool RedirectIAT( SDLLHook* DLLHook, PIMAGE_IMPORT_DESCRIPTOR pImportDesc, PVOID pBaseLoadAddr )
|
bool RedirectIAT( SDLLHook* DLLHook, PIMAGE_IMPORT_DESCRIPTOR pImportDesc, PVOID pBaseLoadAddr )
|
||||||
{
|
{
|
||||||
PIMAGE_THUNK_DATA pIAT; // Ptr to import address table
|
PIMAGE_THUNK_DATA pIAT; // Ptr to import address table
|
||||||
PIMAGE_THUNK_DATA pINT; // Ptr to import names table
|
PIMAGE_THUNK_DATA pINT; // Ptr to import names table
|
||||||
PIMAGE_THUNK_DATA pIteratingIAT;
|
PIMAGE_THUNK_DATA pIteratingIAT;
|
||||||
|
|
||||||
// Figure out which OS platform we're on
|
// Figure out which OS platform we're on
|
||||||
OSVERSIONINFO osvi;
|
OSVERSIONINFO osvi;
|
||||||
osvi.dwOSVersionInfoSize = sizeof(osvi);
|
osvi.dwOSVersionInfoSize = sizeof(osvi);
|
||||||
GetVersionEx( &osvi );
|
GetVersionEx( &osvi );
|
||||||
|
|
||||||
// If no import names table, we can't redirect this, so bail
|
// If no import names table, we can't redirect this, so bail
|
||||||
if ( pImportDesc->OriginalFirstThunk == 0 )
|
if ( pImportDesc->OriginalFirstThunk == 0 )
|
||||||
{
|
{
|
||||||
LOG( "no IAT available." );
|
LOG( "no IAT available." );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pIAT = MakePtr( PIMAGE_THUNK_DATA, pBaseLoadAddr, pImportDesc->FirstThunk );
|
pIAT = MakePtr( PIMAGE_THUNK_DATA, pBaseLoadAddr, pImportDesc->FirstThunk );
|
||||||
pINT = MakePtr( PIMAGE_THUNK_DATA, pBaseLoadAddr, pImportDesc->OriginalFirstThunk );
|
pINT = MakePtr( PIMAGE_THUNK_DATA, pBaseLoadAddr, pImportDesc->OriginalFirstThunk );
|
||||||
|
|
||||||
// Count how many entries there are in this IAT. Array is 0 terminated
|
// Count how many entries there are in this IAT. Array is 0 terminated
|
||||||
pIteratingIAT = pIAT;
|
pIteratingIAT = pIAT;
|
||||||
unsigned cFuncs = 0;
|
unsigned cFuncs = 0;
|
||||||
while ( pIteratingIAT->u1.Function )
|
while ( pIteratingIAT->u1.Function )
|
||||||
{
|
{
|
||||||
cFuncs++;
|
cFuncs++;
|
||||||
pIteratingIAT++;
|
pIteratingIAT++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( cFuncs == 0 ) // If no imported functions, we're done!
|
if ( cFuncs == 0 ) // If no imported functions, we're done!
|
||||||
{
|
{
|
||||||
LOG( "no imported functions" );
|
LOG( "no imported functions" );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// These next few lines ensure that we'll be able to modify the IAT,
|
// These next few lines ensure that we'll be able to modify the IAT,
|
||||||
// which is often in a read-only section in the EXE.
|
// which is often in a read-only section in the EXE.
|
||||||
DWORD flOldProtect, flNewProtect, flDontCare;
|
DWORD flOldProtect, flNewProtect, flDontCare;
|
||||||
MEMORY_BASIC_INFORMATION mbi;
|
MEMORY_BASIC_INFORMATION mbi;
|
||||||
|
|
||||||
// Get the current protection attributes
|
// Get the current protection attributes
|
||||||
VirtualQuery( pIAT, &mbi, sizeof(mbi) );
|
VirtualQuery( pIAT, &mbi, sizeof(mbi) );
|
||||||
|
|
||||||
// remove ReadOnly and ExecuteRead attributes, add on ReadWrite flag
|
// remove ReadOnly and ExecuteRead attributes, add on ReadWrite flag
|
||||||
flNewProtect = mbi.Protect;
|
flNewProtect = mbi.Protect;
|
||||||
flNewProtect &= ~(PAGE_READONLY | PAGE_EXECUTE_READ);
|
flNewProtect &= ~(PAGE_READONLY | PAGE_EXECUTE_READ);
|
||||||
flNewProtect |= (PAGE_READWRITE);
|
flNewProtect |= (PAGE_READWRITE);
|
||||||
|
|
||||||
if ( !VirtualProtect( pIAT, sizeof(PVOID) * cFuncs,
|
if ( !VirtualProtect( pIAT, sizeof(PVOID) * cFuncs,
|
||||||
flNewProtect, &flOldProtect) )
|
flNewProtect, &flOldProtect) )
|
||||||
{
|
{
|
||||||
LOG( "could not remove ReadOnly and ExecuteRead attributes, or add ReadWrite flag" );
|
LOG( "could not remove ReadOnly and ExecuteRead attributes, or add ReadWrite flag" );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the Default hook is enabled, build an array of redirection stubs in the processes memory.
|
// If the Default hook is enabled, build an array of redirection stubs in the processes memory.
|
||||||
DLPD_IAT_STUB * pStubs = 0;
|
DLPD_IAT_STUB * pStubs = 0;
|
||||||
if ( DLLHook->UseDefault )
|
if ( DLLHook->UseDefault )
|
||||||
{
|
{
|
||||||
// Allocate memory for the redirection stubs. Make one extra stub at the
|
// Allocate memory for the redirection stubs. Make one extra stub at the
|
||||||
// end to be a sentinel
|
// end to be a sentinel
|
||||||
pStubs = new DLPD_IAT_STUB[ cFuncs + 1];
|
pStubs = new DLPD_IAT_STUB[ cFuncs + 1];
|
||||||
if ( !pStubs )
|
if ( !pStubs )
|
||||||
{
|
{
|
||||||
LOG( "could not allocate memory for redirection stubs" );
|
LOG( "could not allocate memory for redirection stubs" );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan through the IAT, completing the stubs and redirecting the IAT
|
// Scan through the IAT, completing the stubs and redirecting the IAT
|
||||||
// entries to point to the stubs
|
// entries to point to the stubs
|
||||||
pIteratingIAT = pIAT;
|
pIteratingIAT = pIAT;
|
||||||
|
|
||||||
while ( pIteratingIAT->u1.Function )
|
while ( pIteratingIAT->u1.Function )
|
||||||
{
|
{
|
||||||
void* HookFn = 0; // Set to either the SFunctionHook or pStubs.
|
void* HookFn = 0; // Set to either the SFunctionHook or pStubs.
|
||||||
|
|
||||||
if ( !IMAGE_SNAP_BY_ORDINAL( pINT->u1.Ordinal ) ) // import by name
|
if ( !IMAGE_SNAP_BY_ORDINAL( pINT->u1.Ordinal ) ) // import by name
|
||||||
{
|
{
|
||||||
PIMAGE_IMPORT_BY_NAME pImportName = MakePtr( PIMAGE_IMPORT_BY_NAME, pBaseLoadAddr, pINT->u1.AddressOfData );
|
PIMAGE_IMPORT_BY_NAME pImportName = MakePtr( PIMAGE_IMPORT_BY_NAME, pBaseLoadAddr, pINT->u1.AddressOfData );
|
||||||
|
|
||||||
LOG( "checking function with name: " << pImportName->Name );
|
LOG( "checking function with name: " << pImportName->Name );
|
||||||
|
|
||||||
// Iterate through the hook functions, searching for this import.
|
// Iterate through the hook functions, searching for this import.
|
||||||
SFunctionHook* FHook = DLLHook->Functions;
|
SFunctionHook* FHook = DLLHook->Functions;
|
||||||
while ( FHook->Name )
|
while ( FHook->Name )
|
||||||
{
|
{
|
||||||
if ( lstrcmpi( FHook->Name, (char*)pImportName->Name ) == 0 )
|
if ( lstrcmpi( FHook->Name, (char*)pImportName->Name ) == 0 )
|
||||||
{
|
{
|
||||||
// Save the old function in the SFunctionHook structure and get the new one.
|
// Save the old function in the SFunctionHook structure and get the new one.
|
||||||
FHook->OrigFn = (void*)pIteratingIAT->u1.Function;
|
FHook->OrigFn = (void*)pIteratingIAT->u1.Function;
|
||||||
HookFn = FHook->HookFn;
|
HookFn = FHook->HookFn;
|
||||||
|
|
||||||
LOG( "hooked function: " << pImportName->Name );
|
LOG( "hooked function: " << pImportName->Name );
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
FHook++;
|
FHook++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the default function is enabled, store the name for the user.
|
// If the default function is enabled, store the name for the user.
|
||||||
if ( DLLHook->UseDefault )
|
if ( DLLHook->UseDefault )
|
||||||
pStubs->pszNameOrOrdinal = (DWORD)&pImportName->Name;
|
pStubs->pszNameOrOrdinal = (DWORD)&pImportName->Name;
|
||||||
}
|
}
|
||||||
else // added comparison for ordinal
|
else // added comparison for ordinal
|
||||||
{
|
{
|
||||||
LOG( "checking function at ordinal: " << pINT->u1.Ordinal );
|
LOG( "checking function at ordinal: " << pINT->u1.Ordinal );
|
||||||
|
|
||||||
SFunctionHook* FHook = DLLHook->Functions;
|
SFunctionHook* FHook = DLLHook->Functions;
|
||||||
while ( FHook->Name )
|
while ( FHook->Name )
|
||||||
{
|
{
|
||||||
if ( (DWORD)FHook->Name == pINT->u1.Ordinal )
|
if ( (DWORD)FHook->Name == pINT->u1.Ordinal )
|
||||||
{
|
{
|
||||||
// Save the old function in the SFunctionHook structure and get the new one.
|
// Save the old function in the SFunctionHook structure and get the new one.
|
||||||
FHook->OrigFn = (void*)pIteratingIAT->u1.Function;
|
FHook->OrigFn = (void*)pIteratingIAT->u1.Function;
|
||||||
HookFn = FHook->HookFn;
|
HookFn = FHook->HookFn;
|
||||||
|
|
||||||
LOG( "hooked ordinal: " << pINT->u1.Ordinal );
|
LOG( "hooked ordinal: " << pINT->u1.Ordinal );
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
FHook++;
|
FHook++;
|
||||||
}
|
}
|
||||||
// If the default function is enabled, store the ordinal for the user.
|
// If the default function is enabled, store the ordinal for the user.
|
||||||
if ( DLLHook->UseDefault )
|
if ( DLLHook->UseDefault )
|
||||||
pStubs->pszNameOrOrdinal = (DWORD)pINT->u1.Ordinal;
|
pStubs->pszNameOrOrdinal = (DWORD)pINT->u1.Ordinal;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the default function is enabled, fill in the fields to the stub code.
|
// If the default function is enabled, fill in the fields to the stub code.
|
||||||
if ( DLLHook->UseDefault )
|
if ( DLLHook->UseDefault )
|
||||||
{
|
{
|
||||||
pStubs->data_call = (DWORD)(PDWORD)DLLHook->DefaultFn
|
pStubs->data_call = (DWORD)(PDWORD)DLLHook->DefaultFn
|
||||||
- (DWORD)(PDWORD)&pStubs->instr_JMP;
|
- (DWORD)(PDWORD)&pStubs->instr_JMP;
|
||||||
pStubs->data_JMP = *(PDWORD)pIteratingIAT - (DWORD)(PDWORD)&pStubs->count;
|
pStubs->data_JMP = *(PDWORD)pIteratingIAT - (DWORD)(PDWORD)&pStubs->count;
|
||||||
|
|
||||||
// If it wasn't manually hooked, use the Stub function.
|
// If it wasn't manually hooked, use the Stub function.
|
||||||
if ( !HookFn )
|
if ( !HookFn )
|
||||||
HookFn = (void*)pStubs;
|
HookFn = (void*)pStubs;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace the IAT function pointer if we have a hook.
|
// Replace the IAT function pointer if we have a hook.
|
||||||
if ( HookFn )
|
if ( HookFn )
|
||||||
{
|
{
|
||||||
// Cheez-o hack to see if what we're importing is code or data.
|
// Cheez-o hack to see if what we're importing is code or data.
|
||||||
// If it's code, we shouldn't be able to write to it
|
// If it's code, we shouldn't be able to write to it
|
||||||
if ( IsBadWritePtr( (PVOID)pIteratingIAT->u1.Function, 1 ) )
|
if ( IsBadWritePtr( (PVOID)pIteratingIAT->u1.Function, 1 ) )
|
||||||
{
|
{
|
||||||
pIteratingIAT->u1.Function = (DWORD)(PDWORD)HookFn;
|
pIteratingIAT->u1.Function = (DWORD)(PDWORD)HookFn;
|
||||||
}
|
}
|
||||||
else if ( osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
|
else if ( osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
|
||||||
{
|
{
|
||||||
// Special hack for Win9X, which builds stubs for imported
|
// Special hack for Win9X, which builds stubs for imported
|
||||||
// functions in system DLLs (Loaded above 2GB). These stubs are
|
// functions in system DLLs (Loaded above 2GB). These stubs are
|
||||||
// writeable, so we have to explicitly check for this case
|
// writeable, so we have to explicitly check for this case
|
||||||
if ( pIteratingIAT->u1.Function > (DWORD)(PDWORD)0x80000000 )
|
if ( pIteratingIAT->u1.Function > (DWORD)(PDWORD)0x80000000 )
|
||||||
pIteratingIAT->u1.Function = (DWORD)(PDWORD)HookFn;
|
pIteratingIAT->u1.Function = (DWORD)(PDWORD)HookFn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( DLLHook->UseDefault )
|
if ( DLLHook->UseDefault )
|
||||||
pStubs++; // Advance to next stub
|
pStubs++; // Advance to next stub
|
||||||
|
|
||||||
pIteratingIAT++; // Advance to next IAT entry
|
pIteratingIAT++; // Advance to next IAT entry
|
||||||
pINT++; // Advance to next INT entry
|
pINT++; // Advance to next INT entry
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( DLLHook->UseDefault )
|
if ( DLLHook->UseDefault )
|
||||||
pStubs->pszNameOrOrdinal = 0; // Final stub is a sentinel
|
pStubs->pszNameOrOrdinal = 0; // Final stub is a sentinel
|
||||||
|
|
||||||
// Put the page attributes back the way they were.
|
// Put the page attributes back the way they were.
|
||||||
VirtualProtect( pIAT, sizeof(PVOID) * cFuncs, flOldProtect, &flDontCare);
|
VirtualProtect( pIAT, sizeof(PVOID) * cFuncs, flOldProtect, &flDontCare);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
// Top level routine to find the EXE's imports, and redirect them
|
// Top level routine to find the EXE's imports, and redirect them
|
||||||
bool HookAPICalls( SDLLHook* hook )
|
bool HookAPICalls( SDLLHook* hook )
|
||||||
{
|
{
|
||||||
if ( !hook )
|
if ( !hook )
|
||||||
{
|
{
|
||||||
LOG("no hook");
|
LOG("no hook");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
HMODULE hModEXE = GetModuleHandle( 0 );
|
HMODULE hModEXE = GetModuleHandle( 0 );
|
||||||
|
|
||||||
PIMAGE_NT_HEADERS pExeNTHdr = PEHeaderFromHModule( hModEXE );
|
PIMAGE_NT_HEADERS pExeNTHdr = PEHeaderFromHModule( hModEXE );
|
||||||
|
|
||||||
if ( !pExeNTHdr )
|
if ( !pExeNTHdr )
|
||||||
{
|
{
|
||||||
LOG("no PE header");
|
LOG("no PE header");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD importRVA = pExeNTHdr->OptionalHeader.DataDirectory
|
DWORD importRVA = pExeNTHdr->OptionalHeader.DataDirectory
|
||||||
[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
|
[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
|
||||||
if ( !importRVA )
|
if ( !importRVA )
|
||||||
{
|
{
|
||||||
LOG("no virtual address for image directory entry import");
|
LOG("no virtual address for image directory entry import");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert imports RVA to a usable pointer
|
// Convert imports RVA to a usable pointer
|
||||||
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = MakePtr( PIMAGE_IMPORT_DESCRIPTOR,
|
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = MakePtr( PIMAGE_IMPORT_DESCRIPTOR,
|
||||||
hModEXE, importRVA );
|
hModEXE, importRVA );
|
||||||
|
|
||||||
// Save off imports address in a global for later use
|
// Save off imports address in a global for later use
|
||||||
g_pFirstImportDesc = pImportDesc;
|
g_pFirstImportDesc = pImportDesc;
|
||||||
|
|
||||||
// Iterate through each import descriptor, and redirect if appropriate
|
// Iterate through each import descriptor, and redirect if appropriate
|
||||||
while ( pImportDesc->FirstThunk )
|
while ( pImportDesc->FirstThunk )
|
||||||
{
|
{
|
||||||
PSTR pszImportModuleName = MakePtr( PSTR, hModEXE, pImportDesc->Name);
|
PSTR pszImportModuleName = MakePtr( PSTR, hModEXE, pImportDesc->Name);
|
||||||
|
|
||||||
if ( lstrcmpi( pszImportModuleName, hook->Name ) == 0 )
|
if ( lstrcmpi( pszImportModuleName, hook->Name ) == 0 )
|
||||||
{
|
{
|
||||||
LOG( "found " << hook->Name << " in process" );
|
LOG( "found " << hook->Name << " in process" );
|
||||||
|
|
||||||
if ( RedirectIAT( hook, pImportDesc, (PVOID)hModEXE ) )
|
if ( RedirectIAT( hook, pImportDesc, (PVOID)hModEXE ) )
|
||||||
{
|
{
|
||||||
LOG( "redirected IAT ok" );
|
LOG( "redirected IAT ok" );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG( "failed to redirect IAT" );
|
LOG( "failed to redirect IAT" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pImportDesc++; // Advance to next import descriptor
|
pImportDesc++; // Advance to next import descriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,68 +14,68 @@
|
||||||
*
|
*
|
||||||
* 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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------------------------------------
|
/*--------------------------------------------------------------------------------------------------------
|
||||||
Original comment:
|
Original comment:
|
||||||
|
|
||||||
APIHIJACK.H - Based on DelayLoadProfileDLL.CPP, by Matt Pietrek for MSJ February 2000.
|
APIHIJACK.H - Based on DelayLoadProfileDLL.CPP, by Matt Pietrek for MSJ February 2000.
|
||||||
http://msdn.microsoft.com/library/periodic/period00/hood0200.htm
|
http://msdn.microsoft.com/library/periodic/period00/hood0200.htm
|
||||||
Adapted by Wade Brainerd, wadeb@wadeb.com
|
Adapted by Wade Brainerd, wadeb@wadeb.com
|
||||||
--------------------------------------------------------------------------------------------------------*/
|
--------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#pragma warning(disable:4200)
|
#pragma warning(disable:4200)
|
||||||
|
|
||||||
// Macro for convenient pointer addition.
|
// Macro for convenient pointer addition.
|
||||||
// Essentially treats the last two parameters as DWORDs. The first
|
// Essentially treats the last two parameters as DWORDs. The first
|
||||||
// parameter is used to typecast the result to the appropriate pointer type.
|
// parameter is used to typecast the result to the appropriate pointer type.
|
||||||
#define MakePtr(cast, ptr, addValue ) (cast)( (DWORD)(ptr)+(DWORD)(addValue))
|
#define MakePtr(cast, ptr, addValue ) (cast)( (DWORD)(ptr)+(DWORD)(addValue))
|
||||||
|
|
||||||
// Default Hook Stub Structure: Contains data about the original function, Name/Ordinal, Address
|
// Default Hook Stub Structure: Contains data about the original function, Name/Ordinal, Address
|
||||||
// and a Count field. This is actually a block of assembly code.
|
// and a Count field. This is actually a block of assembly code.
|
||||||
#pragma pack( push, 1 )
|
#pragma pack( push, 1 )
|
||||||
struct DLPD_IAT_STUB
|
struct DLPD_IAT_STUB
|
||||||
{
|
{
|
||||||
BYTE instr_CALL;
|
BYTE instr_CALL;
|
||||||
DWORD data_call;
|
DWORD data_call;
|
||||||
BYTE instr_JMP;
|
BYTE instr_JMP;
|
||||||
DWORD data_JMP;
|
DWORD data_JMP;
|
||||||
DWORD count;
|
DWORD count;
|
||||||
DWORD pszNameOrOrdinal;
|
DWORD pszNameOrOrdinal;
|
||||||
|
|
||||||
DLPD_IAT_STUB() : instr_CALL( 0xE8 ), instr_JMP( 0xE9 ), count( 0 ) {}
|
DLPD_IAT_STUB() : instr_CALL( 0xE8 ), instr_JMP( 0xE9 ), count( 0 ) {}
|
||||||
};
|
};
|
||||||
#pragma pack( pop )
|
#pragma pack( pop )
|
||||||
|
|
||||||
// Example DefaultHook procedure, called from the DLPD_IAT_STUB stubs.
|
// Example DefaultHook procedure, called from the DLPD_IAT_STUB stubs.
|
||||||
// Increments "count" field of the stub.
|
// Increments "count" field of the stub.
|
||||||
// See the implementation for more information.
|
// See the implementation for more information.
|
||||||
void __cdecl DefaultHook( PVOID dummy );
|
void __cdecl DefaultHook( PVOID dummy );
|
||||||
|
|
||||||
struct SFunctionHook
|
struct SFunctionHook
|
||||||
{
|
{
|
||||||
char* Name; // Function name, e.g. "DirectDrawCreateEx".
|
char* Name; // Function name, e.g. "DirectDrawCreateEx".
|
||||||
void* HookFn; // Address of your function.
|
void* HookFn; // Address of your function.
|
||||||
void* OrigFn; // Stored by HookAPICalls, the address of the original function.
|
void* OrigFn; // Stored by HookAPICalls, the address of the original function.
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SDLLHook
|
struct SDLLHook
|
||||||
{
|
{
|
||||||
// Name of the DLL, e.g. "DDRAW.DLL"
|
// Name of the DLL, e.g. "DDRAW.DLL"
|
||||||
char* Name;
|
char* Name;
|
||||||
|
|
||||||
// Set true to call the default for all non-hooked functions before they are executed.
|
// Set true to call the default for all non-hooked functions before they are executed.
|
||||||
bool UseDefault;
|
bool UseDefault;
|
||||||
void* DefaultFn;
|
void* DefaultFn;
|
||||||
|
|
||||||
// Function hook array. Terminated with a NULL Name field.
|
// Function hook array. Terminated with a NULL Name field.
|
||||||
SFunctionHook Functions[];
|
SFunctionHook Functions[];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Hook functions one or more DLLs.
|
// Hook functions one or more DLLs.
|
||||||
bool HookAPICalls( SDLLHook* hook );
|
bool HookAPICalls( SDLLHook* hook );
|
||||||
|
|
|
@ -1,229 +1,229 @@
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* *
|
* *
|
||||||
* XInput.h -- This module defines XBOX controller APIs *
|
* XInput.h -- This module defines XBOX controller APIs *
|
||||||
* and constansts for the Windows platform. *
|
* and constansts for the Windows platform. *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 2012 Bolton Software Ltd.
|
* Copyright (C) 2012 Bolton Software Ltd.
|
||||||
* Copyright (c) Microsoft Corp. All rights reserved. *
|
* Copyright (c) Microsoft Corp. All rights reserved. *
|
||||||
* *
|
* *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
#ifndef _XINPUT_H_
|
#ifndef _XINPUT_H_
|
||||||
#define _XINPUT_H_
|
#define _XINPUT_H_
|
||||||
|
|
||||||
#include <windef.h>
|
#include <windef.h>
|
||||||
|
|
||||||
// Current name of the DLL shipped in the same SDK as this header.
|
// Current name of the DLL shipped in the same SDK as this header.
|
||||||
// The name reflects the current version
|
// The name reflects the current version
|
||||||
#ifndef XINPUT_USE_9_1_0
|
#ifndef XINPUT_USE_9_1_0
|
||||||
#define XINPUT_DLL_A "xinput1_3.dll"
|
#define XINPUT_DLL_A "xinput1_3.dll"
|
||||||
#define XINPUT_DLL_W L"xinput1_3.dll"
|
#define XINPUT_DLL_W L"xinput1_3.dll"
|
||||||
#else
|
#else
|
||||||
#define XINPUT_DLL_A "xinput9_1_0.dll"
|
#define XINPUT_DLL_A "xinput9_1_0.dll"
|
||||||
#define XINPUT_DLL_W L"xinput9_1_0.dll"
|
#define XINPUT_DLL_W L"xinput9_1_0.dll"
|
||||||
#endif
|
#endif
|
||||||
#ifdef UNICODE
|
#ifdef UNICODE
|
||||||
#define XINPUT_DLL XINPUT_DLL_W
|
#define XINPUT_DLL XINPUT_DLL_W
|
||||||
#else
|
#else
|
||||||
#define XINPUT_DLL XINPUT_DLL_A
|
#define XINPUT_DLL XINPUT_DLL_A
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
// Device types available in XINPUT_CAPABILITIES
|
// Device types available in XINPUT_CAPABILITIES
|
||||||
//
|
//
|
||||||
#define XINPUT_DEVTYPE_GAMEPAD 0x01
|
#define XINPUT_DEVTYPE_GAMEPAD 0x01
|
||||||
|
|
||||||
//
|
//
|
||||||
// Device subtypes available in XINPUT_CAPABILITIES
|
// Device subtypes available in XINPUT_CAPABILITIES
|
||||||
//
|
//
|
||||||
#define XINPUT_DEVSUBTYPE_GAMEPAD 0x01
|
#define XINPUT_DEVSUBTYPE_GAMEPAD 0x01
|
||||||
|
|
||||||
#ifndef XINPUT_USE_9_1_0
|
#ifndef XINPUT_USE_9_1_0
|
||||||
|
|
||||||
#define XINPUT_DEVSUBTYPE_WHEEL 0x02
|
#define XINPUT_DEVSUBTYPE_WHEEL 0x02
|
||||||
#define XINPUT_DEVSUBTYPE_ARCADE_STICK 0x03
|
#define XINPUT_DEVSUBTYPE_ARCADE_STICK 0x03
|
||||||
#define XINPUT_DEVSUBTYPE_FLIGHT_SICK 0x04
|
#define XINPUT_DEVSUBTYPE_FLIGHT_SICK 0x04
|
||||||
#define XINPUT_DEVSUBTYPE_DANCE_PAD 0x05
|
#define XINPUT_DEVSUBTYPE_DANCE_PAD 0x05
|
||||||
#define XINPUT_DEVSUBTYPE_GUITAR 0x06
|
#define XINPUT_DEVSUBTYPE_GUITAR 0x06
|
||||||
#define XINPUT_DEVSUBTYPE_DRUM_KIT 0x08
|
#define XINPUT_DEVSUBTYPE_DRUM_KIT 0x08
|
||||||
|
|
||||||
#endif // !XINPUT_USE_9_1_0
|
#endif // !XINPUT_USE_9_1_0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Flags for XINPUT_CAPABILITIES
|
// Flags for XINPUT_CAPABILITIES
|
||||||
//
|
//
|
||||||
#define XINPUT_CAPS_VOICE_SUPPORTED 0x0004
|
#define XINPUT_CAPS_VOICE_SUPPORTED 0x0004
|
||||||
|
|
||||||
//
|
//
|
||||||
// Constants for gamepad buttons
|
// Constants for gamepad buttons
|
||||||
//
|
//
|
||||||
#define XINPUT_GAMEPAD_DPAD_UP 0x0001
|
#define XINPUT_GAMEPAD_DPAD_UP 0x0001
|
||||||
#define XINPUT_GAMEPAD_DPAD_DOWN 0x0002
|
#define XINPUT_GAMEPAD_DPAD_DOWN 0x0002
|
||||||
#define XINPUT_GAMEPAD_DPAD_LEFT 0x0004
|
#define XINPUT_GAMEPAD_DPAD_LEFT 0x0004
|
||||||
#define XINPUT_GAMEPAD_DPAD_RIGHT 0x0008
|
#define XINPUT_GAMEPAD_DPAD_RIGHT 0x0008
|
||||||
#define XINPUT_GAMEPAD_START 0x0010
|
#define XINPUT_GAMEPAD_START 0x0010
|
||||||
#define XINPUT_GAMEPAD_BACK 0x0020
|
#define XINPUT_GAMEPAD_BACK 0x0020
|
||||||
#define XINPUT_GAMEPAD_LEFT_THUMB 0x0040
|
#define XINPUT_GAMEPAD_LEFT_THUMB 0x0040
|
||||||
#define XINPUT_GAMEPAD_RIGHT_THUMB 0x0080
|
#define XINPUT_GAMEPAD_RIGHT_THUMB 0x0080
|
||||||
#define XINPUT_GAMEPAD_LEFT_SHOULDER 0x0100
|
#define XINPUT_GAMEPAD_LEFT_SHOULDER 0x0100
|
||||||
#define XINPUT_GAMEPAD_RIGHT_SHOULDER 0x0200
|
#define XINPUT_GAMEPAD_RIGHT_SHOULDER 0x0200
|
||||||
#define XINPUT_GAMEPAD_A 0x1000
|
#define XINPUT_GAMEPAD_A 0x1000
|
||||||
#define XINPUT_GAMEPAD_B 0x2000
|
#define XINPUT_GAMEPAD_B 0x2000
|
||||||
#define XINPUT_GAMEPAD_X 0x4000
|
#define XINPUT_GAMEPAD_X 0x4000
|
||||||
#define XINPUT_GAMEPAD_Y 0x8000
|
#define XINPUT_GAMEPAD_Y 0x8000
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Gamepad thresholds
|
// Gamepad thresholds
|
||||||
//
|
//
|
||||||
#define XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE 7849
|
#define XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE 7849
|
||||||
#define XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE 8689
|
#define XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE 8689
|
||||||
#define XINPUT_GAMEPAD_TRIGGER_THRESHOLD 30
|
#define XINPUT_GAMEPAD_TRIGGER_THRESHOLD 30
|
||||||
|
|
||||||
//
|
//
|
||||||
// Flags to pass to XInputGetCapabilities
|
// Flags to pass to XInputGetCapabilities
|
||||||
//
|
//
|
||||||
#define XINPUT_FLAG_GAMEPAD 0x00000001
|
#define XINPUT_FLAG_GAMEPAD 0x00000001
|
||||||
|
|
||||||
|
|
||||||
#ifndef XINPUT_USE_9_1_0
|
#ifndef XINPUT_USE_9_1_0
|
||||||
|
|
||||||
//
|
//
|
||||||
// Devices that support batteries
|
// Devices that support batteries
|
||||||
//
|
//
|
||||||
#define BATTERY_DEVTYPE_GAMEPAD 0x00
|
#define BATTERY_DEVTYPE_GAMEPAD 0x00
|
||||||
#define BATTERY_DEVTYPE_HEADSET 0x01
|
#define BATTERY_DEVTYPE_HEADSET 0x01
|
||||||
|
|
||||||
//
|
//
|
||||||
// Flags for battery status level
|
// Flags for battery status level
|
||||||
//
|
//
|
||||||
#define BATTERY_TYPE_DISCONNECTED 0x00 // This device is not connected
|
#define BATTERY_TYPE_DISCONNECTED 0x00 // This device is not connected
|
||||||
#define BATTERY_TYPE_WIRED 0x01 // Wired device, no battery
|
#define BATTERY_TYPE_WIRED 0x01 // Wired device, no battery
|
||||||
#define BATTERY_TYPE_ALKALINE 0x02 // Alkaline battery source
|
#define BATTERY_TYPE_ALKALINE 0x02 // Alkaline battery source
|
||||||
#define BATTERY_TYPE_NIMH 0x03 // Nickel Metal Hydride battery source
|
#define BATTERY_TYPE_NIMH 0x03 // Nickel Metal Hydride battery source
|
||||||
#define BATTERY_TYPE_UNKNOWN 0xFF // Cannot determine the battery type
|
#define BATTERY_TYPE_UNKNOWN 0xFF // Cannot determine the battery type
|
||||||
|
|
||||||
// These are only valid for wireless, connected devices, with known battery types
|
// These are only valid for wireless, connected devices, with known battery types
|
||||||
// The amount of use time remaining depends on the type of device.
|
// The amount of use time remaining depends on the type of device.
|
||||||
#define BATTERY_LEVEL_EMPTY 0x00
|
#define BATTERY_LEVEL_EMPTY 0x00
|
||||||
#define BATTERY_LEVEL_LOW 0x01
|
#define BATTERY_LEVEL_LOW 0x01
|
||||||
#define BATTERY_LEVEL_MEDIUM 0x02
|
#define BATTERY_LEVEL_MEDIUM 0x02
|
||||||
#define BATTERY_LEVEL_FULL 0x03
|
#define BATTERY_LEVEL_FULL 0x03
|
||||||
|
|
||||||
// User index definitions
|
// User index definitions
|
||||||
#define XUSER_MAX_COUNT 4
|
#define XUSER_MAX_COUNT 4
|
||||||
|
|
||||||
#define XUSER_INDEX_ANY 0x000000FF
|
#define XUSER_INDEX_ANY 0x000000FF
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Codes returned for the gamepad keystroke
|
// Codes returned for the gamepad keystroke
|
||||||
//
|
//
|
||||||
|
|
||||||
#define VK_PAD_A 0x5800
|
#define VK_PAD_A 0x5800
|
||||||
#define VK_PAD_B 0x5801
|
#define VK_PAD_B 0x5801
|
||||||
#define VK_PAD_X 0x5802
|
#define VK_PAD_X 0x5802
|
||||||
#define VK_PAD_Y 0x5803
|
#define VK_PAD_Y 0x5803
|
||||||
#define VK_PAD_RSHOULDER 0x5804
|
#define VK_PAD_RSHOULDER 0x5804
|
||||||
#define VK_PAD_LSHOULDER 0x5805
|
#define VK_PAD_LSHOULDER 0x5805
|
||||||
#define VK_PAD_LTRIGGER 0x5806
|
#define VK_PAD_LTRIGGER 0x5806
|
||||||
#define VK_PAD_RTRIGGER 0x5807
|
#define VK_PAD_RTRIGGER 0x5807
|
||||||
|
|
||||||
#define VK_PAD_DPAD_UP 0x5810
|
#define VK_PAD_DPAD_UP 0x5810
|
||||||
#define VK_PAD_DPAD_DOWN 0x5811
|
#define VK_PAD_DPAD_DOWN 0x5811
|
||||||
#define VK_PAD_DPAD_LEFT 0x5812
|
#define VK_PAD_DPAD_LEFT 0x5812
|
||||||
#define VK_PAD_DPAD_RIGHT 0x5813
|
#define VK_PAD_DPAD_RIGHT 0x5813
|
||||||
#define VK_PAD_START 0x5814
|
#define VK_PAD_START 0x5814
|
||||||
#define VK_PAD_BACK 0x5815
|
#define VK_PAD_BACK 0x5815
|
||||||
#define VK_PAD_LTHUMB_PRESS 0x5816
|
#define VK_PAD_LTHUMB_PRESS 0x5816
|
||||||
#define VK_PAD_RTHUMB_PRESS 0x5817
|
#define VK_PAD_RTHUMB_PRESS 0x5817
|
||||||
|
|
||||||
#define VK_PAD_LTHUMB_UP 0x5820
|
#define VK_PAD_LTHUMB_UP 0x5820
|
||||||
#define VK_PAD_LTHUMB_DOWN 0x5821
|
#define VK_PAD_LTHUMB_DOWN 0x5821
|
||||||
#define VK_PAD_LTHUMB_RIGHT 0x5822
|
#define VK_PAD_LTHUMB_RIGHT 0x5822
|
||||||
#define VK_PAD_LTHUMB_LEFT 0x5823
|
#define VK_PAD_LTHUMB_LEFT 0x5823
|
||||||
#define VK_PAD_LTHUMB_UPLEFT 0x5824
|
#define VK_PAD_LTHUMB_UPLEFT 0x5824
|
||||||
#define VK_PAD_LTHUMB_UPRIGHT 0x5825
|
#define VK_PAD_LTHUMB_UPRIGHT 0x5825
|
||||||
#define VK_PAD_LTHUMB_DOWNRIGHT 0x5826
|
#define VK_PAD_LTHUMB_DOWNRIGHT 0x5826
|
||||||
#define VK_PAD_LTHUMB_DOWNLEFT 0x5827
|
#define VK_PAD_LTHUMB_DOWNLEFT 0x5827
|
||||||
|
|
||||||
#define VK_PAD_RTHUMB_UP 0x5830
|
#define VK_PAD_RTHUMB_UP 0x5830
|
||||||
#define VK_PAD_RTHUMB_DOWN 0x5831
|
#define VK_PAD_RTHUMB_DOWN 0x5831
|
||||||
#define VK_PAD_RTHUMB_RIGHT 0x5832
|
#define VK_PAD_RTHUMB_RIGHT 0x5832
|
||||||
#define VK_PAD_RTHUMB_LEFT 0x5833
|
#define VK_PAD_RTHUMB_LEFT 0x5833
|
||||||
#define VK_PAD_RTHUMB_UPLEFT 0x5834
|
#define VK_PAD_RTHUMB_UPLEFT 0x5834
|
||||||
#define VK_PAD_RTHUMB_UPRIGHT 0x5835
|
#define VK_PAD_RTHUMB_UPRIGHT 0x5835
|
||||||
#define VK_PAD_RTHUMB_DOWNRIGHT 0x5836
|
#define VK_PAD_RTHUMB_DOWNRIGHT 0x5836
|
||||||
#define VK_PAD_RTHUMB_DOWNLEFT 0x5837
|
#define VK_PAD_RTHUMB_DOWNLEFT 0x5837
|
||||||
|
|
||||||
//
|
//
|
||||||
// Flags used in XINPUT_KEYSTROKE
|
// Flags used in XINPUT_KEYSTROKE
|
||||||
//
|
//
|
||||||
#define XINPUT_KEYSTROKE_KEYDOWN 0x0001
|
#define XINPUT_KEYSTROKE_KEYDOWN 0x0001
|
||||||
#define XINPUT_KEYSTROKE_KEYUP 0x0002
|
#define XINPUT_KEYSTROKE_KEYUP 0x0002
|
||||||
#define XINPUT_KEYSTROKE_REPEAT 0x0004
|
#define XINPUT_KEYSTROKE_REPEAT 0x0004
|
||||||
|
|
||||||
#endif //!XINPUT_USE_9_1_0
|
#endif //!XINPUT_USE_9_1_0
|
||||||
|
|
||||||
//
|
//
|
||||||
// Structures used by XInput APIs
|
// Structures used by XInput APIs
|
||||||
//
|
//
|
||||||
typedef struct _XINPUT_GAMEPAD
|
typedef struct _XINPUT_GAMEPAD
|
||||||
{
|
{
|
||||||
WORD wButtons;
|
WORD wButtons;
|
||||||
BYTE bLeftTrigger;
|
BYTE bLeftTrigger;
|
||||||
BYTE bRightTrigger;
|
BYTE bRightTrigger;
|
||||||
SHORT sThumbLX;
|
SHORT sThumbLX;
|
||||||
SHORT sThumbLY;
|
SHORT sThumbLY;
|
||||||
SHORT sThumbRX;
|
SHORT sThumbRX;
|
||||||
SHORT sThumbRY;
|
SHORT sThumbRY;
|
||||||
} XINPUT_GAMEPAD, *PXINPUT_GAMEPAD;
|
} XINPUT_GAMEPAD, *PXINPUT_GAMEPAD;
|
||||||
|
|
||||||
typedef struct _XINPUT_STATE
|
typedef struct _XINPUT_STATE
|
||||||
{
|
{
|
||||||
DWORD dwPacketNumber;
|
DWORD dwPacketNumber;
|
||||||
XINPUT_GAMEPAD Gamepad;
|
XINPUT_GAMEPAD Gamepad;
|
||||||
} XINPUT_STATE, *PXINPUT_STATE;
|
} XINPUT_STATE, *PXINPUT_STATE;
|
||||||
|
|
||||||
typedef struct _XINPUT_VIBRATION
|
typedef struct _XINPUT_VIBRATION
|
||||||
{
|
{
|
||||||
WORD wLeftMotorSpeed;
|
WORD wLeftMotorSpeed;
|
||||||
WORD wRightMotorSpeed;
|
WORD wRightMotorSpeed;
|
||||||
} XINPUT_VIBRATION, *PXINPUT_VIBRATION;
|
} XINPUT_VIBRATION, *PXINPUT_VIBRATION;
|
||||||
|
|
||||||
typedef struct _XINPUT_CAPABILITIES
|
typedef struct _XINPUT_CAPABILITIES
|
||||||
{
|
{
|
||||||
BYTE Type;
|
BYTE Type;
|
||||||
BYTE SubType;
|
BYTE SubType;
|
||||||
WORD Flags;
|
WORD Flags;
|
||||||
XINPUT_GAMEPAD Gamepad;
|
XINPUT_GAMEPAD Gamepad;
|
||||||
XINPUT_VIBRATION Vibration;
|
XINPUT_VIBRATION Vibration;
|
||||||
} XINPUT_CAPABILITIES, *PXINPUT_CAPABILITIES;
|
} XINPUT_CAPABILITIES, *PXINPUT_CAPABILITIES;
|
||||||
|
|
||||||
#ifndef XINPUT_USE_9_1_0
|
#ifndef XINPUT_USE_9_1_0
|
||||||
|
|
||||||
typedef struct _XINPUT_BATTERY_INFORMATION
|
typedef struct _XINPUT_BATTERY_INFORMATION
|
||||||
{
|
{
|
||||||
BYTE BatteryType;
|
BYTE BatteryType;
|
||||||
BYTE BatteryLevel;
|
BYTE BatteryLevel;
|
||||||
} XINPUT_BATTERY_INFORMATION, *PXINPUT_BATTERY_INFORMATION;
|
} XINPUT_BATTERY_INFORMATION, *PXINPUT_BATTERY_INFORMATION;
|
||||||
|
|
||||||
typedef struct _XINPUT_KEYSTROKE
|
typedef struct _XINPUT_KEYSTROKE
|
||||||
{
|
{
|
||||||
WORD VirtualKey;
|
WORD VirtualKey;
|
||||||
WCHAR Unicode;
|
WCHAR Unicode;
|
||||||
WORD Flags;
|
WORD Flags;
|
||||||
BYTE UserIndex;
|
BYTE UserIndex;
|
||||||
BYTE HidCode;
|
BYTE HidCode;
|
||||||
} XINPUT_KEYSTROKE, *PXINPUT_KEYSTROKE;
|
} XINPUT_KEYSTROKE, *PXINPUT_KEYSTROKE;
|
||||||
|
|
||||||
#endif // !XINPUT_USE_9_1_0
|
#endif // !XINPUT_USE_9_1_0
|
||||||
|
|
||||||
//
|
//
|
||||||
// XInput APIs
|
// XInput APIs
|
||||||
//
|
//
|
||||||
|
|
||||||
// now defined in proxy class.
|
// now defined in proxy class.
|
||||||
|
|
||||||
#endif //_XINPUT_H_
|
#endif //_XINPUT_H_
|
||||||
|
|
|
@ -1,296 +1,296 @@
|
||||||
/*
|
/*
|
||||||
* synergy -- mouse and keyboard sharing utility
|
* synergy -- mouse and keyboard sharing utility
|
||||||
* Copyright (C) 2012 Bolton Software Ltd.
|
* Copyright (C) 2012 Bolton Software Ltd.
|
||||||
* Copyright (C) 2011 Chris Schoeneman
|
* Copyright (C) 2011 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
|
||||||
* found in the file COPYING that should have accompanied this file.
|
* found in the file COPYING that should have accompanied this file.
|
||||||
*
|
*
|
||||||
* This package is distributed in the hope that it will be useful,
|
* This package is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* 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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#define SYNERGY_EXPORT_XINPUT_HOOKS
|
#define SYNERGY_EXPORT_XINPUT_HOOKS
|
||||||
#define REQUIRED_XINPUT_DLL "xinput1_3.dll"
|
#define REQUIRED_XINPUT_DLL "xinput1_3.dll"
|
||||||
#define HOOK_TIMEOUT 10000 // 10 sec
|
#define HOOK_TIMEOUT 10000 // 10 sec
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <XInput.h>
|
#include <XInput.h>
|
||||||
#include "XInputHook.h"
|
#include "XInputHook.h"
|
||||||
#include "HookDLL.h"
|
#include "HookDLL.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
HINSTANCE dll;
|
HINSTANCE dll;
|
||||||
char name[256];
|
char name[256];
|
||||||
|
|
||||||
#pragma data_seg(".SHARED")
|
#pragma data_seg(".SHARED")
|
||||||
|
|
||||||
HHOOK s_hook = NULL;
|
HHOOK s_hook = NULL;
|
||||||
|
|
||||||
// @todo use a struct for multiple gamepad support
|
// @todo use a struct for multiple gamepad support
|
||||||
WORD s_buttons = 0;
|
WORD s_buttons = 0;
|
||||||
SHORT s_leftStickX = 0;
|
SHORT s_leftStickX = 0;
|
||||||
SHORT s_leftStickY = 0;
|
SHORT s_leftStickY = 0;
|
||||||
SHORT s_rightStickX = 0;
|
SHORT s_rightStickX = 0;
|
||||||
SHORT s_rightStickY = 0;
|
SHORT s_rightStickY = 0;
|
||||||
BYTE s_leftTrigger = 0;
|
BYTE s_leftTrigger = 0;
|
||||||
BYTE s_rightTrigger = 0;
|
BYTE s_rightTrigger = 0;
|
||||||
BOOL s_timingReqQueued = FALSE;
|
BOOL s_timingReqQueued = FALSE;
|
||||||
BOOL s_timingRespQueued = FALSE;
|
BOOL s_timingRespQueued = FALSE;
|
||||||
DWORD s_lastFakeMillis = 0;
|
DWORD s_lastFakeMillis = 0;
|
||||||
WORD s_fakeFreqMillis = 0;
|
WORD s_fakeFreqMillis = 0;
|
||||||
DWORD s_packetNumber = 0;
|
DWORD s_packetNumber = 0;
|
||||||
WORD s_leftMotor = 0;
|
WORD s_leftMotor = 0;
|
||||||
WORD s_rightMotor = 0;
|
WORD s_rightMotor = 0;
|
||||||
BOOL s_feedbackQueued = FALSE;
|
BOOL s_feedbackQueued = FALSE;
|
||||||
|
|
||||||
#pragma data_seg()
|
#pragma data_seg()
|
||||||
|
|
||||||
#pragma comment(linker, "/SECTION:.SHARED,RWS")
|
#pragma comment(linker, "/SECTION:.SHARED,RWS")
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
std::stringstream _xInputHookLogStream;
|
std::stringstream _xInputHookLogStream;
|
||||||
#define LOG(s) \
|
#define LOG(s) \
|
||||||
_xInputHookLogStream.str(""); \
|
_xInputHookLogStream.str(""); \
|
||||||
_xInputHookLogStream << "Synergy XInputHook: " << s << endl; \
|
_xInputHookLogStream << "Synergy XInputHook: " << s << endl; \
|
||||||
OutputDebugString( _xInputHookLogStream.str().c_str())
|
OutputDebugString( _xInputHookLogStream.str().c_str())
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
SDLLHook s_xInputHook =
|
SDLLHook s_xInputHook =
|
||||||
{
|
{
|
||||||
XINPUT_DLL,
|
XINPUT_DLL,
|
||||||
false, NULL,
|
false, NULL,
|
||||||
{
|
{
|
||||||
{ (char*)(0x80000002), HookXInputGetState },
|
{ (char*)(0x80000002), HookXInputGetState },
|
||||||
{ (char*)(0x80000003), HookXInputSetState },
|
{ (char*)(0x80000003), HookXInputSetState },
|
||||||
{ (char*)(0x80000004), HookXInputGetCapabilities },
|
{ (char*)(0x80000004), HookXInputGetCapabilities },
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
BOOL APIENTRY
|
BOOL APIENTRY
|
||||||
DllMain(HINSTANCE module, DWORD reason, LPVOID reserved)
|
DllMain(HINSTANCE module, DWORD reason, LPVOID reserved)
|
||||||
{
|
{
|
||||||
if (reason == DLL_PROCESS_ATTACH)
|
if (reason == DLL_PROCESS_ATTACH)
|
||||||
{
|
{
|
||||||
dll = module;
|
dll = module;
|
||||||
|
|
||||||
// disable unwanted thread notifications to reduce overhead
|
// disable unwanted thread notifications to reduce overhead
|
||||||
DisableThreadLibraryCalls(dll);
|
DisableThreadLibraryCalls(dll);
|
||||||
|
|
||||||
GetModuleFileName(GetModuleHandle(NULL), name, sizeof(name));
|
GetModuleFileName(GetModuleHandle(NULL), name, sizeof(name));
|
||||||
|
|
||||||
// don't hook synergys (this needs to detect real input)
|
// don't hook synergys (this needs to detect real input)
|
||||||
if (string(name).find("synergy") == string::npos)
|
if (string(name).find("synergy") == string::npos)
|
||||||
{
|
{
|
||||||
LOG("checking '" << name << "' for " << XINPUT_DLL);
|
LOG("checking '" << name << "' for " << XINPUT_DLL);
|
||||||
HookAPICalls(&s_xInputHook);
|
HookAPICalls(&s_xInputHook);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SetXInputButtons(DWORD userIndex, WORD buttons)
|
SetXInputButtons(DWORD userIndex, WORD buttons)
|
||||||
{
|
{
|
||||||
s_buttons = buttons;
|
s_buttons = buttons;
|
||||||
|
|
||||||
s_packetNumber++;
|
s_packetNumber++;
|
||||||
|
|
||||||
LOG("SetXInputButtons: idx=" << userIndex << ", btns=" << buttons);
|
LOG("SetXInputButtons: idx=" << userIndex << ", btns=" << buttons);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SetXInputSticks(DWORD userIndex, SHORT lx, SHORT ly, SHORT rx, SHORT ry)
|
SetXInputSticks(DWORD userIndex, SHORT lx, SHORT ly, SHORT rx, SHORT ry)
|
||||||
{
|
{
|
||||||
s_leftStickX = lx;
|
s_leftStickX = lx;
|
||||||
s_leftStickY = ly;
|
s_leftStickY = ly;
|
||||||
s_rightStickX = rx;
|
s_rightStickX = rx;
|
||||||
s_rightStickY = ry;
|
s_rightStickY = ry;
|
||||||
|
|
||||||
s_packetNumber++;
|
s_packetNumber++;
|
||||||
|
|
||||||
LOG("SetXInputSticks:" <<
|
LOG("SetXInputSticks:" <<
|
||||||
" l=" << s_leftStickX << "," << s_leftStickY <<
|
" l=" << s_leftStickX << "," << s_leftStickY <<
|
||||||
" r=" << s_rightStickX << "," << s_rightStickY);
|
" r=" << s_rightStickX << "," << s_rightStickY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SetXInputTriggers(DWORD userIndex, BYTE left, BYTE right)
|
SetXInputTriggers(DWORD userIndex, BYTE left, BYTE right)
|
||||||
{
|
{
|
||||||
s_leftTrigger = left;
|
s_leftTrigger = left;
|
||||||
s_rightTrigger = right;
|
s_rightTrigger = right;
|
||||||
|
|
||||||
s_packetNumber++;
|
s_packetNumber++;
|
||||||
|
|
||||||
LOG("SetXInputTriggers: " <<
|
LOG("SetXInputTriggers: " <<
|
||||||
"l=" << (int)left << " r=" << (int)right);
|
"l=" << (int)left << " r=" << (int)right);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
QueueXInputTimingReq()
|
QueueXInputTimingReq()
|
||||||
{
|
{
|
||||||
s_timingReqQueued = TRUE;
|
s_timingReqQueued = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
DequeueXInputTimingResp()
|
DequeueXInputTimingResp()
|
||||||
{
|
{
|
||||||
BOOL result = s_timingRespQueued;
|
BOOL result = s_timingRespQueued;
|
||||||
s_timingRespQueued = FALSE;
|
s_timingRespQueued = FALSE;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
DequeueXInputFeedback(WORD* leftMotor, WORD* rightMotor)
|
DequeueXInputFeedback(WORD* leftMotor, WORD* rightMotor)
|
||||||
{
|
{
|
||||||
if (s_feedbackQueued)
|
if (s_feedbackQueued)
|
||||||
{
|
{
|
||||||
*leftMotor = s_leftMotor;
|
*leftMotor = s_leftMotor;
|
||||||
*rightMotor = s_rightMotor;
|
*rightMotor = s_rightMotor;
|
||||||
s_feedbackQueued = FALSE;
|
s_feedbackQueued = FALSE;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
WORD
|
WORD
|
||||||
GetXInputFakeFreqMillis()
|
GetXInputFakeFreqMillis()
|
||||||
{
|
{
|
||||||
return s_fakeFreqMillis;
|
return s_fakeFreqMillis;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD WINAPI
|
DWORD WINAPI
|
||||||
HookXInputGetState(DWORD userIndex, XINPUT_STATE* state)
|
HookXInputGetState(DWORD userIndex, XINPUT_STATE* state)
|
||||||
{
|
{
|
||||||
// @todo multiple device support
|
// @todo multiple device support
|
||||||
if (userIndex != 0)
|
if (userIndex != 0)
|
||||||
{
|
{
|
||||||
return ERROR_DEVICE_NOT_CONNECTED;
|
return ERROR_DEVICE_NOT_CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD now = GetTickCount();
|
DWORD now = GetTickCount();
|
||||||
s_fakeFreqMillis = (WORD)(now - s_lastFakeMillis);
|
s_fakeFreqMillis = (WORD)(now - s_lastFakeMillis);
|
||||||
s_lastFakeMillis = now;
|
s_lastFakeMillis = now;
|
||||||
|
|
||||||
state->dwPacketNumber = s_packetNumber;
|
state->dwPacketNumber = s_packetNumber;
|
||||||
state->Gamepad.wButtons = s_buttons;
|
state->Gamepad.wButtons = s_buttons;
|
||||||
state->Gamepad.bLeftTrigger = s_leftTrigger;
|
state->Gamepad.bLeftTrigger = s_leftTrigger;
|
||||||
state->Gamepad.bRightTrigger = s_rightTrigger;
|
state->Gamepad.bRightTrigger = s_rightTrigger;
|
||||||
state->Gamepad.sThumbLX = s_leftStickX;
|
state->Gamepad.sThumbLX = s_leftStickX;
|
||||||
state->Gamepad.sThumbLY = s_leftStickY;
|
state->Gamepad.sThumbLY = s_leftStickY;
|
||||||
state->Gamepad.sThumbRX = s_rightStickX;
|
state->Gamepad.sThumbRX = s_rightStickX;
|
||||||
state->Gamepad.sThumbRY = s_rightStickY;
|
state->Gamepad.sThumbRY = s_rightStickY;
|
||||||
|
|
||||||
LOG("HookXInputGetState"
|
LOG("HookXInputGetState"
|
||||||
<< ", idx=" << userIndex
|
<< ", idx=" << userIndex
|
||||||
<< ", pkt=" << state->dwPacketNumber
|
<< ", pkt=" << state->dwPacketNumber
|
||||||
<< ", btn=" << state->Gamepad.wButtons
|
<< ", btn=" << state->Gamepad.wButtons
|
||||||
<< ", t1=" << (int)state->Gamepad.bLeftTrigger
|
<< ", t1=" << (int)state->Gamepad.bLeftTrigger
|
||||||
<< ", t2=" << (int)state->Gamepad.bRightTrigger
|
<< ", t2=" << (int)state->Gamepad.bRightTrigger
|
||||||
<< ", s1=" << state->Gamepad.sThumbLX << "," << state->Gamepad.sThumbLY
|
<< ", s1=" << state->Gamepad.sThumbLX << "," << state->Gamepad.sThumbLY
|
||||||
<< ", s2=" << state->Gamepad.sThumbRX << "," << state->Gamepad.sThumbRY);
|
<< ", s2=" << state->Gamepad.sThumbRX << "," << state->Gamepad.sThumbRY);
|
||||||
|
|
||||||
if (s_timingReqQueued)
|
if (s_timingReqQueued)
|
||||||
{
|
{
|
||||||
s_timingRespQueued = TRUE;
|
s_timingRespQueued = TRUE;
|
||||||
s_timingReqQueued = FALSE;
|
s_timingReqQueued = FALSE;
|
||||||
LOG("timing response queued");
|
LOG("timing response queued");
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD WINAPI
|
DWORD WINAPI
|
||||||
HookXInputSetState(DWORD userIndex, XINPUT_VIBRATION* vibration)
|
HookXInputSetState(DWORD userIndex, XINPUT_VIBRATION* vibration)
|
||||||
{
|
{
|
||||||
// @todo multiple device support
|
// @todo multiple device support
|
||||||
if (userIndex != 0)
|
if (userIndex != 0)
|
||||||
{
|
{
|
||||||
return ERROR_DEVICE_NOT_CONNECTED;
|
return ERROR_DEVICE_NOT_CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// only change values and queue feedback change if
|
// only change values and queue feedback change if
|
||||||
// feedback has actually changed.
|
// feedback has actually changed.
|
||||||
if ((s_leftMotor != vibration->wLeftMotorSpeed) ||
|
if ((s_leftMotor != vibration->wLeftMotorSpeed) ||
|
||||||
(s_rightMotor != vibration->wRightMotorSpeed))
|
(s_rightMotor != vibration->wRightMotorSpeed))
|
||||||
{
|
{
|
||||||
s_leftMotor = vibration->wLeftMotorSpeed;
|
s_leftMotor = vibration->wLeftMotorSpeed;
|
||||||
s_rightMotor = vibration->wRightMotorSpeed;
|
s_rightMotor = vibration->wRightMotorSpeed;
|
||||||
s_feedbackQueued = TRUE;
|
s_feedbackQueued = TRUE;
|
||||||
|
|
||||||
LOG("HookXInputSetState"
|
LOG("HookXInputSetState"
|
||||||
", idx=" << userIndex <<
|
", idx=" << userIndex <<
|
||||||
", lm=" << s_leftMotor <<
|
", lm=" << s_leftMotor <<
|
||||||
", rm=" << s_rightMotor);
|
", rm=" << s_rightMotor);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD WINAPI
|
DWORD WINAPI
|
||||||
HookXInputGetCapabilities(DWORD userIndex, DWORD flags, XINPUT_CAPABILITIES* capabilities)
|
HookXInputGetCapabilities(DWORD userIndex, DWORD flags, XINPUT_CAPABILITIES* capabilities)
|
||||||
{
|
{
|
||||||
// @todo multiple device support
|
// @todo multiple device support
|
||||||
if (userIndex != 0)
|
if (userIndex != 0)
|
||||||
{
|
{
|
||||||
return ERROR_DEVICE_NOT_CONNECTED;
|
return ERROR_DEVICE_NOT_CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG("HookXInputGetCapabilities"
|
LOG("HookXInputGetCapabilities"
|
||||||
", idx=" << userIndex <<
|
", idx=" << userIndex <<
|
||||||
", flags=" << flags);
|
", flags=" << flags);
|
||||||
|
|
||||||
capabilities->Type = 1;
|
capabilities->Type = 1;
|
||||||
capabilities->SubType = 1;
|
capabilities->SubType = 1;
|
||||||
capabilities->Flags = 4;
|
capabilities->Flags = 4;
|
||||||
capabilities->Gamepad.bLeftTrigger = 1;
|
capabilities->Gamepad.bLeftTrigger = 1;
|
||||||
capabilities->Gamepad.bRightTrigger = 1;
|
capabilities->Gamepad.bRightTrigger = 1;
|
||||||
capabilities->Gamepad.sThumbLX = 1;
|
capabilities->Gamepad.sThumbLX = 1;
|
||||||
capabilities->Gamepad.sThumbLY = 1;
|
capabilities->Gamepad.sThumbLY = 1;
|
||||||
capabilities->Gamepad.sThumbRX = 1;
|
capabilities->Gamepad.sThumbRX = 1;
|
||||||
capabilities->Gamepad.sThumbRY = 1;
|
capabilities->Gamepad.sThumbRY = 1;
|
||||||
capabilities->Gamepad.wButtons = 62463;
|
capabilities->Gamepad.wButtons = 62463;
|
||||||
capabilities->Vibration.wLeftMotorSpeed = 1;
|
capabilities->Vibration.wLeftMotorSpeed = 1;
|
||||||
capabilities->Vibration.wRightMotorSpeed = 1;
|
capabilities->Vibration.wRightMotorSpeed = 1;
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
synxinhk_API LRESULT CALLBACK
|
synxinhk_API LRESULT CALLBACK
|
||||||
HookProc(int code, WPARAM wParam, LPARAM lParam)
|
HookProc(int code, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
return CallNextHookEx(s_hook, code, wParam, lParam);
|
return CallNextHookEx(s_hook, code, wParam, lParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
synxinhk_API BOOL
|
synxinhk_API BOOL
|
||||||
InstallXInputHook()
|
InstallXInputHook()
|
||||||
{
|
{
|
||||||
if (_stricmp(XINPUT_DLL, REQUIRED_XINPUT_DLL) != 0)
|
if (_stricmp(XINPUT_DLL, REQUIRED_XINPUT_DLL) != 0)
|
||||||
{
|
{
|
||||||
LOG("DLL not supported: " << XINPUT_DLL);
|
LOG("DLL not supported: " << XINPUT_DLL);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG("installing hook");
|
LOG("installing hook");
|
||||||
s_hook = SetWindowsHookEx(WH_CBT, HookProc, dll, 0);
|
s_hook = SetWindowsHookEx(WH_CBT, HookProc, dll, 0);
|
||||||
LOG("hook installed");
|
LOG("hook installed");
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
synxinhk_API void
|
synxinhk_API void
|
||||||
RemoveXInputHook()
|
RemoveXInputHook()
|
||||||
{
|
{
|
||||||
LOG("removing hook");
|
LOG("removing hook");
|
||||||
UnhookWindowsHookEx(s_hook);
|
UnhookWindowsHookEx(s_hook);
|
||||||
LOG("hook removed");
|
LOG("hook removed");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,44 +1,44 @@
|
||||||
/*
|
/*
|
||||||
* synergy -- mouse and keyboard sharing utility
|
* synergy -- mouse and keyboard sharing utility
|
||||||
* Copyright (C) 2012 Bolton Software Ltd.
|
* Copyright (C) 2012 Bolton Software Ltd.
|
||||||
* Copyright (C) 2011 Chris Schoeneman
|
* Copyright (C) 2011 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
|
||||||
* found in the file COPYING that should have accompanied this file.
|
* found in the file COPYING that should have accompanied this file.
|
||||||
*
|
*
|
||||||
* This package is distributed in the hope that it will be useful,
|
* This package is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* 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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef synxinhk_EXPORTS
|
#ifdef synxinhk_EXPORTS
|
||||||
#define synxinhk_API __declspec(dllexport)
|
#define synxinhk_API __declspec(dllexport)
|
||||||
#else
|
#else
|
||||||
#define synxinhk_API __declspec(dllimport)
|
#define synxinhk_API __declspec(dllimport)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
synxinhk_API LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam);
|
synxinhk_API LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam);
|
||||||
synxinhk_API BOOL InstallXInputHook();
|
synxinhk_API BOOL InstallXInputHook();
|
||||||
synxinhk_API void RemoveXInputHook();
|
synxinhk_API void RemoveXInputHook();
|
||||||
synxinhk_API void SetXInputButtons(DWORD userIndex, WORD buttons);
|
synxinhk_API void SetXInputButtons(DWORD userIndex, WORD buttons);
|
||||||
synxinhk_API void SetXInputSticks(DWORD userIndex, SHORT lx, SHORT ly, SHORT rx, SHORT ry);
|
synxinhk_API void SetXInputSticks(DWORD userIndex, SHORT lx, SHORT ly, SHORT rx, SHORT ry);
|
||||||
synxinhk_API void SetXInputTriggers(DWORD userIndex, BYTE left, BYTE right);
|
synxinhk_API void SetXInputTriggers(DWORD userIndex, BYTE left, BYTE right);
|
||||||
synxinhk_API void QueueXInputTimingReq();
|
synxinhk_API void QueueXInputTimingReq();
|
||||||
synxinhk_API BOOL DequeueXInputTimingResp();
|
synxinhk_API BOOL DequeueXInputTimingResp();
|
||||||
synxinhk_API WORD GetXInputFakeFreqMillis();
|
synxinhk_API WORD GetXInputFakeFreqMillis();
|
||||||
synxinhk_API BOOL DequeueXInputFeedback(WORD* leftMotor, WORD* rightMotor);
|
synxinhk_API BOOL DequeueXInputFeedback(WORD* leftMotor, WORD* rightMotor);
|
||||||
|
|
||||||
#ifdef SYNERGY_EXPORT_XINPUT_HOOKS
|
#ifdef SYNERGY_EXPORT_XINPUT_HOOKS
|
||||||
|
|
||||||
synxinhk_API DWORD WINAPI HookXInputGetState(DWORD dwUserIndex, XINPUT_STATE* pState);
|
synxinhk_API DWORD WINAPI HookXInputGetState(DWORD dwUserIndex, XINPUT_STATE* pState);
|
||||||
synxinhk_API DWORD WINAPI HookXInputSetState(DWORD dwUserIndex, XINPUT_VIBRATION* pVibration);
|
synxinhk_API DWORD WINAPI HookXInputSetState(DWORD dwUserIndex, XINPUT_VIBRATION* pVibration);
|
||||||
synxinhk_API DWORD WINAPI HookXInputGetCapabilities(DWORD userIndex, DWORD flags, XINPUT_CAPABILITIES* capabilities);
|
synxinhk_API DWORD WINAPI HookXInputGetCapabilities(DWORD userIndex, DWORD flags, XINPUT_CAPABILITIES* capabilities);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
#define SYNERGY_EXPORT_XINPUT_HOOKS
|
#define SYNERGY_EXPORT_XINPUT_HOOKS
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include "XInputProxy13.h"
|
#include "XInputProxy13.h"
|
||||||
#include "XInputHook.h"
|
#include "XInputHook.h"
|
||||||
|
@ -31,43 +31,43 @@
|
||||||
#pragma comment(linker, "/EXPORT:XInputGetBatteryInformation=_XInputGetBatteryInformation@12,@7")
|
#pragma comment(linker, "/EXPORT:XInputGetBatteryInformation=_XInputGetBatteryInformation@12,@7")
|
||||||
#pragma comment(linker, "/EXPORT:XInputGetKeystroke=_XInputGetKeystroke@12,@8")
|
#pragma comment(linker, "/EXPORT:XInputGetKeystroke=_XInputGetKeystroke@12,@8")
|
||||||
|
|
||||||
sxinpx13_API DWORD WINAPI
|
|
||||||
XInputGetState(DWORD dwUserIndex, XINPUT_STATE* pState)
|
|
||||||
{
|
|
||||||
return HookXInputGetState(dwUserIndex, pState);
|
|
||||||
}
|
|
||||||
|
|
||||||
sxinpx13_API DWORD WINAPI
|
|
||||||
XInputSetState(DWORD dwUserIndex, XINPUT_VIBRATION* pVibration)
|
|
||||||
{
|
|
||||||
return HookXInputSetState(dwUserIndex, pVibration);
|
|
||||||
}
|
|
||||||
|
|
||||||
sxinpx13_API DWORD WINAPI
|
|
||||||
XInputGetCapabilities(DWORD dwUserIndex, DWORD dwFlags, XINPUT_CAPABILITIES* pCapabilities)
|
|
||||||
{
|
|
||||||
return HookXInputGetCapabilities(dwUserIndex, dwFlags, pCapabilities);
|
|
||||||
}
|
|
||||||
|
|
||||||
sxinpx13_API void WINAPI
|
|
||||||
XInputEnable(BOOL enable)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
sxinpx13_API DWORD WINAPI
|
|
||||||
XInputGetDSoundAudioDeviceGuids(DWORD dwUserIndex, GUID* pDSoundRenderGuid, GUID* pDSoundCaptureGuid)
|
|
||||||
{
|
|
||||||
return ERROR_DEVICE_NOT_CONNECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
sxinpx13_API DWORD WINAPI
|
|
||||||
XInputGetBatteryInformation(DWORD dwUserIndex, BYTE devType, XINPUT_BATTERY_INFORMATION* pBatteryInformation)
|
|
||||||
{
|
|
||||||
return ERROR_DEVICE_NOT_CONNECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
sxinpx13_API DWORD WINAPI
|
sxinpx13_API DWORD WINAPI
|
||||||
XInputGetKeystroke(DWORD dwUserIndex, DWORD dwReserved, PXINPUT_KEYSTROKE pKeystroke)
|
XInputGetState(DWORD dwUserIndex, XINPUT_STATE* pState)
|
||||||
{
|
{
|
||||||
|
return HookXInputGetState(dwUserIndex, pState);
|
||||||
|
}
|
||||||
|
|
||||||
|
sxinpx13_API DWORD WINAPI
|
||||||
|
XInputSetState(DWORD dwUserIndex, XINPUT_VIBRATION* pVibration)
|
||||||
|
{
|
||||||
|
return HookXInputSetState(dwUserIndex, pVibration);
|
||||||
|
}
|
||||||
|
|
||||||
|
sxinpx13_API DWORD WINAPI
|
||||||
|
XInputGetCapabilities(DWORD dwUserIndex, DWORD dwFlags, XINPUT_CAPABILITIES* pCapabilities)
|
||||||
|
{
|
||||||
|
return HookXInputGetCapabilities(dwUserIndex, dwFlags, pCapabilities);
|
||||||
|
}
|
||||||
|
|
||||||
|
sxinpx13_API void WINAPI
|
||||||
|
XInputEnable(BOOL enable)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
sxinpx13_API DWORD WINAPI
|
||||||
|
XInputGetDSoundAudioDeviceGuids(DWORD dwUserIndex, GUID* pDSoundRenderGuid, GUID* pDSoundCaptureGuid)
|
||||||
|
{
|
||||||
|
return ERROR_DEVICE_NOT_CONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
sxinpx13_API DWORD WINAPI
|
||||||
|
XInputGetBatteryInformation(DWORD dwUserIndex, BYTE devType, XINPUT_BATTERY_INFORMATION* pBatteryInformation)
|
||||||
|
{
|
||||||
|
return ERROR_DEVICE_NOT_CONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
sxinpx13_API DWORD WINAPI
|
||||||
|
XInputGetKeystroke(DWORD dwUserIndex, DWORD dwReserved, PXINPUT_KEYSTROKE pKeystroke)
|
||||||
|
{
|
||||||
return ERROR_DEVICE_NOT_CONNECTED;
|
return ERROR_DEVICE_NOT_CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,67 +14,67 @@
|
||||||
*
|
*
|
||||||
* 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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef sxinpx13_EXPORTS
|
#ifdef sxinpx13_EXPORTS
|
||||||
#define sxinpx13_API __declspec(dllexport)
|
#define sxinpx13_API __declspec(dllexport)
|
||||||
#else
|
#else
|
||||||
#define sxinpx13_API __declspec(dllimport)
|
#define sxinpx13_API __declspec(dllimport)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "XInput13.h"
|
#include "XInput13.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sxinpx13_API DWORD WINAPI XInputGetState
|
sxinpx13_API DWORD WINAPI XInputGetState
|
||||||
(
|
(
|
||||||
__in DWORD dwUserIndex, // Index of the gamer associated with the device
|
__in DWORD dwUserIndex, // Index of the gamer associated with the device
|
||||||
__out XINPUT_STATE* pState // Receives the current state
|
__out XINPUT_STATE* pState // Receives the current state
|
||||||
);
|
);
|
||||||
|
|
||||||
sxinpx13_API DWORD WINAPI XInputSetState
|
sxinpx13_API DWORD WINAPI XInputSetState
|
||||||
(
|
(
|
||||||
__in DWORD dwUserIndex, // Index of the gamer associated with the device
|
__in DWORD dwUserIndex, // Index of the gamer associated with the device
|
||||||
__in XINPUT_VIBRATION* pVibration // The vibration information to send to the controller
|
__in XINPUT_VIBRATION* pVibration // The vibration information to send to the controller
|
||||||
);
|
);
|
||||||
|
|
||||||
sxinpx13_API DWORD WINAPI XInputGetCapabilities
|
sxinpx13_API DWORD WINAPI XInputGetCapabilities
|
||||||
(
|
(
|
||||||
__in DWORD dwUserIndex, // Index of the gamer associated with the device
|
__in DWORD dwUserIndex, // Index of the gamer associated with the device
|
||||||
__in DWORD dwFlags, // Input flags that identify the device type
|
__in DWORD dwFlags, // Input flags that identify the device type
|
||||||
__out XINPUT_CAPABILITIES* pCapabilities // Receives the capabilities
|
__out XINPUT_CAPABILITIES* pCapabilities // Receives the capabilities
|
||||||
);
|
);
|
||||||
|
|
||||||
sxinpx13_API void WINAPI XInputEnable
|
sxinpx13_API void WINAPI XInputEnable
|
||||||
(
|
(
|
||||||
__in BOOL enable // [in] Indicates whether xinput is enabled or disabled.
|
__in BOOL enable // [in] Indicates whether xinput is enabled or disabled.
|
||||||
);
|
);
|
||||||
|
|
||||||
sxinpx13_API DWORD WINAPI XInputGetDSoundAudioDeviceGuids
|
sxinpx13_API DWORD WINAPI XInputGetDSoundAudioDeviceGuids
|
||||||
(
|
(
|
||||||
__in DWORD dwUserIndex, // Index of the gamer associated with the device
|
__in DWORD dwUserIndex, // Index of the gamer associated with the device
|
||||||
__out GUID* pDSoundRenderGuid, // DSound device ID for render
|
__out GUID* pDSoundRenderGuid, // DSound device ID for render
|
||||||
__out GUID* pDSoundCaptureGuid // DSound device ID for capture
|
__out GUID* pDSoundCaptureGuid // DSound device ID for capture
|
||||||
);
|
);
|
||||||
|
|
||||||
sxinpx13_API DWORD WINAPI XInputGetBatteryInformation
|
sxinpx13_API DWORD WINAPI XInputGetBatteryInformation
|
||||||
(
|
(
|
||||||
__in DWORD dwUserIndex, // Index of the gamer associated with the device
|
__in DWORD dwUserIndex, // Index of the gamer associated with the device
|
||||||
__in BYTE devType, // Which device on this user index
|
__in BYTE devType, // Which device on this user index
|
||||||
__out XINPUT_BATTERY_INFORMATION* pBatteryInformation // Contains the level and types of batteries
|
__out XINPUT_BATTERY_INFORMATION* pBatteryInformation // Contains the level and types of batteries
|
||||||
);
|
);
|
||||||
|
|
||||||
sxinpx13_API DWORD WINAPI XInputGetKeystroke
|
sxinpx13_API DWORD WINAPI XInputGetKeystroke
|
||||||
(
|
(
|
||||||
__in DWORD dwUserIndex, // Index of the gamer associated with the device
|
__in DWORD dwUserIndex, // Index of the gamer associated with the device
|
||||||
__reserved DWORD dwReserved, // Reserved for future use
|
__reserved DWORD dwReserved, // Reserved for future use
|
||||||
__out PXINPUT_KEYSTROKE pKeystroke // Pointer to an XINPUT_KEYSTROKE structure that receives an input event.
|
__out PXINPUT_KEYSTROKE pKeystroke // Pointer to an XINPUT_KEYSTROKE structure that receives an input event.
|
||||||
);
|
);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
|
@ -83,7 +83,7 @@ public:
|
||||||
virtual void screensaver(bool activate) = 0;
|
virtual void screensaver(bool activate) = 0;
|
||||||
virtual void resetOptions() = 0;
|
virtual void resetOptions() = 0;
|
||||||
virtual void setOptions(const COptionsList& options) = 0;
|
virtual void setOptions(const COptionsList& options) = 0;
|
||||||
virtual void fileChunkSending(UInt8 mark, const UInt8* data) = 0;
|
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize) = 0;
|
||||||
virtual CString getName() const;
|
virtual CString getName() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -89,7 +89,7 @@ public:
|
||||||
virtual void gameDeviceTriggers(GameDeviceID id, UInt8 t1, UInt8 t2) = 0;
|
virtual void gameDeviceTriggers(GameDeviceID id, UInt8 t1, UInt8 t2) = 0;
|
||||||
virtual void gameDeviceTimingReq() = 0;
|
virtual void gameDeviceTimingReq() = 0;
|
||||||
virtual void cryptoIv(const UInt8* iv) = 0;
|
virtual void cryptoIv(const UInt8* iv) = 0;
|
||||||
virtual void fileChunkSending(UInt8 mark, const UInt8* data) = 0;
|
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
synergy::IStream* m_stream;
|
synergy::IStream* m_stream;
|
||||||
|
|
|
@ -394,7 +394,7 @@ CClientProxy1_0::cryptoIv(const UInt8* iv)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CClientProxy1_0::fileChunkSending(UInt8 mark, const UInt8* iv)
|
CClientProxy1_0::fileChunkSending(UInt8 mark, char* data, size_t dataSize)
|
||||||
{
|
{
|
||||||
// ignore -- not supported in protocol 1.0
|
// ignore -- not supported in protocol 1.0
|
||||||
LOG((CLOG_DEBUG "fileChunkSending not supported"));
|
LOG((CLOG_DEBUG "fileChunkSending not supported"));
|
||||||
|
|
|
@ -64,7 +64,7 @@ public:
|
||||||
virtual void gameDeviceTriggers(GameDeviceID id, UInt8 t1, UInt8 t2);
|
virtual void gameDeviceTriggers(GameDeviceID id, UInt8 t1, UInt8 t2);
|
||||||
virtual void gameDeviceTimingReq();
|
virtual void gameDeviceTimingReq();
|
||||||
virtual void cryptoIv(const UInt8* iv);
|
virtual void cryptoIv(const UInt8* iv);
|
||||||
virtual void fileChunkSending(UInt8 mark, const UInt8* data);
|
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool parseHandshakeMessage(const UInt8* code);
|
virtual bool parseHandshakeMessage(const UInt8* code);
|
||||||
|
|
|
@ -42,7 +42,6 @@ protected:
|
||||||
private:
|
private:
|
||||||
void handleKeepAlive(const CEvent&, void*);
|
void handleKeepAlive(const CEvent&, void*);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double m_keepAliveRate;
|
double m_keepAliveRate;
|
||||||
CEventQueueTimer* m_keepAliveTimer;
|
CEventQueueTimer* m_keepAliveTimer;
|
||||||
|
|
|
@ -29,6 +29,14 @@ public:
|
||||||
CClientProxy1_4(const CString& name, synergy::IStream* adoptedStream, CServer* server, IEventQueue* events);
|
CClientProxy1_4(const CString& name, synergy::IStream* adoptedStream, CServer* server, IEventQueue* events);
|
||||||
~CClientProxy1_4();
|
~CClientProxy1_4();
|
||||||
|
|
||||||
|
//! @name accessors
|
||||||
|
//@{
|
||||||
|
|
||||||
|
//! get server pointer
|
||||||
|
CServer* getServer() { return m_server; }
|
||||||
|
|
||||||
|
//@}
|
||||||
|
|
||||||
// IClient overrides
|
// IClient overrides
|
||||||
virtual void gameDeviceButtons(GameDeviceID id, GameDeviceButton buttons);
|
virtual void gameDeviceButtons(GameDeviceID id, GameDeviceButton buttons);
|
||||||
virtual void gameDeviceSticks(GameDeviceID id, SInt16 x1, SInt16 y1, SInt16 x2, SInt16 y2);
|
virtual void gameDeviceSticks(GameDeviceID id, SInt16 x1, SInt16 y1, SInt16 x2, SInt16 y2);
|
||||||
|
|
|
@ -19,13 +19,15 @@
|
||||||
#include "CProtocolUtil.h"
|
#include "CProtocolUtil.h"
|
||||||
#include "CLog.h"
|
#include "CLog.h"
|
||||||
#include "IStream.h"
|
#include "IStream.h"
|
||||||
|
#include "CServer.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
// CClientProxy1_5
|
// CClientProxy1_5
|
||||||
//
|
//
|
||||||
|
|
||||||
CClientProxy1_5::CClientProxy1_5(const CString& name, synergy::IStream* stream, CServer* server, IEventQueue* events) :
|
CClientProxy1_5::CClientProxy1_5(const CString& name, synergy::IStream* stream, CServer* server, IEventQueue* events) :
|
||||||
CClientProxy1_4(name, stream, server, events)
|
CClientProxy1_4(name, stream, server, events),
|
||||||
|
m_events(events)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,23 +36,64 @@ CClientProxy1_5::~CClientProxy1_5()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CClientProxy1_5::fileChunkSending(UInt8 mark, const UInt8* data)
|
CClientProxy1_5::fileChunkSending(UInt8 mark, char* data, size_t dataSize)
|
||||||
{
|
{
|
||||||
CString chunk(reinterpret_cast<const char*>(data));
|
CString chunk(data, dataSize);
|
||||||
|
|
||||||
switch (mark) {
|
switch (mark) {
|
||||||
case '0':
|
case kFileStart:
|
||||||
LOG((CLOG_DEBUG2 "file sending start: file size = %s", data));
|
LOG((CLOG_DEBUG2 "file sending start: size=%s", data));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '1':
|
case kFileChunk:
|
||||||
LOG((CLOG_DEBUG2 "file chunk sending: %s", data));
|
LOG((CLOG_DEBUG2 "file chunk sending: size=%i", chunk.size()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '2':
|
case kFileEnd:
|
||||||
LOG((CLOG_DEBUG2 "file sending finished"));
|
LOG((CLOG_DEBUG2 "file sending finished"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
CProtocolUtil::writef(getStream(), kMsgDFileTransfer, mark, &chunk);
|
CProtocolUtil::writef(getStream(), kMsgDFileTransfer, mark, &chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CClientProxy1_5::parseMessage(const UInt8* code)
|
||||||
|
{
|
||||||
|
if (memcmp(code, kMsgDFileTransfer, 4) == 0) {
|
||||||
|
fileChunkReceived();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return CClientProxy1_4::parseMessage(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CClientProxy1_5::fileChunkReceived()
|
||||||
|
{
|
||||||
|
// parse
|
||||||
|
UInt8 mark;
|
||||||
|
CString content;
|
||||||
|
CProtocolUtil::readf(getStream(), kMsgDFileTransfer + 4, &mark, &content);
|
||||||
|
|
||||||
|
CServer* server = getServer();
|
||||||
|
switch (mark) {
|
||||||
|
case kFileStart:
|
||||||
|
LOG((CLOG_DEBUG2 "recv file data from client: file size=%s", content.c_str()));
|
||||||
|
server->clearReceivedFileData();
|
||||||
|
server->setExpectedFileSize(content);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kFileChunk:
|
||||||
|
LOG((CLOG_DEBUG2 "recv file data from client: chunck size=%i", content.size()));
|
||||||
|
server->fileChunkReceived(content);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kFileEnd:
|
||||||
|
LOG((CLOG_DEBUG2 "file data transfer finished"));
|
||||||
|
m_events->addEvent(CEvent(m_events->forIScreen().fileRecieveComplete(), server));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -28,5 +28,10 @@ public:
|
||||||
CClientProxy1_5(const CString& name, synergy::IStream* adoptedStream, CServer* server, IEventQueue* events);
|
CClientProxy1_5(const CString& name, synergy::IStream* adoptedStream, CServer* server, IEventQueue* events);
|
||||||
~CClientProxy1_5();
|
~CClientProxy1_5();
|
||||||
|
|
||||||
virtual void fileChunkSending(UInt8 mark, const UInt8* data);
|
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize);
|
||||||
|
virtual bool parseMessage(const UInt8* code);
|
||||||
|
void fileChunkReceived();
|
||||||
|
|
||||||
|
private:
|
||||||
|
IEventQueue* m_events;
|
||||||
};
|
};
|
||||||
|
|
|
@ -274,7 +274,7 @@ CPrimaryClient::screensaver(bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CPrimaryClient::fileChunkSending(UInt8 mark, const UInt8* data)
|
CPrimaryClient::fileChunkSending(UInt8 mark, char* data, size_t dataSize)
|
||||||
{
|
{
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,7 +148,7 @@ public:
|
||||||
virtual void screensaver(bool activate);
|
virtual void screensaver(bool activate);
|
||||||
virtual void resetOptions();
|
virtual void resetOptions();
|
||||||
virtual void setOptions(const COptionsList& options);
|
virtual void setOptions(const COptionsList& options);
|
||||||
virtual void fileChunkSending(UInt8 mark, const UInt8* data);
|
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CScreen* m_screen;
|
CScreen* m_screen;
|
||||||
|
|
|
@ -33,14 +33,22 @@
|
||||||
#include "TMethodEventJob.h"
|
#include "TMethodEventJob.h"
|
||||||
#include "CArch.h"
|
#include "CArch.h"
|
||||||
#include "CKeyState.h"
|
#include "CKeyState.h"
|
||||||
|
#include "CScreen.h"
|
||||||
|
#include "CThread.h"
|
||||||
|
#include "TMethodJob.h"
|
||||||
|
#include "CFileChunker.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include "CScreen.h"
|
#include <sstream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
//
|
//
|
||||||
// CServer
|
// CServer
|
||||||
//
|
//
|
||||||
|
|
||||||
|
const size_t CServer::m_chunkSize = 1024 * 512; // 512kb
|
||||||
|
|
||||||
CServer::CServer(CConfig& config, CPrimaryClient* primaryClient, CScreen* screen, IEventQueue* events) :
|
CServer::CServer(CConfig& config, CPrimaryClient* primaryClient, CScreen* screen, IEventQueue* events) :
|
||||||
m_events(events),
|
m_events(events),
|
||||||
m_mock(false),
|
m_mock(false),
|
||||||
|
@ -177,6 +185,10 @@ CServer::CServer(CConfig& config, CPrimaryClient* primaryClient, CScreen* screen
|
||||||
this,
|
this,
|
||||||
new TMethodEventJob<CServer>(this,
|
new TMethodEventJob<CServer>(this,
|
||||||
&CServer::handleFileChunkSendingEvent));
|
&CServer::handleFileChunkSendingEvent));
|
||||||
|
m_events->adoptHandler(m_events->forIScreen().fileRecieveComplete(),
|
||||||
|
this,
|
||||||
|
new TMethodEventJob<CServer>(this,
|
||||||
|
&CServer::handleFileRecieveCompleteEvent));
|
||||||
|
|
||||||
// add connection
|
// add connection
|
||||||
addClient(m_primaryClient);
|
addClient(m_primaryClient);
|
||||||
|
@ -1516,8 +1528,13 @@ CServer::handleFakeInputEndEvent(const CEvent&, void*)
|
||||||
void
|
void
|
||||||
CServer::handleFileChunkSendingEvent(const CEvent& event, void*)
|
CServer::handleFileChunkSendingEvent(const CEvent& event, void*)
|
||||||
{
|
{
|
||||||
UInt8* data = reinterpret_cast<UInt8*>(event.getData());
|
onFileChunkSending(event.getData());
|
||||||
onFileChunkSending(data);
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CServer::handleFileRecieveCompleteEvent(const CEvent& event, void*)
|
||||||
|
{
|
||||||
|
onFileRecieveComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1981,13 +1998,32 @@ CServer::onGameDeviceTimingReq()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CServer::onFileChunkSending(const UInt8* data)
|
CServer::onFileChunkSending(const void* data)
|
||||||
{
|
{
|
||||||
|
CFileChunker::CFileChunk* fileChunk = reinterpret_cast<CFileChunker::CFileChunk*>(const_cast<void*>(data));
|
||||||
|
|
||||||
LOG((CLOG_DEBUG1 "onFileChunkSending"));
|
LOG((CLOG_DEBUG1 "onFileChunkSending"));
|
||||||
assert(m_active != NULL);
|
assert(m_active != NULL);
|
||||||
|
|
||||||
// relay
|
// relay
|
||||||
m_active->fileChunkSending(data[0], &data[1]);
|
m_active->fileChunkSending(fileChunk->m_chunk[0], &(fileChunk->m_chunk[1]), fileChunk->m_dataSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CServer::onFileRecieveComplete()
|
||||||
|
{
|
||||||
|
if (isReceivedFileSizeValid()) {
|
||||||
|
if (!m_fileTransferDes.empty()) {
|
||||||
|
std::fstream file;
|
||||||
|
file.open(m_fileTransferDes.c_str(), std::ios::out | std::ios::binary);
|
||||||
|
if (!file.is_open()) {
|
||||||
|
// TODO: file open failed
|
||||||
|
}
|
||||||
|
|
||||||
|
file.write(m_receivedFileData.c_str(), m_receivedFileData.size());
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -2260,3 +2296,49 @@ CServer::CKeyboardBroadcastInfo::alloc(State state, const CString& screens)
|
||||||
strcpy(info->m_screens, screens.c_str());
|
strcpy(info->m_screens, screens.c_str());
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CServer::clearReceivedFileData()
|
||||||
|
{
|
||||||
|
m_receivedFileData.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CServer::setExpectedFileSize(CString data)
|
||||||
|
{
|
||||||
|
std::istringstream iss(data);
|
||||||
|
iss >> m_expectedFileSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CServer::fileChunkReceived(CString data)
|
||||||
|
{
|
||||||
|
m_receivedFileData += data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CServer::isReceivedFileSizeValid()
|
||||||
|
{
|
||||||
|
return m_expectedFileSize == m_receivedFileData.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CServer::sendFileToClient(const char* filename)
|
||||||
|
{
|
||||||
|
CThread* thread = new CThread(
|
||||||
|
new TMethodJob<CServer>(
|
||||||
|
this, &CServer::sendFileThread,
|
||||||
|
reinterpret_cast<void*>(const_cast<char*>(filename))));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CServer::sendFileThread(void* filename)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
char* name = reinterpret_cast<char*>(filename);
|
||||||
|
CFileChunker::sendFileChunks(name, m_events, this);
|
||||||
|
}
|
||||||
|
catch (std::runtime_error error) {
|
||||||
|
LOG((CLOG_ERR "failed sending file chunks: %s", error.what()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -144,6 +144,21 @@ public:
|
||||||
//! Notify of game device feedback
|
//! Notify of game device feedback
|
||||||
void gameDeviceFeedback(GameDeviceID id, UInt16 m1, UInt16 m2);
|
void gameDeviceFeedback(GameDeviceID id, UInt16 m1, UInt16 m2);
|
||||||
|
|
||||||
|
//! Clears the file buffer
|
||||||
|
void clearReceivedFileData();
|
||||||
|
|
||||||
|
//! Set the expected size of receiving file
|
||||||
|
void setExpectedFileSize(CString data);
|
||||||
|
|
||||||
|
//! Set
|
||||||
|
void setFileTransferDes(CString& des) { m_fileTransferDes = des; }
|
||||||
|
|
||||||
|
//! Received a chunk of file data
|
||||||
|
void fileChunkReceived(CString data);
|
||||||
|
|
||||||
|
//! Create a new thread and use it to send file to client
|
||||||
|
void sendFileToClient(const char* filename);
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
//! @name accessors
|
//! @name accessors
|
||||||
//@{
|
//@{
|
||||||
|
@ -159,6 +174,9 @@ public:
|
||||||
Set the \c list to the names of the currently connected clients.
|
Set the \c list to the names of the currently connected clients.
|
||||||
*/
|
*/
|
||||||
void getClients(std::vector<CString>& list) const;
|
void getClients(std::vector<CString>& list) const;
|
||||||
|
|
||||||
|
//! Return true if recieved file size is valid
|
||||||
|
bool isReceivedFileSizeValid();
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
|
@ -299,6 +317,7 @@ private:
|
||||||
void handleFakeInputBeginEvent(const CEvent&, void*);
|
void handleFakeInputBeginEvent(const CEvent&, void*);
|
||||||
void handleFakeInputEndEvent(const CEvent&, void*);
|
void handleFakeInputEndEvent(const CEvent&, void*);
|
||||||
void handleFileChunkSendingEvent(const CEvent&, void*);
|
void handleFileChunkSendingEvent(const CEvent&, void*);
|
||||||
|
void handleFileRecieveCompleteEvent(const CEvent&, void*);
|
||||||
|
|
||||||
// event processing
|
// event processing
|
||||||
void onClipboardChanged(CBaseClientProxy* sender,
|
void onClipboardChanged(CBaseClientProxy* sender,
|
||||||
|
@ -318,7 +337,8 @@ private:
|
||||||
void onGameDeviceSticks(GameDeviceID id, SInt16 x1, SInt16 y1, SInt16 x2, SInt16 y2);
|
void onGameDeviceSticks(GameDeviceID id, SInt16 x1, SInt16 y1, SInt16 x2, SInt16 y2);
|
||||||
void onGameDeviceTriggers(GameDeviceID id, UInt8 t1, UInt8 t2);
|
void onGameDeviceTriggers(GameDeviceID id, UInt8 t1, UInt8 t2);
|
||||||
void onGameDeviceTimingReq();
|
void onGameDeviceTimingReq();
|
||||||
void onFileChunkSending(const UInt8* data);
|
void onFileChunkSending(const void* data);
|
||||||
|
void onFileRecieveComplete();
|
||||||
|
|
||||||
// add client to list and attach event handlers for client
|
// add client to list and attach event handlers for client
|
||||||
bool addClient(CBaseClientProxy*);
|
bool addClient(CBaseClientProxy*);
|
||||||
|
@ -343,6 +363,9 @@ private:
|
||||||
// force the cursor off of \p client
|
// force the cursor off of \p client
|
||||||
void forceLeaveClient(CBaseClientProxy* client);
|
void forceLeaveClient(CBaseClientProxy* client);
|
||||||
|
|
||||||
|
// thread funciton for sending file
|
||||||
|
void sendFileThread(void*);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool m_mock;
|
bool m_mock;
|
||||||
|
|
||||||
|
@ -438,6 +461,13 @@ private:
|
||||||
CScreen* m_screen;
|
CScreen* m_screen;
|
||||||
|
|
||||||
IEventQueue* m_events;
|
IEventQueue* m_events;
|
||||||
|
|
||||||
|
// file transfer
|
||||||
|
size_t m_expectedFileSize;
|
||||||
|
CString m_receivedFileData;
|
||||||
|
static const size_t m_chunkSize;
|
||||||
|
CString m_fileTransferSrc;
|
||||||
|
CString m_fileTransferDes;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -170,6 +170,14 @@ CApp::parseArg(const int& argc, const char* const* argv, int& i)
|
||||||
else if (isArg(i, argc, argv, NULL, "--crypto-mode")) {
|
else if (isArg(i, argc, argv, NULL, "--crypto-mode")) {
|
||||||
argsBase().m_crypto.setMode(argv[++i]);
|
argsBase().m_crypto.setMode(argv[++i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (isArg(i, argc, argv, NULL, "--filetransfer-src")) {
|
||||||
|
m_fileTransferSrc = argv[++i];
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (isArg(i, argc, argv, NULL, "--filetransfer-des")) {
|
||||||
|
m_fileTransferDes = argv[++i];
|
||||||
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
// option not supported here
|
// option not supported here
|
||||||
|
|
|
@ -101,6 +101,9 @@ public:
|
||||||
void setSocketMultiplexer(CSocketMultiplexer* sm) { m_socketMultiplexer = sm; }
|
void setSocketMultiplexer(CSocketMultiplexer* sm) { m_socketMultiplexer = sm; }
|
||||||
CSocketMultiplexer* getSocketMultiplexer() const { return m_socketMultiplexer; }
|
CSocketMultiplexer* getSocketMultiplexer() const { return m_socketMultiplexer; }
|
||||||
|
|
||||||
|
CString& getFileTransferSrc() { return m_fileTransferSrc; }
|
||||||
|
CString& getFileTransferDes() { return m_fileTransferDes; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleIpcMessage(const CEvent&, void*);
|
void handleIpcMessage(const CEvent&, void*);
|
||||||
|
|
||||||
|
@ -122,6 +125,8 @@ private:
|
||||||
CIpcClient* m_ipcClient;
|
CIpcClient* m_ipcClient;
|
||||||
IEventQueue* m_events;
|
IEventQueue* m_events;
|
||||||
CSocketMultiplexer* m_socketMultiplexer;
|
CSocketMultiplexer* m_socketMultiplexer;
|
||||||
|
CString m_fileTransferSrc;
|
||||||
|
CString m_fileTransferDes;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define BYE "\nTry `%s --help' for more information."
|
#define BYE "\nTry `%s --help' for more information."
|
||||||
|
|
|
@ -349,6 +349,14 @@ CClientApp::handleClientConnected(const CEvent&, void*)
|
||||||
LOG((CLOG_NOTE "connected to server"));
|
LOG((CLOG_NOTE "connected to server"));
|
||||||
resetRestartTimeout();
|
resetRestartTimeout();
|
||||||
updateStatus();
|
updateStatus();
|
||||||
|
|
||||||
|
/*
|
||||||
|
// TODO: remove testing code for relase
|
||||||
|
CString fileFullDir = getFileTransferSrc();
|
||||||
|
if (!fileFullDir.empty()) {
|
||||||
|
s_client->sendFileToServer(getFileTransferSrc().c_str());
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -473,6 +481,7 @@ CClientApp::startClient()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
s_client->connect();
|
s_client->connect();
|
||||||
|
|
||||||
updateStatus();
|
updateStatus();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2013 Bolton Software 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 "CFileChunker.h"
|
||||||
|
#include "BasicTypes.h"
|
||||||
|
#include "ProtocolTypes.h"
|
||||||
|
#include "CEvent.h"
|
||||||
|
#include "IEventQueue.h"
|
||||||
|
#include "CEventTypes.h"
|
||||||
|
#include "CLOG.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
const size_t CFileChunker::m_chunkSize = 512 * 1024; // 512kb
|
||||||
|
|
||||||
|
void
|
||||||
|
CFileChunker::sendFileChunks(char* filename, IEventQueue* events, void* eventTarget)
|
||||||
|
{
|
||||||
|
std::fstream file(reinterpret_cast<char*>(filename), std::ios::in | std::ios::binary);
|
||||||
|
|
||||||
|
if (!file.is_open()) {
|
||||||
|
throw runtime_error("failed to open file");
|
||||||
|
}
|
||||||
|
|
||||||
|
// check file size
|
||||||
|
file.seekg (0, std::ios::end);
|
||||||
|
size_t size = (size_t)file.tellg();
|
||||||
|
|
||||||
|
// send first message (file size)
|
||||||
|
CString fileSize = intToString(size);
|
||||||
|
UInt32 sizeLength = fileSize.size();
|
||||||
|
CFileChunk* sizeMessage = new CFileChunk(sizeLength + 2);
|
||||||
|
char* chunkData = sizeMessage->m_chunk;
|
||||||
|
|
||||||
|
chunkData[0] = kFileStart;
|
||||||
|
memcpy(&chunkData[1], fileSize.c_str(), sizeLength);
|
||||||
|
chunkData[sizeLength + 1] = '\0';
|
||||||
|
events->addEvent(CEvent(events->forIScreen().fileChunkSending(), eventTarget, sizeMessage));
|
||||||
|
|
||||||
|
// send chunk messages with a fixed chunk size
|
||||||
|
size_t sentLength = 0;
|
||||||
|
size_t chunkSize = m_chunkSize;
|
||||||
|
file.seekg (0, std::ios::beg);
|
||||||
|
while (true) {
|
||||||
|
// make sure we don't read too much from the mock data.
|
||||||
|
if (sentLength + chunkSize > size) {
|
||||||
|
chunkSize = size - sentLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for fileChunk->m_chunk, the first byte is the chunk mark, last is \0
|
||||||
|
CFileChunk* fileChunk = new CFileChunk(chunkSize + 2);
|
||||||
|
char* chunkData = fileChunk->m_chunk;
|
||||||
|
|
||||||
|
chunkData[0] = kFileChunk;
|
||||||
|
file.read(&chunkData[1], chunkSize);
|
||||||
|
chunkData[chunkSize + 1] = '\0';
|
||||||
|
events->addEvent(CEvent(events->forIScreen().fileChunkSending(), eventTarget, fileChunk));
|
||||||
|
|
||||||
|
sentLength += chunkSize;
|
||||||
|
file.seekg (sentLength, std::ios::beg);
|
||||||
|
|
||||||
|
if (sentLength == size) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// send last message
|
||||||
|
CFileChunk* transferFinished = new CFileChunk(2);
|
||||||
|
chunkData = transferFinished->m_chunk;
|
||||||
|
|
||||||
|
chunkData[0] = kFileEnd;
|
||||||
|
chunkData[1] = '\0';
|
||||||
|
events->addEvent(CEvent(events->forIScreen().fileChunkSending(), eventTarget, transferFinished));
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
CString
|
||||||
|
CFileChunker::intToString(size_t i)
|
||||||
|
{
|
||||||
|
stringstream ss;
|
||||||
|
ss << i;
|
||||||
|
return ss.str();
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2013 Bolton Software 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 "CString.h"
|
||||||
|
|
||||||
|
class IEventQueue;
|
||||||
|
|
||||||
|
class CFileChunker {
|
||||||
|
public:
|
||||||
|
//! FileChunk data
|
||||||
|
class CFileChunk {
|
||||||
|
public:
|
||||||
|
CFileChunk(size_t chunkSize) : m_dataSize(chunkSize - 2)
|
||||||
|
{
|
||||||
|
m_chunk = new char[chunkSize];
|
||||||
|
}
|
||||||
|
|
||||||
|
~CFileChunk() { delete[] m_chunk; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
const size_t m_dataSize;
|
||||||
|
char* m_chunk;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void sendFileChunks(char* filename, IEventQueue* events, void* eventTarget);
|
||||||
|
static CString intToString(size_t i);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const size_t m_chunkSize;
|
||||||
|
};
|
|
@ -49,6 +49,7 @@ set(inc
|
||||||
CArgsBase.h
|
CArgsBase.h
|
||||||
IAppUtil.h
|
IAppUtil.h
|
||||||
CEventGameDevice.h
|
CEventGameDevice.h
|
||||||
|
CFileChunker.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(src
|
set(src
|
||||||
|
@ -74,23 +75,24 @@ set(src
|
||||||
XSynergy.cpp
|
XSynergy.cpp
|
||||||
CDaemonApp.cpp
|
CDaemonApp.cpp
|
||||||
CAppUtil.cpp
|
CAppUtil.cpp
|
||||||
CArgsBase.cpp
|
CArgsBase.cpp
|
||||||
CEventGameDevice.cpp
|
CEventGameDevice.cpp
|
||||||
CGameDevice.cpp
|
CGameDevice.cpp
|
||||||
)
|
CFileChunker.cpp
|
||||||
|
)
|
||||||
if (WIN32)
|
|
||||||
|
if (WIN32)
|
||||||
list(APPEND inc
|
list(APPEND inc
|
||||||
CAppUtilWindows.h
|
CAppUtilWindows.h
|
||||||
CGameDevice.h
|
CGameDevice.h
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND src
|
list(APPEND src
|
||||||
${inc}
|
${inc}
|
||||||
CAppUtilWindows.cpp
|
CAppUtilWindows.cpp
|
||||||
)
|
)
|
||||||
elseif(UNIX)
|
elseif(UNIX)
|
||||||
list(APPEND src
|
list(APPEND src
|
||||||
CAppUtilUnix.cpp
|
CAppUtilUnix.cpp
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -228,7 +228,12 @@ CProtocolUtil::vreadf(synergy::IStream* stream, const char* fmt, va_list args)
|
||||||
}
|
}
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
LOG((CLOG_DEBUG2 "readf: read %d byte string: %.*s", len, len, sBuffer));
|
|
||||||
|
// don't cause buffer overrun, using +100 chars in case
|
||||||
|
// someone modifies this log message in future.
|
||||||
|
if (len + 100 < kLogMessageLength) {
|
||||||
|
LOG((CLOG_DEBUG2 "readf: read %d byte string: %.*s", len, len, sBuffer));
|
||||||
|
}
|
||||||
|
|
||||||
// save the data
|
// save the data
|
||||||
CString* dst = va_arg(args, CString*);
|
CString* dst = va_arg(args, CString*);
|
||||||
|
|
|
@ -688,7 +688,7 @@ CServer*
|
||||||
CServerApp::openServer(CConfig& config, CPrimaryClient* primaryClient)
|
CServerApp::openServer(CConfig& config, CPrimaryClient* primaryClient)
|
||||||
{
|
{
|
||||||
CServer* server = new CServer(config, primaryClient, s_serverScreen, m_events);
|
CServer* server = new CServer(config, primaryClient, s_serverScreen, m_events);
|
||||||
|
server->setFileTransferDes(getFileTransferDes());
|
||||||
try {
|
try {
|
||||||
m_events->adoptHandler(
|
m_events->adoptHandler(
|
||||||
m_events->forCServer().disconnected(), server,
|
m_events->forCServer().disconnected(), server,
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
This interface defines the methods common to all platform dependent
|
This interface defines the methods common to all platform dependent
|
||||||
primary screen implementations.
|
primary screen implementations.
|
||||||
*/
|
*/
|
||||||
class IPrimaryScreen : public IInterface {
|
class IPrimaryScreen : public IInterface {
|
||||||
public:
|
public:
|
||||||
//! Button event data
|
//! Button event data
|
||||||
class CButtonInfo {
|
class CButtonInfo {
|
||||||
|
|
|
@ -30,7 +30,7 @@ class IClipboard;
|
||||||
/*!
|
/*!
|
||||||
This interface defines the methods common to all screens.
|
This interface defines the methods common to all screens.
|
||||||
*/
|
*/
|
||||||
class IScreen : public IInterface {
|
class IScreen : public IInterface {
|
||||||
public:
|
public:
|
||||||
struct CClipboardInfo {
|
struct CClipboardInfo {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -68,6 +68,13 @@ enum EDirectionMask {
|
||||||
kBottomMask = 1 << kBottom
|
kBottomMask = 1 << kBottom
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// file transfer constants
|
||||||
|
enum EFileTransfer {
|
||||||
|
kFileStart = 1,
|
||||||
|
kFileChunk = 2,
|
||||||
|
kFileEnd = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// message codes (trailing NUL is not part of code). in comments, $n
|
// message codes (trailing NUL is not part of code). in comments, $n
|
||||||
|
|
|
@ -1,420 +1,420 @@
|
||||||
/*
|
/*
|
||||||
uSynergy client -- Interface for the embedded Synergy client library
|
uSynergy client -- Interface for the embedded Synergy client library
|
||||||
version 1.0.0, July 7th, 2012
|
version 1.0.0, July 7th, 2012
|
||||||
|
|
||||||
Copyright (C) 2012 Bolton Software Ltd.
|
Copyright (C) 2012 Bolton Software Ltd.
|
||||||
Copyright (c) 2012 Alex Evans
|
Copyright (c) 2012 Alex Evans
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
claim that you wrote the original software. If you use this software
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*/
|
*/
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
// Configuration
|
// Configuration
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Determine endianness
|
@brief Determine endianness
|
||||||
**/
|
**/
|
||||||
#if defined(USYNERGY_LITTLE_ENDIAN) && defined(USYNERGY_BIG_ENDIAN)
|
#if defined(USYNERGY_LITTLE_ENDIAN) && defined(USYNERGY_BIG_ENDIAN)
|
||||||
/* Ambiguous: both endians specified */
|
/* Ambiguous: both endians specified */
|
||||||
#error "Can't define both USYNERGY_LITTLE_ENDIAN and USYNERGY_BIG_ENDIAN"
|
#error "Can't define both USYNERGY_LITTLE_ENDIAN and USYNERGY_BIG_ENDIAN"
|
||||||
#elif !defined(USYNERGY_LITTLE_ENDIAN) && !defined(USYNERGY_BIG_ENDIAN)
|
#elif !defined(USYNERGY_LITTLE_ENDIAN) && !defined(USYNERGY_BIG_ENDIAN)
|
||||||
/* Attempt to auto detect */
|
/* Attempt to auto detect */
|
||||||
#if defined(__LITTLE_ENDIAN__) || defined(LITTLE_ENDIAN) || (_BYTE_ORDER == _LITTLE_ENDIAN)
|
#if defined(__LITTLE_ENDIAN__) || defined(LITTLE_ENDIAN) || (_BYTE_ORDER == _LITTLE_ENDIAN)
|
||||||
#define USYNERGY_LITTLE_ENDIAN
|
#define USYNERGY_LITTLE_ENDIAN
|
||||||
#elif defined(__BIG_ENDIAN__) || defined(BIG_ENDIAN) || (_BYTE_ORDER == _BIG_ENDIAN)
|
#elif defined(__BIG_ENDIAN__) || defined(BIG_ENDIAN) || (_BYTE_ORDER == _BIG_ENDIAN)
|
||||||
#define USYNERGY_BIG_ENDIAN
|
#define USYNERGY_BIG_ENDIAN
|
||||||
#else
|
#else
|
||||||
#error "Can't detect endian-nes, please defined either USYNERGY_LITTLE_ENDIAN or USYNERGY_BIG_ENDIAN";
|
#error "Can't detect endian-nes, please defined either USYNERGY_LITTLE_ENDIAN or USYNERGY_BIG_ENDIAN";
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
/* User-specified endian-nes, nothing to do for us */
|
/* User-specified endian-nes, nothing to do for us */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
// Types and Constants
|
// Types and Constants
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Boolean type
|
@brief Boolean type
|
||||||
**/
|
**/
|
||||||
typedef int uSynergyBool;
|
typedef int uSynergyBool;
|
||||||
#define USYNERGY_FALSE 0 /* False value */
|
#define USYNERGY_FALSE 0 /* False value */
|
||||||
#define USYNERGY_TRUE 1 /* True value */
|
#define USYNERGY_TRUE 1 /* True value */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief User context type
|
@brief User context type
|
||||||
|
|
||||||
The uSynergyCookie type is an opaque type that is used by uSynergy to communicate to the client. It is passed along to
|
The uSynergyCookie type is an opaque type that is used by uSynergy to communicate to the client. It is passed along to
|
||||||
callback functions as context.
|
callback functions as context.
|
||||||
**/
|
**/
|
||||||
typedef struct { int ignored; } * uSynergyCookie;
|
typedef struct { int ignored; } * uSynergyCookie;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Clipboard types
|
@brief Clipboard types
|
||||||
**/
|
**/
|
||||||
enum uSynergyClipboardFormat
|
enum uSynergyClipboardFormat
|
||||||
{
|
{
|
||||||
USYNERGY_CLIPBOARD_FORMAT_TEXT = 0, /* Text format, UTF-8, newline is LF */
|
USYNERGY_CLIPBOARD_FORMAT_TEXT = 0, /* Text format, UTF-8, newline is LF */
|
||||||
USYNERGY_CLIPBOARD_FORMAT_BITMAP = 1, /* Bitmap format, BMP 24/32bpp, BI_RGB */
|
USYNERGY_CLIPBOARD_FORMAT_BITMAP = 1, /* Bitmap format, BMP 24/32bpp, BI_RGB */
|
||||||
USYNERGY_CLIPBOARD_FORMAT_HTML = 2, /* HTML format, HTML fragment, UTF-8, newline is LF */
|
USYNERGY_CLIPBOARD_FORMAT_HTML = 2, /* HTML format, HTML fragment, UTF-8, newline is LF */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Constants and limits
|
@brief Constants and limits
|
||||||
**/
|
**/
|
||||||
#define USYNERGY_NUM_JOYSTICKS 4 /* Maximum number of supported joysticks */
|
#define USYNERGY_NUM_JOYSTICKS 4 /* Maximum number of supported joysticks */
|
||||||
|
|
||||||
#define USYNERGY_PROTOCOL_MAJOR 1 /* Major protocol version */
|
#define USYNERGY_PROTOCOL_MAJOR 1 /* Major protocol version */
|
||||||
#define USYNERGY_PROTOCOL_MINOR 4 /* Minor protocol version */
|
#define USYNERGY_PROTOCOL_MINOR 4 /* Minor protocol version */
|
||||||
|
|
||||||
#define USYNERGY_IDLE_TIMEOUT 2000 /* Timeout in milliseconds before reconnecting */
|
#define USYNERGY_IDLE_TIMEOUT 2000 /* Timeout in milliseconds before reconnecting */
|
||||||
|
|
||||||
#define USYNERGY_TRACE_BUFFER_SIZE 1024 /* Maximum length of traced message */
|
#define USYNERGY_TRACE_BUFFER_SIZE 1024 /* Maximum length of traced message */
|
||||||
#define USYNERGY_REPLY_BUFFER_SIZE 1024 /* Maximum size of a reply packet */
|
#define USYNERGY_REPLY_BUFFER_SIZE 1024 /* Maximum size of a reply packet */
|
||||||
#define USYNERGY_RECEIVE_BUFFER_SIZE 4096 /* Maximum size of an incoming packet */
|
#define USYNERGY_RECEIVE_BUFFER_SIZE 4096 /* Maximum size of an incoming packet */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Keyboard constants
|
@brief Keyboard constants
|
||||||
**/
|
**/
|
||||||
#define USYNERGY_MODIFIER_SHIFT 0x0001 /* Shift key modifier */
|
#define USYNERGY_MODIFIER_SHIFT 0x0001 /* Shift key modifier */
|
||||||
#define USYNERGY_MODIFIER_CTRL 0x0002 /* Ctrl key modifier */
|
#define USYNERGY_MODIFIER_CTRL 0x0002 /* Ctrl key modifier */
|
||||||
#define USYNERGY_MODIFIER_ALT 0x0004 /* Alt key modifier */
|
#define USYNERGY_MODIFIER_ALT 0x0004 /* Alt key modifier */
|
||||||
#define USYNERGY_MODIFIER_META 0x0008 /* Meta key modifier */
|
#define USYNERGY_MODIFIER_META 0x0008 /* Meta key modifier */
|
||||||
#define USYNERGY_MODIFIER_WIN 0x0010 /* Windows key modifier */
|
#define USYNERGY_MODIFIER_WIN 0x0010 /* Windows key modifier */
|
||||||
#define USYNERGY_MODIFIER_ALT_GR 0x0020 /* AltGr key modifier */
|
#define USYNERGY_MODIFIER_ALT_GR 0x0020 /* AltGr key modifier */
|
||||||
#define USYNERGY_MODIFIER_LEVEL5LOCK 0x0040 /* Level5Lock key modifier */
|
#define USYNERGY_MODIFIER_LEVEL5LOCK 0x0040 /* Level5Lock key modifier */
|
||||||
#define USYNERGY_MODIFIER_CAPSLOCK 0x1000 /* CapsLock key modifier */
|
#define USYNERGY_MODIFIER_CAPSLOCK 0x1000 /* CapsLock key modifier */
|
||||||
#define USYNERGY_MODIFIER_NUMLOCK 0x2000 /* NumLock key modifier */
|
#define USYNERGY_MODIFIER_NUMLOCK 0x2000 /* NumLock key modifier */
|
||||||
#define USYNERGY_MODIFIER_SCROLLOCK 0x4000 /* ScrollLock key modifier */
|
#define USYNERGY_MODIFIER_SCROLLOCK 0x4000 /* ScrollLock key modifier */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
// Functions and Callbacks
|
// Functions and Callbacks
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Connect function
|
@brief Connect function
|
||||||
|
|
||||||
This function is called when uSynergy needs to connect to the host. It doesn't imply a network implementation or
|
This function is called when uSynergy needs to connect to the host. It doesn't imply a network implementation or
|
||||||
destination address, that must all be handled on the user side. The function should return USYNERGY_TRUE if a
|
destination address, that must all be handled on the user side. The function should return USYNERGY_TRUE if a
|
||||||
connection was established or USYNERGY_FALSE if it could not connect.
|
connection was established or USYNERGY_FALSE if it could not connect.
|
||||||
|
|
||||||
When network errors occur (e.g. uSynergySend or uSynergyReceive fail) then the connect call will be called again
|
When network errors occur (e.g. uSynergySend or uSynergyReceive fail) then the connect call will be called again
|
||||||
so the implementation of the function must close any old connections and clean up resources before retrying.
|
so the implementation of the function must close any old connections and clean up resources before retrying.
|
||||||
|
|
||||||
@param cookie Cookie supplied in the Synergy context
|
@param cookie Cookie supplied in the Synergy context
|
||||||
**/
|
**/
|
||||||
typedef uSynergyBool (*uSynergyConnectFunc)(uSynergyCookie cookie);
|
typedef uSynergyBool (*uSynergyConnectFunc)(uSynergyCookie cookie);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Send function
|
@brief Send function
|
||||||
|
|
||||||
This function is called when uSynergy needs to send something over the default connection. It should return
|
This function is called when uSynergy needs to send something over the default connection. It should return
|
||||||
USYNERGY_TRUE if sending succeeded and USYNERGY_FALSE otherwise. This function should block until the send
|
USYNERGY_TRUE if sending succeeded and USYNERGY_FALSE otherwise. This function should block until the send
|
||||||
operation is completed.
|
operation is completed.
|
||||||
|
|
||||||
@param cookie Cookie supplied in the Synergy context
|
@param cookie Cookie supplied in the Synergy context
|
||||||
@param buffer Address of buffer to send
|
@param buffer Address of buffer to send
|
||||||
@param length Length of buffer to send
|
@param length Length of buffer to send
|
||||||
**/
|
**/
|
||||||
typedef uSynergyBool (*uSynergySendFunc)(uSynergyCookie cookie, const uint8_t *buffer, int length);
|
typedef uSynergyBool (*uSynergySendFunc)(uSynergyCookie cookie, const uint8_t *buffer, int length);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Receive function
|
@brief Receive function
|
||||||
|
|
||||||
This function is called when uSynergy needs to receive data from the default connection. It should return
|
This function is called when uSynergy needs to receive data from the default connection. It should return
|
||||||
USYNERGY_TRUE if receiving data succeeded and USYNERGY_FALSE otherwise. This function should block until data
|
USYNERGY_TRUE if receiving data succeeded and USYNERGY_FALSE otherwise. This function should block until data
|
||||||
has been received and wait for data to become available. If @a outLength is set to 0 upon completion it is
|
has been received and wait for data to become available. If @a outLength is set to 0 upon completion it is
|
||||||
assumed that the connection is alive, but still in a connecting state and needs time to settle.
|
assumed that the connection is alive, but still in a connecting state and needs time to settle.
|
||||||
|
|
||||||
@param cookie Cookie supplied in the Synergy context
|
@param cookie Cookie supplied in the Synergy context
|
||||||
@param buffer Address of buffer to receive data into
|
@param buffer Address of buffer to receive data into
|
||||||
@param maxLength Maximum amount of bytes to write into the receive buffer
|
@param maxLength Maximum amount of bytes to write into the receive buffer
|
||||||
@param outLength Address of integer that receives the actual amount of bytes written into @a buffer
|
@param outLength Address of integer that receives the actual amount of bytes written into @a buffer
|
||||||
**/
|
**/
|
||||||
typedef uSynergyBool (*uSynergyReceiveFunc)(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength);
|
typedef uSynergyBool (*uSynergyReceiveFunc)(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Thread sleep function
|
@brief Thread sleep function
|
||||||
|
|
||||||
This function is called when uSynergy wants to suspend operation for a while before retrying an operation. It
|
This function is called when uSynergy wants to suspend operation for a while before retrying an operation. It
|
||||||
is mostly used when a socket times out or disconnect occurs to prevent uSynergy from continuously hammering a
|
is mostly used when a socket times out or disconnect occurs to prevent uSynergy from continuously hammering a
|
||||||
network connection in case the network is down.
|
network connection in case the network is down.
|
||||||
|
|
||||||
@param cookie Cookie supplied in the Synergy context
|
@param cookie Cookie supplied in the Synergy context
|
||||||
@param timeMs Time to sleep the current thread (in milliseconds)
|
@param timeMs Time to sleep the current thread (in milliseconds)
|
||||||
**/
|
**/
|
||||||
typedef void (*uSynergySleepFunc)(uSynergyCookie cookie, int timeMs);
|
typedef void (*uSynergySleepFunc)(uSynergyCookie cookie, int timeMs);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Get time function
|
@brief Get time function
|
||||||
|
|
||||||
This function is called when uSynergy needs to know the current time. This is used to determine when timeouts
|
This function is called when uSynergy needs to know the current time. This is used to determine when timeouts
|
||||||
have occured. The time base should be a cyclic millisecond time value.
|
have occured. The time base should be a cyclic millisecond time value.
|
||||||
|
|
||||||
@returns Time value in milliseconds
|
@returns Time value in milliseconds
|
||||||
**/
|
**/
|
||||||
typedef uint32_t (*uSynergyGetTimeFunc)();
|
typedef uint32_t (*uSynergyGetTimeFunc)();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Trace function
|
@brief Trace function
|
||||||
|
|
||||||
This function is called when uSynergy wants to trace something. It is optional to show these messages, but they
|
This function is called when uSynergy wants to trace something. It is optional to show these messages, but they
|
||||||
are often useful when debugging. uSynergy only traces major events like connecting and disconnecting. Usually
|
are often useful when debugging. uSynergy only traces major events like connecting and disconnecting. Usually
|
||||||
only a single trace is shown when the connection is established and no more trace are called.
|
only a single trace is shown when the connection is established and no more trace are called.
|
||||||
|
|
||||||
@param cookie Cookie supplied in the Synergy context
|
@param cookie Cookie supplied in the Synergy context
|
||||||
@param text Text to be traced
|
@param text Text to be traced
|
||||||
**/
|
**/
|
||||||
typedef void (*uSynergyTraceFunc)(uSynergyCookie cookie, const char *text);
|
typedef void (*uSynergyTraceFunc)(uSynergyCookie cookie, const char *text);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Screen active callback
|
@brief Screen active callback
|
||||||
|
|
||||||
This callback is called when Synergy makes the screen active or inactive. This
|
This callback is called when Synergy makes the screen active or inactive. This
|
||||||
callback is usually sent when the mouse enters or leaves the screen.
|
callback is usually sent when the mouse enters or leaves the screen.
|
||||||
|
|
||||||
@param cookie Cookie supplied in the Synergy context
|
@param cookie Cookie supplied in the Synergy context
|
||||||
@param active Activation flag, 1 if the screen has become active, 0 if the screen has become inactive
|
@param active Activation flag, 1 if the screen has become active, 0 if the screen has become inactive
|
||||||
**/
|
**/
|
||||||
typedef void (*uSynergyScreenActiveCallback)(uSynergyCookie cookie, uSynergyBool active);
|
typedef void (*uSynergyScreenActiveCallback)(uSynergyCookie cookie, uSynergyBool active);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Mouse callback
|
@brief Mouse callback
|
||||||
|
|
||||||
This callback is called when a mouse events happens. The mouse X and Y position,
|
This callback is called when a mouse events happens. The mouse X and Y position,
|
||||||
wheel and button state is communicated in the message. It's up to the user to
|
wheel and button state is communicated in the message. It's up to the user to
|
||||||
interpret if this is a mouse up, down, double-click or other message.
|
interpret if this is a mouse up, down, double-click or other message.
|
||||||
|
|
||||||
@param cookie Cookie supplied in the Synergy context
|
@param cookie Cookie supplied in the Synergy context
|
||||||
@param x Mouse X position
|
@param x Mouse X position
|
||||||
@param y Mouse Y position
|
@param y Mouse Y position
|
||||||
@param wheelX Mouse wheel X position
|
@param wheelX Mouse wheel X position
|
||||||
@param wheelY Mouse wheel Y position
|
@param wheelY Mouse wheel Y position
|
||||||
@param buttonLeft Left button pressed status, 0 for released, 1 for pressed
|
@param buttonLeft Left button pressed status, 0 for released, 1 for pressed
|
||||||
@param buttonMiddle Middle button pressed status, 0 for released, 1 for pressed
|
@param buttonMiddle Middle button pressed status, 0 for released, 1 for pressed
|
||||||
@param buttonRight Right button pressed status, 0 for released, 1 for pressed
|
@param buttonRight Right button pressed status, 0 for released, 1 for pressed
|
||||||
**/
|
**/
|
||||||
typedef void (*uSynergyMouseCallback)(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle);
|
typedef void (*uSynergyMouseCallback)(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Key event callback
|
@brief Key event callback
|
||||||
|
|
||||||
This callback is called when a key is pressed or released.
|
This callback is called when a key is pressed or released.
|
||||||
|
|
||||||
@param cookie Cookie supplied in the Synergy context
|
@param cookie Cookie supplied in the Synergy context
|
||||||
@param key Key code of key that was pressed or released
|
@param key Key code of key that was pressed or released
|
||||||
@param modifiers Status of modifier keys (alt, shift, etc.)
|
@param modifiers Status of modifier keys (alt, shift, etc.)
|
||||||
@param down Down or up status, 1 is key is pressed down, 0 if key is released (up)
|
@param down Down or up status, 1 is key is pressed down, 0 if key is released (up)
|
||||||
@param repeat Repeat flag, 1 if the key is down because the key is repeating, 0 if the key is initially pressed by the user
|
@param repeat Repeat flag, 1 if the key is down because the key is repeating, 0 if the key is initially pressed by the user
|
||||||
**/
|
**/
|
||||||
typedef void (*uSynergyKeyboardCallback)(uSynergyCookie cookie, uint16_t key, uint16_t modifiers, uSynergyBool down, uSynergyBool repeat);
|
typedef void (*uSynergyKeyboardCallback)(uSynergyCookie cookie, uint16_t key, uint16_t modifiers, uSynergyBool down, uSynergyBool repeat);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Joystick event callback
|
@brief Joystick event callback
|
||||||
|
|
||||||
This callback is called when a joystick stick or button changes. It is possible that multiple callbacks are
|
This callback is called when a joystick stick or button changes. It is possible that multiple callbacks are
|
||||||
fired when different sticks or buttons change as these are individual messages in the packet stream. Each
|
fired when different sticks or buttons change as these are individual messages in the packet stream. Each
|
||||||
callback will contain all the valid state for the different axes and buttons. The last callback received will
|
callback will contain all the valid state for the different axes and buttons. The last callback received will
|
||||||
represent the most current joystick state.
|
represent the most current joystick state.
|
||||||
|
|
||||||
@param cookie Cookie supplied in the Synergy context
|
@param cookie Cookie supplied in the Synergy context
|
||||||
@param joyNum Joystick number, always in the range [0 ... USYNERGY_NUM_JOYSTICKS>
|
@param joyNum Joystick number, always in the range [0 ... USYNERGY_NUM_JOYSTICKS>
|
||||||
@param buttons Button pressed mask
|
@param buttons Button pressed mask
|
||||||
@param leftStickX Left stick X position, in range [-127 ... 127]
|
@param leftStickX Left stick X position, in range [-127 ... 127]
|
||||||
@param leftStickY Left stick Y position, in range [-127 ... 127]
|
@param leftStickY Left stick Y position, in range [-127 ... 127]
|
||||||
@param rightStickX Right stick X position, in range [-127 ... 127]
|
@param rightStickX Right stick X position, in range [-127 ... 127]
|
||||||
@param rightStickY Right stick Y position, in range [-127 ... 127]
|
@param rightStickY Right stick Y position, in range [-127 ... 127]
|
||||||
**/
|
**/
|
||||||
typedef void (*uSynergyJoystickCallback)(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY);
|
typedef void (*uSynergyJoystickCallback)(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Clipboard event callback
|
@brief Clipboard event callback
|
||||||
|
|
||||||
This callback is called when something is placed on the clipboard. Multiple callbacks may be fired for
|
This callback is called when something is placed on the clipboard. Multiple callbacks may be fired for
|
||||||
multiple clipboard formats if they are supported. The data provided is read-only and may not be modified
|
multiple clipboard formats if they are supported. The data provided is read-only and may not be modified
|
||||||
by the application.
|
by the application.
|
||||||
|
|
||||||
@param cookie Cookie supplied in the Synergy context
|
@param cookie Cookie supplied in the Synergy context
|
||||||
@param format Clipboard format
|
@param format Clipboard format
|
||||||
@param data Memory area containing the clipboard raw data
|
@param data Memory area containing the clipboard raw data
|
||||||
@param size Size of clipboard data
|
@param size Size of clipboard data
|
||||||
**/
|
**/
|
||||||
typedef void (*uSynergyClipboardCallback)(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size);
|
typedef void (*uSynergyClipboardCallback)(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
// Context
|
// Context
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief uSynergy context
|
@brief uSynergy context
|
||||||
**/
|
**/
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
/* Mandatory configuration data, filled in by client */
|
/* Mandatory configuration data, filled in by client */
|
||||||
uSynergyConnectFunc m_connectFunc; /* Connect function */
|
uSynergyConnectFunc m_connectFunc; /* Connect function */
|
||||||
uSynergySendFunc m_sendFunc; /* Send data function */
|
uSynergySendFunc m_sendFunc; /* Send data function */
|
||||||
uSynergyReceiveFunc m_receiveFunc; /* Receive data function */
|
uSynergyReceiveFunc m_receiveFunc; /* Receive data function */
|
||||||
uSynergySleepFunc m_sleepFunc; /* Thread sleep function */
|
uSynergySleepFunc m_sleepFunc; /* Thread sleep function */
|
||||||
uSynergyGetTimeFunc m_getTimeFunc; /* Get current time function */
|
uSynergyGetTimeFunc m_getTimeFunc; /* Get current time function */
|
||||||
const char* m_clientName; /* Name of Synergy Screen / Client */
|
const char* m_clientName; /* Name of Synergy Screen / Client */
|
||||||
uint16_t m_clientWidth; /* Width of screen */
|
uint16_t m_clientWidth; /* Width of screen */
|
||||||
uint16_t m_clientHeight; /* Height of screen */
|
uint16_t m_clientHeight; /* Height of screen */
|
||||||
|
|
||||||
/* Optional configuration data, filled in by client */
|
/* Optional configuration data, filled in by client */
|
||||||
uSynergyCookie m_cookie; /* Cookie pointer passed to callback functions (can be NULL) */
|
uSynergyCookie m_cookie; /* Cookie pointer passed to callback functions (can be NULL) */
|
||||||
uSynergyTraceFunc m_traceFunc; /* Function for tracing status (can be NULL) */
|
uSynergyTraceFunc m_traceFunc; /* Function for tracing status (can be NULL) */
|
||||||
uSynergyScreenActiveCallback m_screenActiveCallback; /* Callback for entering and leaving screen */
|
uSynergyScreenActiveCallback m_screenActiveCallback; /* Callback for entering and leaving screen */
|
||||||
uSynergyMouseCallback m_mouseCallback; /* Callback for mouse events */
|
uSynergyMouseCallback m_mouseCallback; /* Callback for mouse events */
|
||||||
uSynergyKeyboardCallback m_keyboardCallback; /* Callback for keyboard events */
|
uSynergyKeyboardCallback m_keyboardCallback; /* Callback for keyboard events */
|
||||||
uSynergyJoystickCallback m_joystickCallback; /* Callback for joystick events */
|
uSynergyJoystickCallback m_joystickCallback; /* Callback for joystick events */
|
||||||
uSynergyClipboardCallback m_clipboardCallback; /* Callback for clipboard events */
|
uSynergyClipboardCallback m_clipboardCallback; /* Callback for clipboard events */
|
||||||
|
|
||||||
/* State data, used internall by client, initialized by uSynergyInit() */
|
/* State data, used internall by client, initialized by uSynergyInit() */
|
||||||
uSynergyBool m_connected; /* Is our socket connected? */
|
uSynergyBool m_connected; /* Is our socket connected? */
|
||||||
uSynergyBool m_hasReceivedHello; /* Have we received a 'Hello' from the server? */
|
uSynergyBool m_hasReceivedHello; /* Have we received a 'Hello' from the server? */
|
||||||
uSynergyBool m_isCaptured; /* Is Synergy active (i.e. this client is receiving input messages?) */
|
uSynergyBool m_isCaptured; /* Is Synergy active (i.e. this client is receiving input messages?) */
|
||||||
uint32_t m_lastMessageTime; /* Time at which last message was received */
|
uint32_t m_lastMessageTime; /* Time at which last message was received */
|
||||||
uint32_t m_sequenceNumber; /* Packet sequence number */
|
uint32_t m_sequenceNumber; /* Packet sequence number */
|
||||||
uint8_t m_receiveBuffer[USYNERGY_RECEIVE_BUFFER_SIZE]; /* Receive buffer */
|
uint8_t m_receiveBuffer[USYNERGY_RECEIVE_BUFFER_SIZE]; /* Receive buffer */
|
||||||
int m_receiveOfs; /* Receive buffer offset */
|
int m_receiveOfs; /* Receive buffer offset */
|
||||||
uint8_t m_replyBuffer[USYNERGY_REPLY_BUFFER_SIZE]; /* Reply buffer */
|
uint8_t m_replyBuffer[USYNERGY_REPLY_BUFFER_SIZE]; /* Reply buffer */
|
||||||
uint8_t* m_replyCur; /* Write offset into reply buffer */
|
uint8_t* m_replyCur; /* Write offset into reply buffer */
|
||||||
uint16_t m_mouseX; /* Mouse X position */
|
uint16_t m_mouseX; /* Mouse X position */
|
||||||
uint16_t m_mouseY; /* Mouse Y position */
|
uint16_t m_mouseY; /* Mouse Y position */
|
||||||
int16_t m_mouseWheelX; /* Mouse wheel X position */
|
int16_t m_mouseWheelX; /* Mouse wheel X position */
|
||||||
int16_t m_mouseWheelY; /* Mouse wheel Y position */
|
int16_t m_mouseWheelY; /* Mouse wheel Y position */
|
||||||
uSynergyBool m_mouseButtonLeft; /* Mouse left button */
|
uSynergyBool m_mouseButtonLeft; /* Mouse left button */
|
||||||
uSynergyBool m_mouseButtonRight; /* Mouse right button */
|
uSynergyBool m_mouseButtonRight; /* Mouse right button */
|
||||||
uSynergyBool m_mouseButtonMiddle; /* Mouse middle button */
|
uSynergyBool m_mouseButtonMiddle; /* Mouse middle button */
|
||||||
int8_t m_joystickSticks[USYNERGY_NUM_JOYSTICKS][4]; /* Joystick stick position in 2 axes for 2 sticks */
|
int8_t m_joystickSticks[USYNERGY_NUM_JOYSTICKS][4]; /* Joystick stick position in 2 axes for 2 sticks */
|
||||||
uint16_t m_joystickButtons[USYNERGY_NUM_JOYSTICKS]; /* Joystick button state */
|
uint16_t m_joystickButtons[USYNERGY_NUM_JOYSTICKS]; /* Joystick button state */
|
||||||
} uSynergyContext;
|
} uSynergyContext;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
// Interface
|
// Interface
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Initialize uSynergy context
|
@brief Initialize uSynergy context
|
||||||
|
|
||||||
This function initializes @a context for use. Call this function directly after
|
This function initializes @a context for use. Call this function directly after
|
||||||
creating the context, before filling in any configuration data in it. Not calling
|
creating the context, before filling in any configuration data in it. Not calling
|
||||||
this function will cause undefined behavior.
|
this function will cause undefined behavior.
|
||||||
|
|
||||||
@param context Context to be initialized
|
@param context Context to be initialized
|
||||||
**/
|
**/
|
||||||
extern void uSynergyInit(uSynergyContext *context);
|
extern void uSynergyInit(uSynergyContext *context);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Update uSynergy
|
@brief Update uSynergy
|
||||||
|
|
||||||
This function updates uSynergy and does the bulk of the work. It does connection management,
|
This function updates uSynergy and does the bulk of the work. It does connection management,
|
||||||
receiving data, reconnecting after errors or timeouts and so on. It assumes that networking
|
receiving data, reconnecting after errors or timeouts and so on. It assumes that networking
|
||||||
operations are blocking and it can suspend the current thread if it needs to wait. It is
|
operations are blocking and it can suspend the current thread if it needs to wait. It is
|
||||||
best practice to call uSynergyUpdate from a background thread so it is responsive.
|
best practice to call uSynergyUpdate from a background thread so it is responsive.
|
||||||
|
|
||||||
Because uSynergy relies mostly on blocking calls it will mostly stay in thread sleep state
|
Because uSynergy relies mostly on blocking calls it will mostly stay in thread sleep state
|
||||||
waiting for system mutexes and won't eat much memory.
|
waiting for system mutexes and won't eat much memory.
|
||||||
|
|
||||||
uSynergyUpdate doesn't do any memory allocations or have any side effects beyond those of
|
uSynergyUpdate doesn't do any memory allocations or have any side effects beyond those of
|
||||||
the callbacks it calls.
|
the callbacks it calls.
|
||||||
|
|
||||||
@param context Context to be updated
|
@param context Context to be updated
|
||||||
**/
|
**/
|
||||||
extern void uSynergyUpdate(uSynergyContext *context);
|
extern void uSynergyUpdate(uSynergyContext *context);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Send clipboard data
|
@brief Send clipboard data
|
||||||
|
|
||||||
This function sets new clipboard data and sends it to the server. Use this function if
|
This function sets new clipboard data and sends it to the server. Use this function if
|
||||||
your client cuts or copies data onto the clipboard that it needs to share with the
|
your client cuts or copies data onto the clipboard that it needs to share with the
|
||||||
server.
|
server.
|
||||||
|
|
||||||
Currently there is only support for plaintext, but HTML and image data could be
|
Currently there is only support for plaintext, but HTML and image data could be
|
||||||
supported with some effort.
|
supported with some effort.
|
||||||
|
|
||||||
@param context Context to send clipboard data to
|
@param context Context to send clipboard data to
|
||||||
@param text Text to set to the clipboard
|
@param text Text to set to the clipboard
|
||||||
**/
|
**/
|
||||||
extern void uSynergySendClipboard(uSynergyContext *context, const char *text);
|
extern void uSynergySendClipboard(uSynergyContext *context, const char *text);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -19,15 +19,15 @@
|
||||||
#include "winmmjoy.h"
|
#include "winmmjoy.h"
|
||||||
|
|
||||||
#include <MMSystem.h>
|
#include <MMSystem.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
#pragma comment(lib, "winmm.lib")
|
#pragma comment(lib, "winmm.lib")
|
||||||
|
|
||||||
std::stringstream _logStream;
|
std::stringstream _logStream;
|
||||||
#define LOG(s) \
|
#define LOG(s) \
|
||||||
_logStream.str(""); \
|
_logStream.str(""); \
|
||||||
_logStream << "winmmjoy: " << s << std::endl; \
|
_logStream << "winmmjoy: " << s << std::endl; \
|
||||||
s_log( _logStream.str().c_str())
|
s_log( _logStream.str().c_str())
|
||||||
|
|
||||||
static bool s_running = true;
|
static bool s_running = true;
|
||||||
|
@ -64,7 +64,7 @@ mainLoop(void* data)
|
||||||
const char* triggersEvent = "IPrimaryScreen::getGameDeviceTriggersEvent";
|
const char* triggersEvent = "IPrimaryScreen::getGameDeviceTriggersEvent";
|
||||||
|
|
||||||
JOYINFOEX joyInfo;
|
JOYINFOEX joyInfo;
|
||||||
ZeroMemory(&joyInfo, sizeof(joyInfo));
|
ZeroMemory(&joyInfo, sizeof(joyInfo));
|
||||||
joyInfo.dwSize = sizeof(joyInfo);
|
joyInfo.dwSize = sizeof(joyInfo);
|
||||||
joyInfo.dwFlags = JOY_RETURNALL;
|
joyInfo.dwFlags = JOY_RETURNALL;
|
||||||
|
|
||||||
|
|
|
@ -1,47 +1,47 @@
|
||||||
/*
|
/*
|
||||||
* synergy -- mouse and keyboard sharing utility
|
* synergy -- mouse and keyboard sharing utility
|
||||||
* Copyright (C) 2012 Bolton Software Ltd.
|
* Copyright (C) 2012 Bolton Software Ltd.
|
||||||
* Copyright (C) 2012 Nick Bolton
|
* Copyright (C) 2012 Nick Bolton
|
||||||
*
|
*
|
||||||
* 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
|
||||||
* found in the file COPYING that should have accompanied this file.
|
* found in the file COPYING that should have accompanied this file.
|
||||||
*
|
*
|
||||||
* This package is distributed in the hope that it will be useful,
|
* This package is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* 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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "VersionCheckerTests.h"
|
#include "VersionCheckerTests.h"
|
||||||
#include "VersionChecker.cpp"
|
#include "VersionChecker.cpp"
|
||||||
#include "../../gui/tmp/debug/moc_VersionChecker.cpp"
|
#include "../../gui/tmp/debug/moc_VersionChecker.cpp"
|
||||||
|
|
||||||
#include <QtTest/QTest>
|
#include <QtTest/QTest>
|
||||||
|
|
||||||
void VersionCheckerTests::compareVersions()
|
void VersionCheckerTests::compareVersions()
|
||||||
{
|
{
|
||||||
VersionChecker versionChecker;
|
VersionChecker versionChecker;
|
||||||
|
|
||||||
// compare majors
|
// compare majors
|
||||||
QCOMPARE(versionChecker.compareVersions("1.0.0", "2.0.0"), 1);
|
QCOMPARE(versionChecker.compareVersions("1.0.0", "2.0.0"), 1);
|
||||||
QCOMPARE(versionChecker.compareVersions("2.0.0", "1.0.0"), -1);
|
QCOMPARE(versionChecker.compareVersions("2.0.0", "1.0.0"), -1);
|
||||||
QCOMPARE(versionChecker.compareVersions("1.0.0", "1.0.0"), 0);
|
QCOMPARE(versionChecker.compareVersions("1.0.0", "1.0.0"), 0);
|
||||||
QCOMPARE(versionChecker.compareVersions("1.4.8", "2.4.7"), 1);
|
QCOMPARE(versionChecker.compareVersions("1.4.8", "2.4.7"), 1);
|
||||||
QCOMPARE(versionChecker.compareVersions("2.4.7", "1.4.8"), -1);
|
QCOMPARE(versionChecker.compareVersions("2.4.7", "1.4.8"), -1);
|
||||||
|
|
||||||
// compare minors
|
// compare minors
|
||||||
QCOMPARE(versionChecker.compareVersions("1.3.0", "1.4.0"), 1);
|
QCOMPARE(versionChecker.compareVersions("1.3.0", "1.4.0"), 1);
|
||||||
QCOMPARE(versionChecker.compareVersions("1.4.0", "1.3.0"), -1);
|
QCOMPARE(versionChecker.compareVersions("1.4.0", "1.3.0"), -1);
|
||||||
QCOMPARE(versionChecker.compareVersions("1.4.0", "1.4.0"), 0);
|
QCOMPARE(versionChecker.compareVersions("1.4.0", "1.4.0"), 0);
|
||||||
QCOMPARE(versionChecker.compareVersions("1.3.8", "1.4.7"), 1);
|
QCOMPARE(versionChecker.compareVersions("1.3.8", "1.4.7"), 1);
|
||||||
QCOMPARE(versionChecker.compareVersions("1.4.7", "1.3.8"), -1);
|
QCOMPARE(versionChecker.compareVersions("1.4.7", "1.3.8"), -1);
|
||||||
|
|
||||||
// compare revs
|
// compare revs
|
||||||
QCOMPARE(versionChecker.compareVersions("1.4.7", "1.4.8"), 1);
|
QCOMPARE(versionChecker.compareVersions("1.4.7", "1.4.8"), 1);
|
||||||
QCOMPARE(versionChecker.compareVersions("1.4.8", "1.4.7"), -1);
|
QCOMPARE(versionChecker.compareVersions("1.4.8", "1.4.7"), -1);
|
||||||
QCOMPARE(versionChecker.compareVersions("1.4.7", "1.4.7"), 0);
|
QCOMPARE(versionChecker.compareVersions("1.4.7", "1.4.7"), 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
/*
|
/*
|
||||||
* synergy -- mouse and keyboard sharing utility
|
* synergy -- mouse and keyboard sharing utility
|
||||||
* Copyright (C) 2012 Bolton Software Ltd.
|
* Copyright (C) 2012 Bolton Software Ltd.
|
||||||
* Copyright (C) 2012 Nick Bolton
|
* Copyright (C) 2012 Nick Bolton
|
||||||
*
|
*
|
||||||
* 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
|
||||||
* found in the file COPYING that should have accompanied this file.
|
* found in the file COPYING that should have accompanied this file.
|
||||||
*
|
*
|
||||||
* This package is distributed in the hope that it will be useful,
|
* This package is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* 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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "QObject.h"
|
#include "QObject.h"
|
||||||
|
|
||||||
class VersionCheckerTests : public QObject
|
class VersionCheckerTests : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
private slots:
|
private slots:
|
||||||
void compareVersions();
|
void compareVersions();
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
/*
|
/*
|
||||||
* synergy -- mouse and keyboard sharing utility
|
* synergy -- mouse and keyboard sharing utility
|
||||||
* Copyright (C) 2012 Bolton Software Ltd.
|
* Copyright (C) 2012 Bolton Software Ltd.
|
||||||
* Copyright (C) 2012 Nick Bolton
|
* Copyright (C) 2012 Nick Bolton
|
||||||
*
|
*
|
||||||
* 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
|
||||||
* found in the file COPYING that should have accompanied this file.
|
* found in the file COPYING that should have accompanied this file.
|
||||||
*
|
*
|
||||||
* This package is distributed in the hope that it will be useful,
|
* This package is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* 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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <QtTest/QTest>
|
#include <QtTest/QTest>
|
||||||
#include "VersionCheckerTests.h"
|
#include "VersionCheckerTests.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
VersionCheckerTests versionCheckerTests;
|
VersionCheckerTests versionCheckerTests;
|
||||||
QTest::qExec(&versionCheckerTests, argc, argv);
|
QTest::qExec(&versionCheckerTests, argc, argv);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "CLog.h"
|
#include "CLog.h"
|
||||||
#include "TMethodEventJob.h"
|
#include "TMethodEventJob.h"
|
||||||
#include "CSimpleEventQueueBuffer.h"
|
#include "CSimpleEventQueueBuffer.h"
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
void
|
void
|
||||||
CTestEventQueue::raiseQuitEvent()
|
CTestEventQueue::raiseQuitEvent()
|
||||||
|
@ -47,6 +48,5 @@ CTestEventQueue::cleanupQuitTimeout()
|
||||||
void
|
void
|
||||||
CTestEventQueue::handleQuitTimeout(const CEvent&, void* vclient)
|
CTestEventQueue::handleQuitTimeout(const CEvent&, void* vclient)
|
||||||
{
|
{
|
||||||
LOG((CLOG_ERR "timeout"));
|
throw std::runtime_error("test event queue timeout");
|
||||||
raiseQuitEvent();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <iostream>
|
#include <stdexcept>
|
||||||
|
#include <sstream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#define TEST_ENV
|
#define TEST_ENV
|
||||||
|
|
||||||
|
@ -33,42 +36,74 @@
|
||||||
#include "CTCPSocketFactory.h"
|
#include "CTCPSocketFactory.h"
|
||||||
#include "CCryptoOptions.h"
|
#include "CCryptoOptions.h"
|
||||||
#include "CSocketMultiplexer.h"
|
#include "CSocketMultiplexer.h"
|
||||||
#include "CMSWindowsScreen.h"
|
|
||||||
#include "CGameDevice.h"
|
|
||||||
#include "CThread.h"
|
|
||||||
#include "TMethodJob.h"
|
|
||||||
#include "CTestEventQueue.h"
|
#include "CTestEventQueue.h"
|
||||||
#include "server/CMockInputFilter.h"
|
#include "server/CMockInputFilter.h"
|
||||||
|
#include "TMethodJob.h"
|
||||||
|
#include "CThread.h"
|
||||||
|
#include "CFileChunker.h"
|
||||||
|
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
using ::testing::_;
|
using ::testing::_;
|
||||||
using ::testing::NiceMock;
|
using ::testing::NiceMock;
|
||||||
using ::testing::Return;
|
using ::testing::Return;
|
||||||
using ::testing::Invoke;
|
using ::testing::Invoke;
|
||||||
|
|
||||||
#define TEST_PORT 24803
|
#define TEST_PORT 24803
|
||||||
#define TEST_HOST "localhost"
|
#define TEST_HOST "localhost"
|
||||||
|
|
||||||
const int klargeDataSize = 512;
|
const size_t kMockDataSize = 1024 * 1024 * 10; // 10MB
|
||||||
char g_largeData[klargeDataSize] = "large data:head.1221412312341244213123fdsfasdawdwadwadacwdd.12321412312341244213123fdsfasdawdwadwadacwdawddawdwacawdawd232141231awddawdwacawdawd2321412312341244213123fdsfasdawdwadacwdawddawdwacawdtrtetawdawdwaewe1213412321412312341244213123fdsfasdawdwadacwdawddawdwacawdawdawdwaewe121341awdwaewedacwdawddawdwacawdawd2321412312341244213123fdsfasdawdwadacwdawddawdwacawdtrtetawdawdwaewe1213412321412312341244213123fdsfasdawdwadacwdawddawdwacawdawdawdwaewe121341awdwaewe12134123njk1u31i2nm3e123hu23oi132213njk.tail";
|
const UInt16 kMockDataChunkIncrement = 1024; // 1KB
|
||||||
|
const char* kMockFilename = "NetworkTests.mock";
|
||||||
|
const size_t kMockFileSize = 1024 * 1024 * 10; // 10MB
|
||||||
|
|
||||||
void sendFileToClient_getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h);
|
void getScreenShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h);
|
||||||
void sendFileToClient_getCursorPos(SInt32& x, SInt32& y);
|
void getCursorPos(SInt32& x, SInt32& y);
|
||||||
|
CString intToString(size_t i);
|
||||||
|
UInt8* newMockData(size_t size);
|
||||||
|
void createFile(fstream& file, const char* filename, size_t size);
|
||||||
|
|
||||||
class NetworkTests : public ::testing::Test
|
class NetworkTests : public ::testing::Test
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NetworkTests() { }
|
NetworkTests() :
|
||||||
|
m_mockData(NULL),
|
||||||
|
m_mockDataSize(0),
|
||||||
|
m_mockFileSize(0)
|
||||||
|
{
|
||||||
|
m_mockData = newMockData(kMockDataSize);
|
||||||
|
createFile(m_mockFile, kMockFilename, kMockFileSize);
|
||||||
|
}
|
||||||
|
|
||||||
void sendData(CServer* server);
|
~NetworkTests()
|
||||||
|
{
|
||||||
|
remove(kMockFilename);
|
||||||
|
delete[] m_mockData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendMockData(void* eventTarget);
|
||||||
|
|
||||||
void sendFileToClient_handleClientConnected(const CEvent&, void* vlistener);
|
void sendToClient_mockData_handleClientConnected(const CEvent&, void* vlistener);
|
||||||
void sendFileToClient_fileRecieveComplete(const CEvent&, void*);
|
void sendToClient_mockData_fileRecieveComplete(const CEvent&, void*);
|
||||||
|
|
||||||
|
void sendToClient_mockFile_handleClientConnected(const CEvent&, void* vlistener);
|
||||||
|
void sendToClient_mockFile_fileRecieveComplete(const CEvent& event, void*);
|
||||||
|
|
||||||
|
void sendToServer_mockData_handleClientConnected(const CEvent&, void* vlistener);
|
||||||
|
void sendToServer_mockData_fileRecieveComplete(const CEvent& event, void*);
|
||||||
|
|
||||||
|
void sendToServer_mockFile_handleClientConnected(const CEvent&, void* vlistener);
|
||||||
|
void sendToServer_mockFile_fileRecieveComplete(const CEvent& event, void*);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CTestEventQueue m_events;
|
CTestEventQueue m_events;
|
||||||
|
UInt8* m_mockData;
|
||||||
|
size_t m_mockDataSize;
|
||||||
|
fstream m_mockFile;
|
||||||
|
size_t m_mockFileSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(NetworkTests, sendFileToClient)
|
TEST_F(NetworkTests, sendToClient_mockData)
|
||||||
{
|
{
|
||||||
// server and client
|
// server and client
|
||||||
CNetworkAddress serverAddress(TEST_HOST, TEST_PORT);
|
CNetworkAddress serverAddress(TEST_HOST, TEST_PORT);
|
||||||
|
@ -88,7 +123,7 @@ TEST_F(NetworkTests, sendFileToClient)
|
||||||
m_events.adoptHandler(
|
m_events.adoptHandler(
|
||||||
m_events.forCClientListener().connected(), &listener,
|
m_events.forCClientListener().connected(), &listener,
|
||||||
new TMethodEventJob<NetworkTests>(
|
new TMethodEventJob<NetworkTests>(
|
||||||
this, &NetworkTests::sendFileToClient_handleClientConnected, &listener));
|
this, &NetworkTests::sendToClient_mockData_handleClientConnected, &listener));
|
||||||
|
|
||||||
ON_CALL(serverConfig, isScreen(_)).WillByDefault(Return(true));
|
ON_CALL(serverConfig, isScreen(_)).WillByDefault(Return(true));
|
||||||
ON_CALL(serverConfig, getInputFilter()).WillByDefault(Return(&serverInputFilter));
|
ON_CALL(serverConfig, getInputFilter()).WillByDefault(Return(&serverInputFilter));
|
||||||
|
@ -102,43 +137,196 @@ TEST_F(NetworkTests, sendFileToClient)
|
||||||
CSocketMultiplexer clientSocketMultiplexer;
|
CSocketMultiplexer clientSocketMultiplexer;
|
||||||
CTCPSocketFactory* clientSocketFactory = new CTCPSocketFactory(&m_events, &clientSocketMultiplexer);
|
CTCPSocketFactory* clientSocketFactory = new CTCPSocketFactory(&m_events, &clientSocketMultiplexer);
|
||||||
|
|
||||||
ON_CALL(clientScreen, getShape(_, _, _, _)).WillByDefault(Invoke(sendFileToClient_getShape));
|
ON_CALL(clientScreen, getShape(_, _, _, _)).WillByDefault(Invoke(getScreenShape));
|
||||||
ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(sendFileToClient_getCursorPos));
|
ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos));
|
||||||
|
|
||||||
CClient client(&m_events, "stub", serverAddress, clientSocketFactory, NULL, &clientScreen, cryptoOptions);
|
CClient client(&m_events, "stub", serverAddress, clientSocketFactory, NULL, &clientScreen, cryptoOptions);
|
||||||
|
|
||||||
m_events.adoptHandler(
|
m_events.adoptHandler(
|
||||||
m_events.forIScreen().fileRecieveComplete(), &client,
|
m_events.forIScreen().fileRecieveComplete(), &client,
|
||||||
new TMethodEventJob<NetworkTests>(
|
new TMethodEventJob<NetworkTests>(
|
||||||
this, &NetworkTests::sendFileToClient_fileRecieveComplete));
|
this, &NetworkTests::sendToClient_mockData_fileRecieveComplete));
|
||||||
|
|
||||||
client.connect();
|
client.connect();
|
||||||
|
|
||||||
m_events.initQuitTimeout(10);
|
m_events.initQuitTimeout(5);
|
||||||
|
m_events.loop();
|
||||||
|
m_events.cleanupQuitTimeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(NetworkTests, sendToClient_mockFile)
|
||||||
|
{
|
||||||
|
// server and client
|
||||||
|
CNetworkAddress serverAddress(TEST_HOST, TEST_PORT);
|
||||||
|
CCryptoOptions cryptoOptions;
|
||||||
|
|
||||||
|
serverAddress.resolve();
|
||||||
|
|
||||||
|
// server
|
||||||
|
CSocketMultiplexer serverSocketMultiplexer;
|
||||||
|
CTCPSocketFactory* serverSocketFactory = new CTCPSocketFactory(&m_events, &serverSocketMultiplexer);
|
||||||
|
CClientListener listener(serverAddress, serverSocketFactory, NULL, cryptoOptions, &m_events);
|
||||||
|
NiceMock<CMockScreen> serverScreen;
|
||||||
|
NiceMock<CMockPrimaryClient> primaryClient;
|
||||||
|
NiceMock<CMockConfig> serverConfig;
|
||||||
|
NiceMock<CMockInputFilter> serverInputFilter;
|
||||||
|
|
||||||
|
m_events.adoptHandler(
|
||||||
|
m_events.forCClientListener().connected(), &listener,
|
||||||
|
new TMethodEventJob<NetworkTests>(
|
||||||
|
this, &NetworkTests::sendToClient_mockFile_handleClientConnected, &listener));
|
||||||
|
|
||||||
|
ON_CALL(serverConfig, isScreen(_)).WillByDefault(Return(true));
|
||||||
|
ON_CALL(serverConfig, getInputFilter()).WillByDefault(Return(&serverInputFilter));
|
||||||
|
|
||||||
|
CServer server(serverConfig, &primaryClient, &serverScreen, &m_events);
|
||||||
|
server.m_mock = true;
|
||||||
|
listener.setServer(&server);
|
||||||
|
|
||||||
|
// client
|
||||||
|
NiceMock<CMockScreen> clientScreen;
|
||||||
|
CSocketMultiplexer clientSocketMultiplexer;
|
||||||
|
CTCPSocketFactory* clientSocketFactory = new CTCPSocketFactory(&m_events, &clientSocketMultiplexer);
|
||||||
|
|
||||||
|
ON_CALL(clientScreen, getShape(_, _, _, _)).WillByDefault(Invoke(getScreenShape));
|
||||||
|
ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos));
|
||||||
|
|
||||||
|
CClient client(&m_events, "stub", serverAddress, clientSocketFactory, NULL, &clientScreen, cryptoOptions);
|
||||||
|
|
||||||
|
m_events.adoptHandler(
|
||||||
|
m_events.forIScreen().fileRecieveComplete(), &client,
|
||||||
|
new TMethodEventJob<NetworkTests>(
|
||||||
|
this, &NetworkTests::sendToClient_mockFile_fileRecieveComplete));
|
||||||
|
|
||||||
|
client.connect();
|
||||||
|
|
||||||
|
m_events.initQuitTimeout(5);
|
||||||
|
m_events.loop();
|
||||||
|
m_events.cleanupQuitTimeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(NetworkTests, sendToServer_mockData)
|
||||||
|
{
|
||||||
|
// server and client
|
||||||
|
CNetworkAddress serverAddress(TEST_HOST, TEST_PORT);
|
||||||
|
CCryptoOptions cryptoOptions;
|
||||||
|
|
||||||
|
serverAddress.resolve();
|
||||||
|
|
||||||
|
// server
|
||||||
|
CSocketMultiplexer serverSocketMultiplexer;
|
||||||
|
CTCPSocketFactory* serverSocketFactory = new CTCPSocketFactory(&m_events, &serverSocketMultiplexer);
|
||||||
|
CClientListener listener(serverAddress, serverSocketFactory, NULL, cryptoOptions, &m_events);
|
||||||
|
NiceMock<CMockScreen> serverScreen;
|
||||||
|
NiceMock<CMockPrimaryClient> primaryClient;
|
||||||
|
NiceMock<CMockConfig> serverConfig;
|
||||||
|
NiceMock<CMockInputFilter> serverInputFilter;
|
||||||
|
|
||||||
|
ON_CALL(serverConfig, isScreen(_)).WillByDefault(Return(true));
|
||||||
|
ON_CALL(serverConfig, getInputFilter()).WillByDefault(Return(&serverInputFilter));
|
||||||
|
|
||||||
|
CServer server(serverConfig, &primaryClient, &serverScreen, &m_events);
|
||||||
|
server.m_mock = true;
|
||||||
|
listener.setServer(&server);
|
||||||
|
|
||||||
|
// client
|
||||||
|
NiceMock<CMockScreen> clientScreen;
|
||||||
|
CSocketMultiplexer clientSocketMultiplexer;
|
||||||
|
CTCPSocketFactory* clientSocketFactory = new CTCPSocketFactory(&m_events, &clientSocketMultiplexer);
|
||||||
|
|
||||||
|
ON_CALL(clientScreen, getShape(_, _, _, _)).WillByDefault(Invoke(getScreenShape));
|
||||||
|
ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos));
|
||||||
|
|
||||||
|
CClient client(&m_events, "stub", serverAddress, clientSocketFactory, NULL, &clientScreen, cryptoOptions);
|
||||||
|
|
||||||
|
m_events.adoptHandler(
|
||||||
|
m_events.forCClientListener().connected(), &listener,
|
||||||
|
new TMethodEventJob<NetworkTests>(
|
||||||
|
this, &NetworkTests::sendToServer_mockData_handleClientConnected, &client));
|
||||||
|
|
||||||
|
m_events.adoptHandler(
|
||||||
|
m_events.forIScreen().fileRecieveComplete(), &server,
|
||||||
|
new TMethodEventJob<NetworkTests>(
|
||||||
|
this, &NetworkTests::sendToServer_mockData_fileRecieveComplete));
|
||||||
|
|
||||||
|
client.connect();
|
||||||
|
|
||||||
|
m_events.initQuitTimeout(5);
|
||||||
|
m_events.loop();
|
||||||
|
m_events.cleanupQuitTimeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(NetworkTests, sendToServer_mockFile)
|
||||||
|
{
|
||||||
|
// server and client
|
||||||
|
CNetworkAddress serverAddress(TEST_HOST, TEST_PORT);
|
||||||
|
CCryptoOptions cryptoOptions;
|
||||||
|
|
||||||
|
serverAddress.resolve();
|
||||||
|
|
||||||
|
// server
|
||||||
|
CSocketMultiplexer serverSocketMultiplexer;
|
||||||
|
CTCPSocketFactory* serverSocketFactory = new CTCPSocketFactory(&m_events, &serverSocketMultiplexer);
|
||||||
|
CClientListener listener(serverAddress, serverSocketFactory, NULL, cryptoOptions, &m_events);
|
||||||
|
NiceMock<CMockScreen> serverScreen;
|
||||||
|
NiceMock<CMockPrimaryClient> primaryClient;
|
||||||
|
NiceMock<CMockConfig> serverConfig;
|
||||||
|
NiceMock<CMockInputFilter> serverInputFilter;
|
||||||
|
|
||||||
|
ON_CALL(serverConfig, isScreen(_)).WillByDefault(Return(true));
|
||||||
|
ON_CALL(serverConfig, getInputFilter()).WillByDefault(Return(&serverInputFilter));
|
||||||
|
|
||||||
|
CServer server(serverConfig, &primaryClient, &serverScreen, &m_events);
|
||||||
|
server.m_mock = true;
|
||||||
|
listener.setServer(&server);
|
||||||
|
|
||||||
|
// client
|
||||||
|
NiceMock<CMockScreen> clientScreen;
|
||||||
|
CSocketMultiplexer clientSocketMultiplexer;
|
||||||
|
CTCPSocketFactory* clientSocketFactory = new CTCPSocketFactory(&m_events, &clientSocketMultiplexer);
|
||||||
|
|
||||||
|
ON_CALL(clientScreen, getShape(_, _, _, _)).WillByDefault(Invoke(getScreenShape));
|
||||||
|
ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos));
|
||||||
|
|
||||||
|
CClient client(&m_events, "stub", serverAddress, clientSocketFactory, NULL, &clientScreen, cryptoOptions);
|
||||||
|
|
||||||
|
m_events.adoptHandler(
|
||||||
|
m_events.forCClientListener().connected(), &listener,
|
||||||
|
new TMethodEventJob<NetworkTests>(
|
||||||
|
this, &NetworkTests::sendToServer_mockFile_handleClientConnected, &client));
|
||||||
|
|
||||||
|
m_events.adoptHandler(
|
||||||
|
m_events.forIScreen().fileRecieveComplete(), &server,
|
||||||
|
new TMethodEventJob<NetworkTests>(
|
||||||
|
this, &NetworkTests::sendToServer_mockFile_fileRecieveComplete));
|
||||||
|
|
||||||
|
client.connect();
|
||||||
|
|
||||||
|
m_events.initQuitTimeout(5);
|
||||||
m_events.loop();
|
m_events.loop();
|
||||||
m_events.cleanupQuitTimeout();
|
m_events.cleanupQuitTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
NetworkTests::sendFileToClient_handleClientConnected(const CEvent&, void* vlistener)
|
NetworkTests::sendToClient_mockData_handleClientConnected(const CEvent&, void* vlistener)
|
||||||
{
|
{
|
||||||
CClientListener* listener = reinterpret_cast<CClientListener*>(vlistener);
|
CClientListener* listener = reinterpret_cast<CClientListener*>(vlistener);
|
||||||
CServer* server = listener->getServer();
|
CServer* server = listener->getServer();
|
||||||
|
|
||||||
CClientProxy* client = listener->getNextClient();
|
CClientProxy* client = listener->getNextClient();
|
||||||
if (client == NULL) {
|
if (client == NULL) {
|
||||||
throw std::exception("client is null");
|
throw runtime_error("client is null");
|
||||||
}
|
}
|
||||||
|
|
||||||
CBaseClientProxy* bcp = reinterpret_cast<CBaseClientProxy*>(client);
|
CBaseClientProxy* bcp = reinterpret_cast<CBaseClientProxy*>(client);
|
||||||
server->adoptClient(bcp);
|
server->adoptClient(bcp);
|
||||||
server->setActive(bcp);
|
server->setActive(bcp);
|
||||||
|
|
||||||
sendData(server);
|
sendMockData(server);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
NetworkTests::sendFileToClient_fileRecieveComplete(const CEvent& event, void*)
|
NetworkTests::sendToClient_mockData_fileRecieveComplete(const CEvent& event, void*)
|
||||||
{
|
{
|
||||||
CClient* client = reinterpret_cast<CClient*>(event.getTarget());
|
CClient* client = reinterpret_cast<CClient*>(event.getTarget());
|
||||||
EXPECT_TRUE(client->isReceivedFileSizeValid());
|
EXPECT_TRUE(client->isReceivedFileSizeValid());
|
||||||
|
@ -147,32 +335,166 @@ NetworkTests::sendFileToClient_fileRecieveComplete(const CEvent& event, void*)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
NetworkTests::sendData(CServer* server)
|
NetworkTests::sendToClient_mockFile_handleClientConnected(const CEvent&, void* vlistener)
|
||||||
{
|
{
|
||||||
UInt8* largeDataSize = new UInt8[5];
|
CClientListener* listener = reinterpret_cast<CClientListener*>(vlistener);
|
||||||
largeDataSize[0] = '0';
|
CServer* server = listener->getServer();
|
||||||
largeDataSize[1] = '5';
|
|
||||||
largeDataSize[2] = '1';
|
|
||||||
largeDataSize[3] = '1';
|
|
||||||
largeDataSize[4] = '\0';
|
|
||||||
|
|
||||||
// transfer data from server -> client
|
|
||||||
m_events.addEvent(CEvent(m_events.forIScreen().fileChunkSending(), server, largeDataSize));
|
|
||||||
|
|
||||||
UInt8* largeData = new UInt8[klargeDataSize + 1];
|
|
||||||
largeData[0] = '1';
|
|
||||||
memcpy(&largeData[1], g_largeData, klargeDataSize);
|
|
||||||
m_events.addEvent(CEvent(m_events.forIScreen().fileChunkSending(), server, (UInt8*)largeData));
|
|
||||||
|
|
||||||
UInt8* transferFinished = new UInt8[2];
|
CClientProxy* client = listener->getNextClient();
|
||||||
transferFinished[0] = '2';
|
if (client == NULL) {
|
||||||
transferFinished[1] = '\0';
|
throw runtime_error("client is null");
|
||||||
|
}
|
||||||
|
|
||||||
m_events.addEvent(CEvent(m_events.forIScreen().fileChunkSending(), server, transferFinished));
|
CBaseClientProxy* bcp = reinterpret_cast<CBaseClientProxy*>(client);
|
||||||
|
server->adoptClient(bcp);
|
||||||
|
server->setActive(bcp);
|
||||||
|
|
||||||
|
server->sendFileToClient(kMockFilename);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetworkTests::sendToClient_mockFile_fileRecieveComplete(const CEvent& event, void*)
|
||||||
|
{
|
||||||
|
CClient* client = reinterpret_cast<CClient*>(event.getTarget());
|
||||||
|
EXPECT_TRUE(client->isReceivedFileSizeValid());
|
||||||
|
|
||||||
|
m_events.raiseQuitEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetworkTests::sendToServer_mockData_handleClientConnected(const CEvent&, void* vclient)
|
||||||
|
{
|
||||||
|
CClient* client = reinterpret_cast<CClient*>(vclient);
|
||||||
|
sendMockData(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetworkTests::sendToServer_mockData_fileRecieveComplete(const CEvent& event, void*)
|
||||||
|
{
|
||||||
|
CServer* server = reinterpret_cast<CServer*>(event.getTarget());
|
||||||
|
EXPECT_TRUE(server->isReceivedFileSizeValid());
|
||||||
|
|
||||||
|
m_events.raiseQuitEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetworkTests::sendToServer_mockFile_handleClientConnected(const CEvent&, void* vclient)
|
||||||
|
{
|
||||||
|
CClient* client = reinterpret_cast<CClient*>(vclient);
|
||||||
|
client->sendFileToServer(kMockFilename);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetworkTests::sendToServer_mockFile_fileRecieveComplete(const CEvent& event, void*)
|
||||||
|
{
|
||||||
|
CServer* server = reinterpret_cast<CServer*>(event.getTarget());
|
||||||
|
EXPECT_TRUE(server->isReceivedFileSizeValid());
|
||||||
|
|
||||||
|
m_events.raiseQuitEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetworkTests::sendMockData(void* eventTarget)
|
||||||
|
{
|
||||||
|
// send first message (file size)
|
||||||
|
CString size = intToString(kMockDataSize);
|
||||||
|
UInt32 sizeLength = size.size();
|
||||||
|
CFileChunker::CFileChunk* sizeMessage = new CFileChunker::CFileChunk(sizeLength + 2);
|
||||||
|
char* chunkData = sizeMessage->m_chunk;
|
||||||
|
|
||||||
|
chunkData[0] = kFileStart;
|
||||||
|
memcpy(&chunkData[1], size.c_str(), sizeLength);
|
||||||
|
chunkData[sizeLength + 1] = '\0';
|
||||||
|
m_events.addEvent(CEvent(m_events.forIScreen().fileChunkSending(), eventTarget, sizeMessage));
|
||||||
|
|
||||||
|
// send chunk messages with incrementing chunk size
|
||||||
|
size_t lastSize = 0;
|
||||||
|
size_t sentLength = 0;
|
||||||
|
while (true) {
|
||||||
|
size_t chunkSize = lastSize + kMockDataChunkIncrement;
|
||||||
|
|
||||||
|
// make sure we don't read too much from the mock data.
|
||||||
|
if (sentLength + chunkSize > kMockDataSize) {
|
||||||
|
chunkSize = kMockDataSize - sentLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
// first byte is the chunk mark, last is \0
|
||||||
|
CFileChunker::CFileChunk* fileChunk = new CFileChunker::CFileChunk(chunkSize + 2);
|
||||||
|
char* chunkData = fileChunk->m_chunk;
|
||||||
|
|
||||||
|
chunkData[0] = kFileChunk;
|
||||||
|
memcpy(&chunkData[1], &m_mockData[sentLength], chunkSize);
|
||||||
|
chunkData[chunkSize + 1] = '\0';
|
||||||
|
m_events.addEvent(CEvent(m_events.forIScreen().fileChunkSending(), eventTarget, fileChunk));
|
||||||
|
|
||||||
|
sentLength += chunkSize;
|
||||||
|
lastSize = chunkSize;
|
||||||
|
|
||||||
|
if (sentLength == kMockDataSize) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// send last message
|
||||||
|
CFileChunker::CFileChunk* transferFinished = new CFileChunker::CFileChunk(2);
|
||||||
|
chunkData = transferFinished->m_chunk;
|
||||||
|
|
||||||
|
chunkData[0] = kFileEnd;
|
||||||
|
chunkData[1] = '\0';
|
||||||
|
m_events.addEvent(CEvent(m_events.forIScreen().fileChunkSending(), eventTarget, transferFinished));
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt8*
|
||||||
|
newMockData(size_t size)
|
||||||
|
{
|
||||||
|
UInt8* buffer = new UInt8[size];
|
||||||
|
|
||||||
|
UInt8* data = buffer;
|
||||||
|
const UInt8 head[] = "mock head... ";
|
||||||
|
size_t headSize = sizeof(head) - 1;
|
||||||
|
const UInt8 tail[] = "... mock tail";
|
||||||
|
size_t tailSize = sizeof(tail) - 1;
|
||||||
|
const UInt8 synergyRocks[] = "synergy\0 rocks! ";
|
||||||
|
size_t synergyRocksSize = sizeof(synergyRocks) - 1;
|
||||||
|
|
||||||
|
memcpy(data, head, headSize);
|
||||||
|
data += headSize;
|
||||||
|
|
||||||
|
SInt32 times = (size - headSize - tailSize) / synergyRocksSize;
|
||||||
|
for (SInt32 i = 0; i < times; ++i) {
|
||||||
|
memcpy(data, synergyRocks, synergyRocksSize);
|
||||||
|
data += synergyRocksSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
SInt32 remainder = (size - headSize - tailSize) % synergyRocksSize;
|
||||||
|
if (remainder != 0) {
|
||||||
|
memset(data, '.', remainder);
|
||||||
|
data += remainder;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(data, tail, tailSize);
|
||||||
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sendFileToClient_getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h)
|
createFile(fstream& file, const char* filename, size_t size)
|
||||||
|
{
|
||||||
|
UInt8* buffer = newMockData(size);
|
||||||
|
|
||||||
|
file.open(filename, ios::out | ios::binary);
|
||||||
|
if (!file.is_open()) {
|
||||||
|
throw runtime_error("file not open");
|
||||||
|
}
|
||||||
|
|
||||||
|
file.write(reinterpret_cast<char*>(buffer), size);
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
delete[] buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
getScreenShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h)
|
||||||
{
|
{
|
||||||
x = 0;
|
x = 0;
|
||||||
y = 0;
|
y = 0;
|
||||||
|
@ -181,8 +503,16 @@ sendFileToClient_getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sendFileToClient_getCursorPos(SInt32& x, SInt32& y)
|
getCursorPos(SInt32& x, SInt32& y)
|
||||||
{
|
{
|
||||||
x = 0;
|
x = 0;
|
||||||
y = 0;
|
y = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CString
|
||||||
|
intToString(size_t i)
|
||||||
|
{
|
||||||
|
stringstream ss;
|
||||||
|
ss << i;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
#include <gmock/gmock.h>
|
#include <gmock/gmock.h>
|
||||||
|
|
||||||
#include "COSXKeyState.h"
|
#include "COSXKeyState.h"
|
||||||
#include "CMockKeyMap.h"
|
#include "synergy/CMockKeyMap.h"
|
||||||
#include "CMockEventQueue.h"
|
#include "synergy/CMockEventQueue.h"
|
||||||
|
|
||||||
#include "CLog.h"
|
#include "CLog.h"
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,8 @@
|
||||||
#define TEST_ENV
|
#define TEST_ENV
|
||||||
#include "Global.h"
|
#include "Global.h"
|
||||||
|
|
||||||
#include "CMockKeyMap.h"
|
#include "synergy/CMockKeyMap.h"
|
||||||
#include "CMockEventQueue.h"
|
#include "synergy/CMockEventQueue.h"
|
||||||
#include "CXWindowsKeyState.h"
|
#include "CXWindowsKeyState.h"
|
||||||
#include "CLog.h"
|
#include "CLog.h"
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include "CXWindowsScreen.h"
|
#include "CXWindowsScreen.h"
|
||||||
#include "CMockEventQueue.h"
|
#include "synergy/CMockEventQueue.h"
|
||||||
|
|
||||||
using ::testing::_;
|
using ::testing::_;
|
||||||
|
|
||||||
|
|
|
@ -48,8 +48,8 @@ TEST(CServerProxyTests, mouseMove)
|
||||||
g_mouseMove_bufferIndex = 0;
|
g_mouseMove_bufferIndex = 0;
|
||||||
|
|
||||||
NiceMock<CMockEventQueue> eventQueue;
|
NiceMock<CMockEventQueue> eventQueue;
|
||||||
NiceMock<CMockClient> client;
|
|
||||||
NiceMock<CMockStream> stream;
|
NiceMock<CMockStream> stream;
|
||||||
|
NiceMock<CMockClient> client;
|
||||||
IStreamEvents streamEvents;
|
IStreamEvents streamEvents;
|
||||||
streamEvents.setEvents(&eventQueue);
|
streamEvents.setEvents(&eventQueue);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue