summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton <anton@picapica>2017-12-30 21:06:08 +0400
committerAnton <anton@picapica>2017-12-30 21:06:08 +0400
commitfe90bf0b2eb78f74836b6ab7832aa06e6d48b673 (patch)
tree206e168819d1dde81d29d8e11ab22c33646de0de
parent87c68a2ecadee7c86d80b585a2ed47b352c7b2d6 (diff)
downloadpica-pica-fe90bf0b2eb78f74836b6ab7832aa06e6d48b673.tar.gz
pica-pica-fe90bf0b2eb78f74836b6ab7832aa06e6d48b673.zip
pica-client: implemented autoconfiguration of address for direct incoming connections
-rw-r--r--Makefile.am3
-rw-r--r--PICA_netconf.h9
-rw-r--r--pica-client/dialogs/settingsdialog.cpp50
-rw-r--r--pica-client/dialogs/settingsdialog.h4
-rw-r--r--pica-client/pica-client.pro11
-rw-r--r--pica-client/skynet.cpp28
6 files changed, 97 insertions, 8 deletions
diff --git a/Makefile.am b/Makefile.am
index ec75613..c60d6b1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -111,7 +111,8 @@ PICA_client.h \
PICA_msgproc.c \
PICA_msgproc.h \
PICA_common.h PICA_proto.h \
-PICA_id.c PICA_id.h
+PICA_id.c PICA_id.h \
+PICA_netconf.c PICA_netconf.h
nodist_pica_client_pica_client_SOURCES = \
moc_accountswindow.cpp \
diff --git a/PICA_netconf.h b/PICA_netconf.h
index 13b4044..8e779b6 100644
--- a/PICA_netconf.h
+++ b/PICA_netconf.h
@@ -4,6 +4,7 @@
#ifndef WIN32
#include <netinet/in.h>
+#include <arpa/inet.h>
#else
@@ -19,6 +20,10 @@ typedef u_long in_addr_t;
typedef u_short in_port_t;
#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
+
int PICA_is_reserved_addr_ipv4(in_addr_t);
in_addr_t PICA_guess_listening_addr_ipv4();
@@ -27,5 +32,9 @@ in_addr_t PICA_guess_listening_addr_ipv4();
int PICA_upnp_autoconfigure_ipv4(int public_port, int local_port, char *public_ip);
#endif
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/pica-client/dialogs/settingsdialog.cpp b/pica-client/dialogs/settingsdialog.cpp
index d16bb63..1bd7812 100644
--- a/pica-client/dialogs/settingsdialog.cpp
+++ b/pica-client/dialogs/settingsdialog.cpp
@@ -1,6 +1,7 @@
#include "settingsdialog.h"
#include "../settings.h"
#include "../globals.h"
+#include "../../PICA_netconf.h"
#include <QGroupBox>
#include <QVBoxLayout>
@@ -28,6 +29,11 @@ SettingsDialog::SettingsDialog(QWidget *parent) :
rbEnableOutgoingConns = new QRadioButton(tr("Connect to the remote peer directly if possible"), this);
rbEnableIncomingConns = new QRadioButton(tr("Enable incoming direct connections"), this);
+#ifdef HAVE_LIBMINIUPNPC
+ cbEnableUPnP = new QCheckBox(tr("Enable UPnP"));
+ cbEnableUPnP->setChecked(true);
+#endif
+
rbEnableIncomingConns->setChecked(true);
connect(rbEnableIncomingConns, SIGNAL(toggled(bool)), this, SLOT(toggleIncomingConnections(bool)));
@@ -49,6 +55,8 @@ SettingsDialog::SettingsDialog(QWidget *parent) :
QList<QHostAddress> hostIfAddrs = QNetworkInterface::allAddresses();
QHostAddress ifAddr;
+ addr->addItem(QString("autoconfigure"));
+
foreach (ifAddr, hostIfAddrs)
if (ifAddr.protocol() == QAbstractSocket::IPv4Protocol)
addr->addItem(ifAddr.toString());
@@ -57,6 +65,9 @@ SettingsDialog::SettingsDialog(QWidget *parent) :
directc2cLayout->addWidget(rbDisableDirectConns);
directc2cLayout->addWidget(rbEnableOutgoingConns);
directc2cLayout->addWidget(rbEnableIncomingConns);
+#ifdef HAVE_LIBMINIUPNPC
+ directc2cLayout->addWidget(cbEnableUPnP);
+#endif
directc2cLayout->addWidget(lbAddr);
directc2cLayout->addWidget(addr);
directc2cLayout->addWidget(lbPubPort);
@@ -99,6 +110,9 @@ void SettingsDialog::toggleIncomingConnections(bool checked)
addr->setEnabled(checked);
publicPort->setEnabled(checked);
localPort->setEnabled(checked);
+#ifdef HAVE_LIBMINIUPNPC
+ cbEnableUPnP->setEnabled(checked);
+#endif
}
void SettingsDialog::OK()
@@ -139,7 +153,37 @@ void SettingsDialog::loadSettings()
break;
}
- addr->lineEdit()->setText(st.loadValue("direct_c2c.public_addr", "0.0.0.0").toString());
+#ifdef HAVE_LIBMINIUPNPC
+ cbEnableUPnP->setChecked(st.loadValue("direct_c2c.upnp_enabled", 1).toBool());
+#endif
+
+ addr->lineEdit()->setText(st.loadValue("direct_c2c.public_addr", "autoconfigure").toString());
+
+ if (addr->lineEdit()->text().contains(QString("autoconfigure")))
+ {
+ in_addr_t guess;
+ struct in_addr in;
+
+ guess = PICA_guess_listening_addr_ipv4();
+ in.s_addr = guess;
+ addr->lineEdit()->setText(QString("autoconfigured(%1)").arg(inet_ntoa(in)));
+
+#ifdef HAVE_LIBMINIUPNPC
+ if (cbEnableUPnP->isChecked() && PICA_is_reserved_addr_ipv4(guess))
+ {
+ int ret;
+ char public_ip[64];
+ ret = PICA_upnp_autoconfigure_ipv4(st.loadValue("direct_c2c.public_port", 2298).toInt(),
+ st.loadValue("direct_c2c.local_port", 2298).toInt(),
+ public_ip);
+
+ if (ret)
+ {
+ addr->lineEdit()->setText(QString("autoconfigured(%1)").arg(public_ip));
+ }
+ }
+#endif
+ }
publicPort->setValue(st.loadValue("direct_c2c.public_port", 2298).toInt());
localPort->setValue(st.loadValue("direct_c2c.local_port", 2298).toInt());
@@ -162,6 +206,10 @@ void SettingsDialog::storeSettings()
st.storeValue("direct_c2c.state", QString::number(c2c_state));
+#ifdef HAVE_LIBMINIUPNPC
+ st.storeValue("direct_c2c.upnp_enabled", cbEnableUPnP->isChecked() ? "1" : "0");
+#endif
+
st.storeValue("direct_c2c.public_addr", addr->lineEdit()->text());
st.storeValue("direct_c2c.public_port", QString::number(publicPort->value()));
st.storeValue("direct_c2c.local_port", QString::number(localPort->value()));
diff --git a/pica-client/dialogs/settingsdialog.h b/pica-client/dialogs/settingsdialog.h
index f0ab0cd..233fd3e 100644
--- a/pica-client/dialogs/settingsdialog.h
+++ b/pica-client/dialogs/settingsdialog.h
@@ -7,6 +7,7 @@
#include <QSpinBox>
#include <QRadioButton>
#include <QComboBox>
+#include <QCheckBox>
class SettingsDialog : public QDialog
{
@@ -23,6 +24,9 @@ private:
QRadioButton *rbDisableDirectConns;
QRadioButton *rbEnableOutgoingConns;
QRadioButton *rbEnableIncomingConns;
+#ifdef HAVE_LIBMINIUPNPC
+ QCheckBox *cbEnableUPnP;
+#endif
QComboBox *addr;
QSpinBox *publicPort;
diff --git a/pica-client/pica-client.pro b/pica-client/pica-client.pro
index ef9f9fd..205d215 100644
--- a/pica-client/pica-client.pro
+++ b/pica-client/pica-client.pro
@@ -38,7 +38,8 @@ SOURCES += main.cpp\
filetransfercontroller.cpp \
sound.cpp \
dialogs/settingsdialog.cpp \
- settings.cpp
+ settings.cpp \
+ ../PICA_netconf.c
HEADERS += mainwindow.h \
chatwindow.h \
@@ -70,10 +71,12 @@ HEADERS += mainwindow.h \
filetransfercontroller.h \
sound.h \
dialogs/settingsdialog.h \
- settings.h
+ settings.h \
+ ../PICA_netconf.h
DEFINES = PICA_MULTITHREADED
+DEFINES += HAVE_LIBMINIUPNPC
FORMS += mainwindow.ui
@@ -85,6 +88,4 @@ unix: PKGCONFIG += libssl
unix: CONFIG += link_pkgconfig
unix: PKGCONFIG += libcrypto
-
-
-
+unix|win32: LIBS += -lminiupnpc
diff --git a/pica-client/skynet.cpp b/pica-client/skynet.cpp
index 8e22635..d2abb64 100644
--- a/pica-client/skynet.cpp
+++ b/pica-client/skynet.cpp
@@ -11,6 +11,7 @@
#include "dhparam.h"
#include "askpassword.h"
#include "settings.h"
+#include "../PICA_netconf.h"
SkyNet::SkyNet()
: nodes(config_dbname), QObject(0)
@@ -345,9 +346,34 @@ void SkyNet::Join(Accounts::AccountRecord &accrec)
{
int pub_port = st.loadValue("direct_c2c.public_port", 2298).toInt();
int loc_port = st.loadValue("direct_c2c.local_port", 2298).toInt();
+ QString public_addr = st.loadValue("direct_c2c.public_addr", "autoconfigure").toString();
+
+ if (public_addr.contains("autoconfigure"))
+ {
+ in_addr_t guess;
+ struct in_addr in;
+
+ guess = PICA_guess_listening_addr_ipv4();
+ in.s_addr = guess;
+ public_addr = QString(inet_ntoa(in));
+#ifdef HAVE_LIBMINIUPNPC
+ if (st.loadValue("direct_c2c.upnp_enabled", 1).toBool() && PICA_is_reserved_addr_ipv4(guess))
+ {
+ int ret;
+ char public_ip[64];
+ ret = PICA_upnp_autoconfigure_ipv4(pub_port, loc_port, public_ip);
+
+ if (ret)
+ {
+ public_addr = QString(public_ip);
+ }
+ }
+#endif
+ emit StatusMsg(QString(tr("Using autoconfigured address %1 port %2 for incoming direct connections")).arg(public_addr).arg(pub_port), false);
+ }
int ret = PICA_new_listener(acc,
- st.loadValue("direct_c2c.public_addr", "0.0.0.0").toString().toAscii().constData(),
+ public_addr.toAscii().constData(),
pub_port,
loc_port, &listener);
if (ret != PICA_OK)