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 1.5.1
===== =====
Bug #3307 - Configuration file paths containing spaces don't work 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/Ipc.cpp \
src/SynergyLocale.cpp \ src/SynergyLocale.cpp \
src/QUtility.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 \ HEADERS += src/MainWindow.h \
src/AboutDialog.h \ src/AboutDialog.h \
src/ServerConfig.h \ src/ServerConfig.h \
@ -69,7 +74,13 @@ HEADERS += src/MainWindow.h \
src/Ipc.h \ src/Ipc.h \
src/SynergyLocale.h \ src/SynergyLocale.h \
src/QUtility.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 RESOURCES += res/Synergy.qrc
RC_FILE = res/win/Synergy.rc RC_FILE = res/win/Synergy.rc
macx { macx {
@ -82,6 +93,9 @@ macx {
QMAKE_BUNDLE_DATA += QSYNERGY_ICON QMAKE_BUNDLE_DATA += QSYNERGY_ICON
LIBS += $$MACX_LIBS LIBS += $$MACX_LIBS
} }
unix:!macx {
LIBS += -ldns_sd
}
debug { debug {
OBJECTS_DIR = tmp/debug OBJECTS_DIR = tmp/debug
MOC_DIR = tmp/debug MOC_DIR = tmp/debug
@ -95,5 +109,7 @@ release {
win32 { win32 {
Debug:DESTDIR = ../../bin/Debug Debug:DESTDIR = ../../bin/Debug
Release:DESTDIR = ../../bin/Release Release:DESTDIR = ../../bin/Release
LIBS += -L"../../ext/bonjour/x64" -ldnssd
INCLUDEPATH += "$(BONJOUR_SDK_HOME)/Include"
} }
else:DESTDIR = ../../bin else:DESTDIR = ../../bin

View File

@ -252,7 +252,7 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="title"> <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>
<property name="checkable"> <property name="checkable">
<bool>true</bool> <bool>true</bool>

View File

@ -128,7 +128,7 @@
<item> <item>
<widget class="QRadioButton" name="m_pRadioButtonPremiumLogin"> <widget class="QRadioButton" name="m_pRadioButtonPremiumLogin">
<property name="text"> <property name="text">
<string>Yes, I have Synergy Premium</string> <string>I donated to Synergy and have a premium login...</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -289,33 +289,10 @@
</property> </property>
</spacer> </spacer>
</item> </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> <item>
<widget class="QRadioButton" name="m_pRadioButtonPremiumLater"> <widget class="QRadioButton" name="m_pRadioButtonPremiumLater">
<property name="text"> <property name="text">
<string>Not interested</string> <string>No, I have not donated to Synergy, skip this step</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -360,7 +337,7 @@
</font> </font>
</property> </property>
<property name="text"> <property name="text">
<string>&amp;Server (new setup)</string> <string>&amp;Server (share this computer's mouse and keyboard)</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -373,7 +350,11 @@
</size> </size>
</property> </property>
<property name="text"> <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>
<property name="wordWrap"> <property name="wordWrap">
<bool>true</bool> <bool>true</bool>
@ -405,7 +386,7 @@
</font> </font>
</property> </property>
<property name="text"> <property name="text">
<string>&amp;Client (add to setup)</string> <string>&amp;Client (use another computer's mouse and keyboard)</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -418,7 +399,11 @@
</size> </size>
</property> </property>
<property name="text"> <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>
<property name="wordWrap"> <property name="wordWrap">
<bool>true</bool> <bool>true</bool>
@ -443,225 +428,15 @@
</item> </item>
</layout> </layout>
</widget> </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> </widget>
<tabstops> <tabstops>
<tabstop>m_pComboLanguage</tabstop> <tabstop>m_pComboLanguage</tabstop>
<tabstop>m_pRadioButtonPremiumLogin</tabstop> <tabstop>m_pRadioButtonPremiumLogin</tabstop>
<tabstop>m_pLineEditPremiumEmail</tabstop> <tabstop>m_pLineEditPremiumEmail</tabstop>
<tabstop>m_pLineEditPremiumPassword</tabstop> <tabstop>m_pLineEditPremiumPassword</tabstop>
<tabstop>m_pRadioButtonPremiumRegister</tabstop>
<tabstop>m_pRadioButtonPremiumLater</tabstop> <tabstop>m_pRadioButtonPremiumLater</tabstop>
<tabstop>m_pServerRadioButton</tabstop> <tabstop>m_pServerRadioButton</tabstop>
<tabstop>m_pClientRadioButton</tabstop> <tabstop>m_pClientRadioButton</tabstop>
<tabstop>m_pLineEditCryptoPassword1</tabstop>
<tabstop>m_pLineEditCryptoPassword2</tabstop>
</tabstops> </tabstops>
<resources/> <resources/>
<connections/> <connections/>

View File

@ -25,6 +25,7 @@
#include "ServerConfigDialog.h" #include "ServerConfigDialog.h"
#include "SettingsDialog.h" #include "SettingsDialog.h"
#include "SetupWizard.h" #include "SetupWizard.h"
#include "ZeroconfService.h"
#include <QtCore> #include <QtCore>
#include <QtGui> #include <QtGui>
@ -64,7 +65,7 @@ MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) :
m_AppConfig(appConfig), m_AppConfig(appConfig),
m_pSynergy(NULL), m_pSynergy(NULL),
m_SynergyState(synergyDisconnected), m_SynergyState(synergyDisconnected),
m_ServerConfig(&m_Settings, 5, 3), m_ServerConfig(&m_Settings, 5, 3, m_AppConfig.screenName()),
m_pTempConfigFile(NULL), m_pTempConfigFile(NULL),
m_pTrayIcon(NULL), m_pTrayIcon(NULL),
m_pTrayIconMenu(NULL), m_pTrayIconMenu(NULL),
@ -75,7 +76,8 @@ MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) :
m_pMenuFile(NULL), m_pMenuFile(NULL),
m_pMenuEdit(NULL), m_pMenuEdit(NULL),
m_pMenuWindow(NULL), m_pMenuWindow(NULL),
m_pMenuHelp(NULL) m_pMenuHelp(NULL),
m_pZeroconfService(NULL)
{ {
setupUi(this); setupUi(this);
@ -107,16 +109,20 @@ MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) :
resize(700, 530); resize(700, 530);
setMinimumSize(size()); setMinimumSize(size());
#endif #endif
updateZeroconfService();
} }
MainWindow::~MainWindow() MainWindow::~MainWindow()
{ {
if (appConfig().processMode() == Desktop) if (appConfig().processMode() == Desktop) {
{
stopDesktop(); stopDesktop();
} }
saveSettings(); saveSettings();
delete m_pZeroconfService;
} }
void MainWindow::open() void MainWindow::open()
@ -382,13 +388,13 @@ void MainWindow::startSynergy()
args << "-f" << "--no-tray" << "--debug" << appConfig().logLevelText(); args << "-f" << "--no-tray" << "--debug" << appConfig().logLevelText();
if (!appConfig().screenName().isEmpty())
args << "--name" << appConfig().screenName();
if (appConfig().cryptoEnabled()) args << "--name" << getScreenName();
{
args << "--crypto-pass" << appConfig().cryptoPass(); if (appConfig().cryptoEnabled())
} {
args << "--crypto-pass" << appConfig().cryptoPass();
}
if (desktopMode) if (desktopMode)
{ {
@ -553,7 +559,8 @@ QString MainWindow::configFilename()
QString MainWindow::address() 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) 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() bool MainWindow::on_m_pButtonBrowseConfigFile_clicked()
{ {
QString fileName = QFileDialog::getOpenFileName(this, tr("Browse for a synergys config file"), QString(), synergyConfigFilter); 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()); ServerConfigDialog dlg(this, serverConfig(), appConfig().screenName());
dlg.message(message);
dlg.exec(); dlg.exec();
} }
void MainWindow::on_m_pButtonConfigureServer_clicked()
{
showConfigureServer();
}
void MainWindow::on_m_pActionWizard_triggered() void MainWindow::on_m_pActionWizard_triggered()
{ {
SetupWizard wizard(*this, false); SetupWizard wizard(*this, false);

View File

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

View File

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

View File

@ -28,18 +28,21 @@ static const struct
const char* name; const char* name;
} neighbourDirs[] = } neighbourDirs[] =
{ {
{ 0, -1, "up" },
{ 1, 0, "right" }, { 1, 0, "right" },
{ 0, 1, "down" },
{ -1, 0, "left" }, { -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_pSettings(settings),
m_Screens(), m_Screens(),
m_NumColumns(numColumns), m_NumColumns(numColumns),
m_NumRows(numRows) m_NumRows(numRows),
m_ServerName(serverName)
{ {
Q_ASSERT(m_pSettings); Q_ASSERT(m_pSettings);
@ -263,3 +266,62 @@ int ServerConfig::numScreens() const
return rval; 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); friend QTextStream& operator<<(QTextStream& outStream, const ServerConfig& config);
public: public:
ServerConfig(QSettings* settings, int numColumns, int numRows); ServerConfig(QSettings* settings, int numColumns, int numRows, QString serverName);
~ServerConfig(); ~ServerConfig();
public: public:
@ -64,6 +64,7 @@ class ServerConfig : public BaseConfig
bool save(const QString& fileName) const; bool save(const QString& fileName) const;
void save(QFile& file) const; void save(QFile& file) const;
int numScreens() const; int numScreens() const;
int autoAddScreen(const QString name);
protected: protected:
QSettings& settings() { return *m_pSettings; } QSettings& settings() { return *m_pSettings; }
@ -89,6 +90,10 @@ class ServerConfig : public BaseConfig
void init(); void init();
int adjacentScreenIndex(int idx, int deltaColumn, int deltaRow) const; 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: private:
QSettings* m_pSettings; QSettings* m_pSettings;
ScreenList m_Screens; ScreenList m_Screens;
@ -106,9 +111,16 @@ class ServerConfig : public BaseConfig
int m_SwitchCornerSize; int m_SwitchCornerSize;
QList<bool> m_SwitchCorners; QList<bool> m_SwitchCorners;
HotkeyList m_Hotkeys; HotkeyList m_Hotkeys;
QString m_ServerName;
}; };
QTextStream& operator<<(QTextStream& outStream, const ServerConfig& config); QTextStream& operator<<(QTextStream& outStream, const ServerConfig& config);
enum {
kAutoAddScreenOk,
kAutoAddScreenNoServer,
kAutoAddScreenNoSpace
};
#endif #endif

View File

@ -23,13 +23,15 @@
#include <QtCore> #include <QtCore>
#include <QtGui> #include <QtGui>
#include <QMessageBox>
ServerConfigDialog::ServerConfigDialog(QWidget* parent, ServerConfig& config, const QString& defaultScreenName) : ServerConfigDialog::ServerConfigDialog(QWidget* parent, ServerConfig& config, const QString& defaultScreenName) :
QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint), QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint),
Ui::ServerConfigDialogBase(), Ui::ServerConfigDialogBase(),
m_OrigServerConfig(config), m_OrigServerConfig(config),
m_ServerConfig(config), m_ServerConfig(config),
m_ScreenSetupModel(serverConfig().screens(), serverConfig().numColumns(), serverConfig().numRows()) m_ScreenSetupModel(serverConfig().screens(), serverConfig().numColumns(), serverConfig().numRows()),
m_Message("")
{ {
setupUi(this); setupUi(this);
@ -61,6 +63,17 @@ ServerConfigDialog::ServerConfigDialog(QWidget* parent, ServerConfig& config, co
model().screen(serverConfig().numColumns() / 2, serverConfig().numRows() / 2) = Screen(defaultScreenName); 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() void ServerConfigDialog::accept()
{ {
serverConfig().haveHeartbeat(m_pCheckBoxHeartbeat->isChecked()); serverConfig().haveHeartbeat(m_pCheckBoxHeartbeat->isChecked());

View File

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

View File

@ -105,13 +105,6 @@ bool SetupWizard::validateCurrentPage()
return false; 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()) else if (m_pRadioButtonPremiumLater->isChecked())
{ {
return true; return true;
@ -122,25 +115,6 @@ bool SetupWizard::validateCurrentPage()
return false; 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; return true;
} }
@ -169,8 +143,6 @@ void SetupWizard::accept()
{ {
AppConfig& appConfig = m_MainWindow.appConfig(); 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.setLanguage(m_pComboLanguage->itemData(m_pComboLanguage->currentIndex()).toString());
appConfig.setPremiumEmail(m_pLineEditPremiumEmail->text()); appConfig.setPremiumEmail(m_pLineEditPremiumEmail->text());
@ -205,6 +177,7 @@ void SetupWizard::accept()
if (m_StartMain) if (m_StartMain)
{ {
m_MainWindow.updateZeroconfService();
m_MainWindow.open(); m_MainWindow.open();
} }
@ -225,14 +198,6 @@ void SetupWizard::reject()
void SetupWizard::on_m_pCheckBoxEnableCrypto_stateChanged(int ) 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) 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;
};