issue #65 - Auto config feature using Zeroconf/Bonjour

merging zeroconf into trunk
This commit is contained in:
jerry 2014-08-21 17:32:40 +00:00
parent 1a5ebb7922
commit 8cad7551e6
24 changed files with 905 additions and 303 deletions

View File

@ -1,3 +1,7 @@
1.6.0
=====
Feature #65 - Auto config feature using Zeroconf/Bonjour
1.5.1
=====
Bug #3307 - Configuration file paths containing spaces don't work

BIN
ext/bonjour/x64/libdnssd.a Normal file

Binary file not shown.

View File

@ -41,7 +41,12 @@ SOURCES += src/main.cpp \
src/Ipc.cpp \
src/SynergyLocale.cpp \
src/QUtility.cpp \
src/PremiumAuth.cpp
src/PremiumAuth.cpp \
src/ZeroconfServer.cpp \
src/ZeroconfThread.cpp \
src/ZeroconfRegister.cpp \
src/ZeroconfBrowser.cpp \
src/ZeroconfService.cpp
HEADERS += src/MainWindow.h \
src/AboutDialog.h \
src/ServerConfig.h \
@ -69,7 +74,13 @@ HEADERS += src/MainWindow.h \
src/Ipc.h \
src/SynergyLocale.h \
src/QUtility.h \
src/PremiumAuth.h
src/PremiumAuth.h \
src/ZeroconfServer.h \
src/ZeroconfThread.h \
src/ZeroconfRegister.h \
src/ZeroconfRecord.h \
src/ZeroconfBrowser.h \
src/ZeroconfService.h
RESOURCES += res/Synergy.qrc
RC_FILE = res/win/Synergy.rc
macx {
@ -82,6 +93,9 @@ macx {
QMAKE_BUNDLE_DATA += QSYNERGY_ICON
LIBS += $$MACX_LIBS
}
unix:!macx {
LIBS += -ldns_sd
}
debug {
OBJECTS_DIR = tmp/debug
MOC_DIR = tmp/debug
@ -95,5 +109,7 @@ release {
win32 {
Debug:DESTDIR = ../../bin/Debug
Release:DESTDIR = ../../bin/Release
LIBS += -L"../../ext/bonjour/x64" -ldnssd
INCLUDEPATH += "$(BONJOUR_SDK_HOME)/Include"
}
else:DESTDIR = ../../bin

View File

@ -252,7 +252,7 @@
</sizepolicy>
</property>
<property name="title">
<string>&amp;Client (use another computer's keyboard and mouse):</string>
<string>&amp;Client (use another computer's mouse and keyboard):</string>
</property>
<property name="checkable">
<bool>true</bool>

View File

@ -128,7 +128,7 @@
<item>
<widget class="QRadioButton" name="m_pRadioButtonPremiumLogin">
<property name="text">
<string>Yes, I have Synergy Premium</string>
<string>I donated to Synergy and have a premium login...</string>
</property>
</widget>
</item>
@ -289,33 +289,10 @@
</property>
</spacer>
</item>
<item>
<widget class="QRadioButton" name="m_pRadioButtonPremiumRegister">
<property name="text">
<string>Tell me more...</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_11">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QRadioButton" name="m_pRadioButtonPremiumLater">
<property name="text">
<string>Not interested</string>
<string>No, I have not donated to Synergy, skip this step</string>
</property>
</widget>
</item>
@ -360,7 +337,7 @@
</font>
</property>
<property name="text">
<string>&amp;Server (new setup)</string>
<string>&amp;Server (share this computer's mouse and keyboard)</string>
</property>
</widget>
</item>
@ -373,7 +350,11 @@
</size>
</property>
<property name="text">
<string>This is the first computer you are configuring. Your keyboard and mouse are connected to this computer. This will allow you to move your mouse over to another computer's screen. There can only be one server in your setup.</string>
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;My main mouse and keyboard are connected to this computer. This will allow you to move your mouse over to another computer's screen. There can only be one server in your setup.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
@ -405,7 +386,7 @@
</font>
</property>
<property name="text">
<string>&amp;Client (add to setup)</string>
<string>&amp;Client (use another computer's mouse and keyboard)</string>
</property>
</widget>
</item>
@ -418,7 +399,11 @@
</size>
</property>
<property name="text">
<string>You have already set up a server. This is a computer you wish to control using the server's keyboard and mouse. There can be many clients in your setup.</string>
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;You have already set up a server. This computer will be controlled using the server's mouse and keyboard. There can be many clients in your setup.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
@ -443,225 +428,15 @@
</item>
</layout>
</widget>
<widget class="QWizardPage" name="m_pCryptoPage">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Encryption</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>Network traffic can be easily monitored on public networks (e.g. schools and corporate networks) or WiFi networks. Using encryption can reduce the risk that sensitive information (e.g. passwords) will be revealed to others.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_10">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="m_pCheckBoxEnableCrypto">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Enable encryption</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="m_pLabel_27">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>A longer password will provide stronger encryption. It is a good idea to use 20 characters or more.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout_2">
<item row="1" column="0">
<widget class="QLabel" name="m_pLabel_23">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>&amp;Password:</string>
</property>
<property name="indent">
<number>10</number>
</property>
<property name="buddy">
<cstring>m_pLineEditCryptoPassword1</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="m_pLineEditCryptoPassword1">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="m_pLabel_24">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>&amp;Confirm:</string>
</property>
<property name="indent">
<number>10</number>
</property>
<property name="buddy">
<cstring>m_pLineEditCryptoPassword2</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="m_pLineEditCryptoPassword2">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>100</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
<tabstops>
<tabstop>m_pComboLanguage</tabstop>
<tabstop>m_pRadioButtonPremiumLogin</tabstop>
<tabstop>m_pLineEditPremiumEmail</tabstop>
<tabstop>m_pLineEditPremiumPassword</tabstop>
<tabstop>m_pRadioButtonPremiumRegister</tabstop>
<tabstop>m_pRadioButtonPremiumLater</tabstop>
<tabstop>m_pServerRadioButton</tabstop>
<tabstop>m_pClientRadioButton</tabstop>
<tabstop>m_pLineEditCryptoPassword1</tabstop>
<tabstop>m_pLineEditCryptoPassword2</tabstop>
</tabstops>
<resources/>
<connections/>

View File

@ -25,6 +25,7 @@
#include "ServerConfigDialog.h"
#include "SettingsDialog.h"
#include "SetupWizard.h"
#include "ZeroconfService.h"
#include <QtCore>
#include <QtGui>
@ -64,7 +65,7 @@ MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) :
m_AppConfig(appConfig),
m_pSynergy(NULL),
m_SynergyState(synergyDisconnected),
m_ServerConfig(&m_Settings, 5, 3),
m_ServerConfig(&m_Settings, 5, 3, m_AppConfig.screenName()),
m_pTempConfigFile(NULL),
m_pTrayIcon(NULL),
m_pTrayIconMenu(NULL),
@ -75,7 +76,8 @@ MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) :
m_pMenuFile(NULL),
m_pMenuEdit(NULL),
m_pMenuWindow(NULL),
m_pMenuHelp(NULL)
m_pMenuHelp(NULL),
m_pZeroconfService(NULL)
{
setupUi(this);
@ -107,16 +109,20 @@ MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) :
resize(700, 530);
setMinimumSize(size());
#endif
updateZeroconfService();
}
MainWindow::~MainWindow()
{
if (appConfig().processMode() == Desktop)
{
if (appConfig().processMode() == Desktop) {
stopDesktop();
}
saveSettings();
delete m_pZeroconfService;
}
void MainWindow::open()
@ -382,13 +388,13 @@ void MainWindow::startSynergy()
args << "-f" << "--no-tray" << "--debug" << appConfig().logLevelText();
if (!appConfig().screenName().isEmpty())
args << "--name" << appConfig().screenName();
if (appConfig().cryptoEnabled())
{
args << "--crypto-pass" << appConfig().cryptoPass();
}
args << "--name" << getScreenName();
if (appConfig().cryptoEnabled())
{
args << "--crypto-pass" << appConfig().cryptoPass();
}
if (desktopMode)
{
@ -553,7 +559,8 @@ QString MainWindow::configFilename()
QString MainWindow::address()
{
return (!appConfig().interface().isEmpty() ? appConfig().interface() : "") + ":" + QString::number(appConfig().port());
QString i = appConfig().interface();
return (!i.isEmpty() ? i : "") + ":" + QString::number(appConfig().port());
}
QString MainWindow::appPath(const QString& name)
@ -796,6 +803,29 @@ void MainWindow::updatePremiumInfo()
}
}
void MainWindow::updateZeroconfService()
{
if (!m_AppConfig.wizardShouldRun()) {
if (m_pZeroconfService) {
delete m_pZeroconfService;
}
m_pZeroconfService = new ZeroconfService(this);
}
}
void MainWindow::on_m_pGroupClient_toggled(bool on)
{
m_pGroupServer->setChecked(!on);
updateZeroconfService();
}
void MainWindow::on_m_pGroupServer_toggled(bool on)
{
m_pGroupClient->setChecked(!on);
updateZeroconfService();
}
bool MainWindow::on_m_pButtonBrowseConfigFile_clicked()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("Browse for a synergys config file"), QString(), synergyConfigFilter);
@ -841,12 +871,37 @@ void MainWindow::on_m_pActionSettings_triggered()
}
}
void MainWindow::on_m_pButtonConfigureServer_clicked()
void MainWindow::autoAddScreen(const QString name)
{
int r = m_ServerConfig.autoAddScreen(name);
if (r != kAutoAddScreenOk) {
switch (r) {
case kAutoAddScreenNoServer:
showConfigureServer(
tr("Please add the server (%1) to the grid.")
.arg(appConfig().screenName()));
break;
case kAutoAddScreenNoSpace:
showConfigureServer(
tr("Please add the client (%1) to the grid.").arg(name));
break;
}
}
}
void MainWindow::showConfigureServer(const QString& message)
{
ServerConfigDialog dlg(this, serverConfig(), appConfig().screenName());
dlg.message(message);
dlg.exec();
}
void MainWindow::on_m_pButtonConfigureServer_clicked()
{
showConfigureServer();
}
void MainWindow::on_m_pActionWizard_triggered()
{
SetupWizard wizard(*this, false);

View File

@ -49,6 +49,7 @@ class QTemporaryFile;
class LogDialog;
class QSynergyApplication;
class SetupWizard;
class ZeroconfService;
class MainWindow : public QMainWindow, public Ui::MainWindowBase
{
@ -91,6 +92,13 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
void open();
void clearLog();
VersionChecker& versionChecker() { return m_VersionChecker; }
QString getScreenName();
void startSynergy();
ServerConfig& serverConfig() { return m_ServerConfig; }
void showConfigureServer(const QString& message);
void showConfigureServer() { showConfigureServer(""); }
void autoAddScreen(const QString name);
void updateZeroconfService();
public slots:
void appendLogRaw(const QString& text);
@ -98,8 +106,8 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
void appendLogError(const QString& text);
protected slots:
void on_m_pGroupClient_toggled(bool on) { m_pGroupServer->setChecked(!on); }
void on_m_pGroupServer_toggled(bool on) { m_pGroupClient->setChecked(!on); }
void on_m_pGroupClient_toggled(bool on);
void on_m_pGroupServer_toggled(bool on);
bool on_m_pButtonBrowseConfigFile_clicked();
void on_m_pButtonConfigureServer_clicked();
bool on_m_pActionSave_triggered();
@ -109,7 +117,6 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
void on_m_pElevateCheckBox_toggled(bool checked);
void synergyFinished(int exitCode, QProcess::ExitStatus);
void trayActivated(QSystemTrayIcon::ActivationReason reason);
void startSynergy();
void stopSynergy();
void logOutput();
void logError();
@ -120,7 +127,6 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
AppConfig& appConfig() { return m_AppConfig; }
QProcess*& synergyProcess() { return m_pSynergy; }
void setSynergyProcess(QProcess* p) { m_pSynergy = p; }
ServerConfig& serverConfig() { return m_ServerConfig; }
void initConnections();
void createMenuBar();
void createStatusBar();
@ -137,7 +143,6 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
void onModeChanged(bool startDesktop, bool applyService);
void updateStateFromLogLine(const QString& line);
QString getIPAddresses();
QString getScreenName();
void stopService();
void stopDesktop();
void changeEvent(QEvent* event);
@ -163,6 +168,7 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
QMenu* m_pMenuEdit;
QMenu* m_pMenuWindow;
QMenu* m_pMenuHelp;
ZeroconfService* m_pZeroconfService;
private slots:
void on_m_pButtonApply_clicked();

View File

@ -64,12 +64,12 @@ class Screen : public BaseConfig
QTextStream& writeAliasesSection(QTextStream& outStream) const;
bool swapped() const { return m_Swapped; }
QString& name() { return m_Name; }
void setName(const QString& name) { m_Name = name; }
protected:
void init();
void setName(const QString& name) { m_Name = name; }
QPixmap* pixmap() { return &m_Pixmap; }
QString& name() { return m_Name; }
void setPixmap(const QPixmap& pixmap) { m_Pixmap = pixmap; }
QStringList& aliases() { return m_Aliases; }

View File

@ -28,18 +28,21 @@ static const struct
const char* name;
} neighbourDirs[] =
{
{ 0, -1, "up" },
{ 1, 0, "right" },
{ 0, 1, "down" },
{ -1, 0, "left" },
{ 0, -1, "up" },
{ 0, 1, "down" },
};
const int serverDefaultIndex = 7;
ServerConfig::ServerConfig(QSettings* settings, int numColumns, int numRows) :
ServerConfig::ServerConfig(QSettings* settings, int numColumns, int numRows , QString serverName) :
m_pSettings(settings),
m_Screens(),
m_NumColumns(numColumns),
m_NumRows(numRows)
m_NumRows(numRows),
m_ServerName(serverName)
{
Q_ASSERT(m_pSettings);
@ -263,3 +266,62 @@ int ServerConfig::numScreens() const
return rval;
}
int ServerConfig::autoAddScreen(const QString name)
{
int serverIndex = -1;
int targetIndex = -1;
if (!findScreenName(m_ServerName, serverIndex)) {
if (!tryFixNoServer(m_ServerName, serverIndex)) {
return kAutoAddScreenNoServer;
}
}
if (findScreenName(name, targetIndex)) {
// already exists.
return kAutoAddScreenOk;
}
bool success = false;
for (unsigned int i = 0; i < sizeof(neighbourDirs) / sizeof(neighbourDirs[0]); i++) {
int idx = adjacentScreenIndex(serverIndex, neighbourDirs[i].x, neighbourDirs[i].y);
if (idx != -1 && screens()[idx].isNull()) {
m_Screens[idx].setName(name);
success = true;
break;
}
}
if (!success) {
return kAutoAddScreenNoSpace;
}
saveSettings();
return kAutoAddScreenOk;
}
bool ServerConfig::findScreenName(const QString& name, int& index)
{
bool found = false;
for (int i = 0; i < screens().size(); i++) {
QString test = screens()[i].name();
if (!screens()[i].isNull() &&
screens()[i].name().compare(name) == 0) {
index = i;
found = true;
break;
}
}
return found;
}
bool ServerConfig::tryFixNoServer(const QString& name, int& index)
{
bool fixed = false;
if (screens()[serverDefaultIndex].isNull()) {
m_Screens[serverDefaultIndex].setName(name);
index = serverDefaultIndex;
fixed = true;
}
return fixed;
}

View File

@ -38,7 +38,7 @@ class ServerConfig : public BaseConfig
friend QTextStream& operator<<(QTextStream& outStream, const ServerConfig& config);
public:
ServerConfig(QSettings* settings, int numColumns, int numRows);
ServerConfig(QSettings* settings, int numColumns, int numRows, QString serverName);
~ServerConfig();
public:
@ -64,6 +64,7 @@ class ServerConfig : public BaseConfig
bool save(const QString& fileName) const;
void save(QFile& file) const;
int numScreens() const;
int autoAddScreen(const QString name);
protected:
QSettings& settings() { return *m_pSettings; }
@ -89,6 +90,10 @@ class ServerConfig : public BaseConfig
void init();
int adjacentScreenIndex(int idx, int deltaColumn, int deltaRow) const;
private:
bool findScreenName(const QString& name, int& index);
bool tryFixNoServer(const QString& name, int& index);
private:
QSettings* m_pSettings;
ScreenList m_Screens;
@ -106,9 +111,16 @@ class ServerConfig : public BaseConfig
int m_SwitchCornerSize;
QList<bool> m_SwitchCorners;
HotkeyList m_Hotkeys;
QString m_ServerName;
};
QTextStream& operator<<(QTextStream& outStream, const ServerConfig& config);
enum {
kAutoAddScreenOk,
kAutoAddScreenNoServer,
kAutoAddScreenNoSpace
};
#endif

View File

@ -23,13 +23,15 @@
#include <QtCore>
#include <QtGui>
#include <QMessageBox>
ServerConfigDialog::ServerConfigDialog(QWidget* parent, ServerConfig& config, const QString& defaultScreenName) :
QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint),
Ui::ServerConfigDialogBase(),
m_OrigServerConfig(config),
m_ServerConfig(config),
m_ScreenSetupModel(serverConfig().screens(), serverConfig().numColumns(), serverConfig().numRows())
m_ScreenSetupModel(serverConfig().screens(), serverConfig().numColumns(), serverConfig().numRows()),
m_Message("")
{
setupUi(this);
@ -61,6 +63,17 @@ ServerConfigDialog::ServerConfigDialog(QWidget* parent, ServerConfig& config, co
model().screen(serverConfig().numColumns() / 2, serverConfig().numRows() / 2) = Screen(defaultScreenName);
}
void ServerConfigDialog::showEvent(QShowEvent* event)
{
QDialog::show();
if (!m_Message.isEmpty())
{
// TODO: ideally this massage box should pop up after the dialog is shown
QMessageBox::information(this, tr("Configure server"), m_Message);
}
}
void ServerConfigDialog::accept()
{
serverConfig().haveHeartbeat(m_pCheckBoxHeartbeat->isChecked());

View File

@ -36,6 +36,8 @@ class ServerConfigDialog : public QDialog, public Ui::ServerConfigDialogBase
public slots:
void accept();
void showEvent(QShowEvent* event);
void message(const QString& message) { m_Message = message; }
protected slots:
void on_m_pButtonNewHotkey_clicked();
@ -57,6 +59,7 @@ class ServerConfigDialog : public QDialog, public Ui::ServerConfigDialogBase
ServerConfig& m_OrigServerConfig;
ServerConfig m_ServerConfig;
ScreenSetupModel m_ScreenSetupModel;
QString m_Message;
};
#endif

View File

@ -105,13 +105,6 @@ bool SetupWizard::validateCurrentPage()
return false;
}
}
else if (m_pRadioButtonPremiumRegister->isChecked())
{
const QUrl url(QString(PREMIUM_REGISTER_URL));
QDesktopServices::openUrl(url);
m_pRadioButtonPremiumLogin->setChecked(true);
return false;
}
else if (m_pRadioButtonPremiumLater->isChecked())
{
return true;
@ -122,25 +115,6 @@ bool SetupWizard::validateCurrentPage()
return false;
}
}
else if (currentPage() == m_pCryptoPage)
{
if (m_pCheckBoxEnableCrypto->isChecked())
{
if (m_pLineEditCryptoPassword1->text().isEmpty())
{
message.setText(tr("Encryption password required."));
message.exec();
return false;
}
if (m_pLineEditCryptoPassword1->text() != m_pLineEditCryptoPassword2->text())
{
message.setText(tr("Encryption password and confirmation do not match."));
message.exec();
return false;
}
}
}
return true;
}
@ -169,8 +143,6 @@ void SetupWizard::accept()
{
AppConfig& appConfig = m_MainWindow.appConfig();
appConfig.setCryptoEnabled(m_pCheckBoxEnableCrypto->isChecked());
appConfig.setCryptoPass(m_pLineEditCryptoPassword1->text());
appConfig.setLanguage(m_pComboLanguage->itemData(m_pComboLanguage->currentIndex()).toString());
appConfig.setPremiumEmail(m_pLineEditPremiumEmail->text());
@ -205,6 +177,7 @@ void SetupWizard::accept()
if (m_StartMain)
{
m_MainWindow.updateZeroconfService();
m_MainWindow.open();
}
@ -225,14 +198,6 @@ void SetupWizard::reject()
void SetupWizard::on_m_pCheckBoxEnableCrypto_stateChanged(int )
{
bool enabled = m_pCheckBoxEnableCrypto->isChecked();
m_pLineEditCryptoPassword1->setEnabled(enabled);
m_pLineEditCryptoPassword2->setEnabled(enabled);
if (!enabled)
{
m_pLineEditCryptoPassword1->clear();
m_pLineEditCryptoPassword2->clear();
}
}
void SetupWizard::on_m_pComboLanguage_currentIndexChanged(int index)

View File

@ -0,0 +1,88 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014 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 "ZeroconfBrowser.h"
#include <QtCore/QSocketNotifier>
ZeroconfBrowser::ZeroconfBrowser(QObject* parent) :
QObject(parent),
m_DnsServiceRef(0),
m_pSocket(0)
{
}
ZeroconfBrowser::~ZeroconfBrowser()
{
if (m_DnsServiceRef) {
DNSServiceRefDeallocate(m_DnsServiceRef);
m_DnsServiceRef = 0;
}
}
void ZeroconfBrowser::browseForType(const QString& type)
{
DNSServiceErrorType err = DNSServiceBrowse(&m_DnsServiceRef, 0, 0,
type.toUtf8().constData(), 0, browseReply, this);
if (err != kDNSServiceErr_NoError) {
emit error(err);
}
else {
int sockFD = DNSServiceRefSockFD(m_DnsServiceRef);
if (sockFD == -1) {
emit error(kDNSServiceErr_Invalid);
}
else {
m_pSocket = new QSocketNotifier(sockFD, QSocketNotifier::Read, this);
connect(m_pSocket, SIGNAL(activated(int)), this,
SLOT(socketReadyRead()));
}
}
}
void ZeroconfBrowser::socketReadyRead()
{
DNSServiceErrorType err = DNSServiceProcessResult(m_DnsServiceRef);
if (err != kDNSServiceErr_NoError) {
emit error(err);
}
}
void ZeroconfBrowser::browseReply(DNSServiceRef, DNSServiceFlags flags,
quint32, DNSServiceErrorType errorCode, const char* serviceName,
const char* regType, const char* replyDomain, void* context)
{
ZeroconfBrowser* browser = static_cast<ZeroconfBrowser*>(context);
if (errorCode != kDNSServiceErr_NoError) {
emit browser->error(errorCode);
}
else {
ZeroconfRecord record(serviceName, regType, replyDomain);
if (flags & kDNSServiceFlagsAdd) {
if (!browser->m_Records.contains(record)) {
browser->m_Records.append(record);
}
}
else {
browser->m_Records.removeAll(record);
}
if (!(flags & kDNSServiceFlagsMoreComing)) {
emit browser->currentRecordsChanged(browser->m_Records);
}
}
}

View File

@ -0,0 +1,57 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014 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 "ZeroconfRecord.h"
#include <QtCore/QObject>
#define _MSL_STDINT_H
#include <stdint.h>
#include <dns_sd.h>
class QSocketNotifier;
class ZeroconfBrowser : public QObject
{
Q_OBJECT
public:
ZeroconfBrowser(QObject* parent = 0);
~ZeroconfBrowser();
void browseForType(const QString& type);
inline QList<ZeroconfRecord> currentRecords() const { return m_Records; }
inline QString serviceType() const { return m_BrowsingType; }
signals:
void currentRecordsChanged(const QList<ZeroconfRecord>& list);
void error(DNSServiceErrorType err);
private slots:
void socketReadyRead();
private:
static void DNSSD_API browseReply(DNSServiceRef, DNSServiceFlags flags,
quint32, DNSServiceErrorType errorCode, const char* serviceName,
const char* regType, const char* replyDomain, void* context);
private:
DNSServiceRef m_DnsServiceRef;
QSocketNotifier* m_pSocket;
QList<ZeroconfRecord> m_Records;
QString m_BrowsingType;
};

View File

@ -0,0 +1,50 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014 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 <QtCore/QMetaType>
#include <QtCore/QString>
class ZeroconfRecord
{
public:
ZeroconfRecord() {}
ZeroconfRecord(const QString& name, const QString& regType,
const QString& domain)
: serviceName(name), registeredType(regType), replyDomain(domain)
{}
ZeroconfRecord(const char* name, const char* regType, const char* domain)
{
serviceName = QString::fromUtf8(name);
registeredType = QString::fromUtf8(regType);
replyDomain = QString::fromUtf8(domain);
}
bool operator==(const ZeroconfRecord& other) const {
return serviceName == other.serviceName
&& registeredType == other.registeredType
&& replyDomain == other.replyDomain;
}
public:
QString serviceName;
QString registeredType;
QString replyDomain;
};
Q_DECLARE_METATYPE(ZeroconfRecord)

View File

@ -0,0 +1,89 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014 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 "ZeroconfRegister.h"
#include <QtCore/QSocketNotifier>
ZeroconfRegister::ZeroconfRegister(QObject* parent) :
QObject(parent),
m_DnsServiceRef(0),
m_pSocket(0)
{
}
ZeroconfRegister::~ZeroconfRegister()
{
if (m_DnsServiceRef) {
DNSServiceRefDeallocate(m_DnsServiceRef);
m_DnsServiceRef = 0;
}
}
void ZeroconfRegister::registerService(const ZeroconfRecord& record,
quint16 servicePort)
{
if (m_DnsServiceRef) {
qWarning("Warning: Already registered a service for this object");
return;
}
quint16 bigEndianPort = servicePort;
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
{
bigEndianPort = 0 | ((servicePort & 0x00ff) << 8) | ((servicePort & 0xff00) >> 8);
}
#endif
DNSServiceErrorType err = DNSServiceRegister(&m_DnsServiceRef, 0, 0,
record.serviceName.toUtf8().constData(),
record.registeredType.toUtf8().constData(),
record.replyDomain.isEmpty() ? 0 : record.replyDomain.toUtf8().constData(),
0, bigEndianPort, 0, 0, registerService, this);
if (err != kDNSServiceErr_NoError) {
emit error(err);
}
else {
int sockfd = DNSServiceRefSockFD(m_DnsServiceRef);
if (sockfd == -1) {
emit error(kDNSServiceErr_Invalid);
}
else {
m_pSocket = new QSocketNotifier(sockfd, QSocketNotifier::Read, this);
connect(m_pSocket, SIGNAL(activated(int)), this, SLOT(socketReadyRead()));
}
}
}
void ZeroconfRegister::socketReadyRead()
{
DNSServiceErrorType err = DNSServiceProcessResult(m_DnsServiceRef);
if (err != kDNSServiceErr_NoError) {
emit error(err);
}
}
void ZeroconfRegister::registerService(DNSServiceRef, DNSServiceFlags,
DNSServiceErrorType errorCode, const char* name, const char* regtype,
const char* domain, void* data)
{
ZeroconfRegister* serviceRegister = static_cast<ZeroconfRegister*>(data);
if (errorCode != kDNSServiceErr_NoError) {
emit serviceRegister->error(errorCode);
}
}

View File

@ -0,0 +1,61 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014 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 <QtCore/QObject>
#include "ZeroconfRecord.h"
class QSocketNotifier;
// Bonjour flags
#define _MSL_STDINT_H
#include <stdint.h>
#if defined(Q_OS_WIN)
#define WIN32_LEAN_AND_MEAN
#endif
#include <dns_sd.h>
class ZeroconfRegister : public QObject
{
Q_OBJECT
public:
ZeroconfRegister(QObject* parent = 0);
~ZeroconfRegister();
void registerService(const ZeroconfRecord& record, quint16 servicePort);
inline ZeroconfRecord registeredRecord() const { return finalRecord; }
signals:
void error(DNSServiceErrorType error);
void serviceRegistered(const ZeroconfRecord& record);
private slots:
void socketReadyRead();
private:
static void DNSSD_API registerService(DNSServiceRef sdRef,
DNSServiceFlags, DNSServiceErrorType errorCode, const char* name,
const char* regtype, const char* domain, void* context);
private:
DNSServiceRef m_DnsServiceRef;
QSocketNotifier* m_pSocket;
ZeroconfRecord finalRecord;
};

View File

@ -0,0 +1,33 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014 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 "ZeroconfServer.h"
#include "ZeroconfThread.h"
#include <stdlib.h>
ZeroconfServer::ZeroconfServer(QObject* parent) :
QTcpServer(parent)
{
}
void ZeroconfServer::incomingConnection(int socketDescriptor)
{
ZeroconfThread* thread = new ZeroconfThread(socketDescriptor, this);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
}

View File

@ -0,0 +1,37 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014 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 <QStringList>
#include <QTcpServer>
class ZeroconfRegister;
class ZeroconfServer : public QTcpServer
{
Q_OBJECT
public:
ZeroconfServer(QObject* parent = 0);
protected:
void incomingConnection(int socketDescriptor);
private:
QStringList fortunes;
};

View File

@ -0,0 +1,145 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014 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 "ZeroconfService.h"
#include "MainWindow.h"
#include "ZeroconfRegister.h"
#include "ZeroconfBrowser.h"
#include <QtNetwork>
#include <QMessageBox>
#define _MSL_STDINT_H
#include <stdint.h>
#include <dns_sd.h>
const char* ZeroconfService:: m_ServerServiceName = "_synergyServerZeroconf._tcp";
const char* ZeroconfService:: m_ClientServiceName = "_synergyClientZeroconf._tcp";
ZeroconfService::ZeroconfService(MainWindow* mainWindow) :
m_pMainWindow(mainWindow),
m_pZeroconfBrowser(0),
m_pZeroconfRegister(0),
m_ServiceRegistered(false)
{
if (m_pMainWindow->synergyType() == MainWindow::synergyServer) {
if (registerService(true)) {
m_pZeroconfBrowser = new ZeroconfBrowser(this);
connect(m_pZeroconfBrowser, SIGNAL(
currentRecordsChanged(const QList<ZeroconfRecord>&)),
this, SLOT(clientDetected(const QList<ZeroconfRecord>&)));
m_pZeroconfBrowser->browseForType(
QLatin1String(m_ClientServiceName));
}
}
else {
m_pZeroconfBrowser = new ZeroconfBrowser(this);
connect(m_pZeroconfBrowser, SIGNAL(
currentRecordsChanged(const QList<ZeroconfRecord>&)),
this, SLOT(serverDetected(const QList<ZeroconfRecord>&)));
m_pZeroconfBrowser->browseForType(
QLatin1String(m_ServerServiceName));
}
connect(m_pZeroconfBrowser, SIGNAL(error(DNSServiceErrorType)),
this, SLOT(errorHandle(int32_t)));
}
ZeroconfService::~ZeroconfService()
{
if (m_pZeroconfBrowser) {
delete m_pZeroconfBrowser;
}
if (m_pZeroconfRegister) {
delete m_pZeroconfRegister;
}
}
void ZeroconfService::serverDetected(const QList<ZeroconfRecord>& list)
{
foreach (ZeroconfRecord record, list) {
registerService(false);
m_pMainWindow->m_pLineEditHostname->setText(record.serviceName);
m_pMainWindow->appendLogNote(tr("zeroconf server detected: %1").arg(
record.serviceName));
}
if (!list.isEmpty()) {
m_pMainWindow->startSynergy();
}
}
void ZeroconfService::clientDetected(const QList<ZeroconfRecord>& list)
{
foreach (ZeroconfRecord record, list) {
m_pMainWindow->appendLogNote(tr("zeroconf client detected: %1").arg(
record.serviceName));
m_pMainWindow->autoAddScreen(record.serviceName);
}
if (!list.isEmpty()) {
m_pMainWindow->startSynergy();
}
}
void ZeroconfService::errorHandle(int32_t errorCode)
{
QMessageBox::critical(0, tr("Zero configuration service"),
tr("Error code: %1.").arg(errorCode));
}
QString ZeroconfService::getLocalIPAddresses()
{
foreach (const QHostAddress& address, QNetworkInterface::allAddresses()) {
if (address.protocol() == QAbstractSocket::IPv4Protocol && address != QHostAddress(QHostAddress::LocalHost))
return address.toString();
}
return "";
}
bool ZeroconfService::registerService(bool server)
{
bool result = true;
if (!m_ServiceRegistered) {
if (!m_zeroconfServer.listen()) {
QMessageBox::critical(0, tr("Zero configuration service"),
tr("Unable to start the zeroconf: %1.")
.arg(m_zeroconfServer.errorString()));
result = false;
}
else {
m_pZeroconfRegister = new ZeroconfRegister(this);
if (server) {
m_pZeroconfRegister->registerService(
ZeroconfRecord(tr("%1").arg(getLocalIPAddresses()),
QLatin1String(m_ServerServiceName), QString()),
m_zeroconfServer.serverPort());
}
else {
m_pZeroconfRegister->registerService(
ZeroconfRecord(tr("%1").arg(m_pMainWindow->getScreenName()),
QLatin1String(m_ClientServiceName), QString()),
m_zeroconfServer.serverPort());
}
m_ServiceRegistered = true;
}
}
return result;
}

View File

@ -0,0 +1,55 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014 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 "ZeroconfServer.h"
#include "ZeroconfRecord.h"
#include <QtCore/QObject>
class ZeroconfRegister;
class ZeroconfBrowser;
class MainWindow;
class ZeroconfService : public QObject
{
Q_OBJECT
public:
ZeroconfService(MainWindow* mainWindow);
~ZeroconfService();
private slots:
void serverDetected(const QList<ZeroconfRecord>& list);
void clientDetected(const QList<ZeroconfRecord>& list);
void errorHandle(int32_t errorCode);
private:
QString getLocalIPAddresses();
bool registerService(bool server);
private:
MainWindow* m_pMainWindow;
ZeroconfServer m_zeroconfServer;
ZeroconfBrowser* m_pZeroconfBrowser;
ZeroconfRegister* m_pZeroconfRegister;
bool m_ServiceRegistered;
static const char* m_ServerServiceName;
static const char* m_ClientServiceName;
};

View File

@ -0,0 +1,38 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014 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 "ZeroconfThread.h"
#include <QtNetwork>
ZeroconfThread::ZeroconfThread(int socketDescriptor, QObject* parent) :
QThread(parent),
m_SocketDescriptor(socketDescriptor)
{
}
void ZeroconfThread::run()
{
QTcpSocket tcpSocket;
if (!tcpSocket.setSocketDescriptor(m_SocketDescriptor)) {
emit error(tcpSocket.error());
return;
}
tcpSocket.disconnectFromHost();
tcpSocket.waitForDisconnected();
}

View File

@ -0,0 +1,38 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014 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 <QThread>
#include <QTcpSocket>
class ZeroconfThread : public QThread
{
Q_OBJECT
public:
ZeroconfThread(int socketDescriptor, QObject* parent);
void run();
signals:
void error(QTcpSocket::SocketError socketError);
private:
int m_SocketDescriptor;
QString m_Text;
};