Feature: Ostinato client now accepts hostnames for drones and does DNS resolution for the same; IPv6 addresses are also accepted. Introduced Drone setting to listen to specific or 'any' IPv4 (or IPv6) address

Fixes #152
This commit is contained in:
Srivats P 2015-11-06 18:57:07 +05:30
parent 01e8524491
commit efdfa7f95d
10 changed files with 65 additions and 30 deletions

View File

@ -37,7 +37,7 @@ extern char *version;
quint32 PortGroup::mPortGroupAllocId = 0; quint32 PortGroup::mPortGroupAllocId = 0;
PortGroup::PortGroup(QHostAddress ip, quint16 port) PortGroup::PortGroup(QString serverName, quint16 port)
{ {
// Allocate an id for self // Allocate an id for self
mPortGroupId = PortGroup::mPortGroupAllocId++; mPortGroupId = PortGroup::mPortGroupAllocId++;
@ -57,7 +57,7 @@ PortGroup::PortGroup(QHostAddress ip, quint16 port)
connect(reconnectTimer, SIGNAL(timeout()), connect(reconnectTimer, SIGNAL(timeout()),
this, SLOT(on_reconnectTimer_timeout())); this, SLOT(on_reconnectTimer_timeout()));
rpcChannel = new PbRpcChannel(ip, port, rpcChannel = new PbRpcChannel(serverName, port,
OstProto::Notification::default_instance()); OstProto::Notification::default_instance());
serviceStub = new OstProto::OstService::Stub(rpcChannel); serviceStub = new OstProto::OstService::Stub(rpcChannel);
@ -272,7 +272,7 @@ void PortGroup::when_portListChanged(quint32 /*portGroupId*/)
"For more information see " "For more information see "
"http://code.google.com/p/ostinato/wiki/FAQ#" "http://code.google.com/p/ostinato/wiki/FAQ#"
"Q._Port_group_has_no_interfaces") "Q._Port_group_has_no_interfaces")
.arg(serverAddress().toString()) .arg(serverName())
.arg(int(serverPort()))); .arg(int(serverPort())));
} }
} }

View File

@ -66,7 +66,7 @@ public: // FIXME(HIGH): member access
QList<Port*> mPorts; QList<Port*> mPorts;
public: public:
PortGroup(QHostAddress ip = QHostAddress::LocalHost, PortGroup(QString serverName = "127.0.0.1",
quint16 port = DEFAULT_SERVER_PORT); quint16 port = DEFAULT_SERVER_PORT);
~PortGroup(); ~PortGroup();
@ -75,10 +75,10 @@ public:
compat = kUnknown; compat = kUnknown;
rpcChannel->establish(); rpcChannel->establish();
} }
void connectToHost(QHostAddress ip, quint16 port) { void connectToHost(QString serverName, quint16 port) {
reconnect = true; reconnect = true;
compat = kUnknown; compat = kUnknown;
rpcChannel->establish(ip, port); rpcChannel->establish(serverName, port);
} }
void disconnectFromHost() { reconnect = false; rpcChannel->tearDown(); } void disconnectFromHost() { reconnect = false; rpcChannel->tearDown(); }
@ -88,8 +88,8 @@ public:
const QString& userAlias() const { return mUserAlias; } const QString& userAlias() const { return mUserAlias; }
void setUserAlias(QString alias) { mUserAlias = alias; }; void setUserAlias(QString alias) { mUserAlias = alias; };
const QHostAddress& serverAddress() const const QString serverName() const
{ return rpcChannel->serverAddress(); } { return rpcChannel->serverName(); }
quint16 serverPort() const quint16 serverPort() const
{ return rpcChannel->serverPort(); } { return rpcChannel->serverPort(); }
QAbstractSocket::SocketState state() const { QAbstractSocket::SocketState state() const {

View File

@ -121,10 +121,10 @@ QVariant PortModel::data(const QModelIndex &index, int role) const
if ((role == Qt::DisplayRole)) if ((role == Qt::DisplayRole))
{ {
DBG0("Exit PortModel data 1\n"); DBG0("Exit PortModel data 1\n");
return QString("Port Group %1: %2 [%3:%4] (%5)"). return QString("Port Group %1: %2 [%3]:%4 (%5)").
arg(pgl->mPortGroups.at(index.row())->id()). arg(pgl->mPortGroups.at(index.row())->id()).
arg(pgl->mPortGroups.at(index.row())->userAlias()). arg(pgl->mPortGroups.at(index.row())->userAlias()).
arg(pgl->mPortGroups.at(index.row())->serverAddress().toString()). arg(pgl->mPortGroups.at(index.row())->serverName()).
arg(pgl->mPortGroups.at(index.row())->serverPort()). arg(pgl->mPortGroups.at(index.row())->serverPort()).
arg(pgl->mPortGroups.value(index.row())->numPorts()); arg(pgl->mPortGroups.value(index.row())->numPorts());
} }

View File

@ -503,15 +503,29 @@ void PortsWindow::on_actionNew_Port_Group_triggered()
{ {
bool ok; bool ok;
QString text = QInputDialog::getText(this, QString text = QInputDialog::getText(this,
"Add Port Group", "Port Group Address (IP[:Port])", "Add Port Group", "Port Group Address (HostName[:Port])",
QLineEdit::Normal, lastNewPortGroup, &ok); QLineEdit::Normal, lastNewPortGroup, &ok);
if (ok) if (ok)
{ {
QStringList addr = text.split(":"); QStringList addr = text.split(":");
if (addr.size() == 1) // Port unspecified quint16 port = DEFAULT_SERVER_PORT;
addr.append(QString().setNum(DEFAULT_SERVER_PORT));
PortGroup *pg = new PortGroup(QHostAddress(addr[0]),addr[1].toUShort()); if (addr.size() > 2) { // IPv6 Address
// IPv6 addresses with port number SHOULD be specified as
// [2001:db8::1]:80 (RFC5952 Sec6) to avoid ambiguity due to ':'
addr = text.split("]:");
if (addr.size() > 1)
port = addr[1].toUShort();
}
else if (addr.size() == 2) // Hostname/IPv4 + Port specified
port = addr[1].toUShort();
// Play nice and remove square brackets irrespective of addr type
addr[0].remove(QChar('['));
addr[0].remove(QChar(']'));
PortGroup *pg = new PortGroup(addr[0], port);
plm->addPortGroup(*pg); plm->addPortGroup(*pg);
lastNewPortGroup = text; lastNewPortGroup = text;
} }

View File

@ -25,7 +25,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
static uchar msgBuf[4096]; static uchar msgBuf[4096];
PbRpcChannel::PbRpcChannel(QHostAddress ip, quint16 port, PbRpcChannel::PbRpcChannel(QString serverName, quint16 port,
const ::google::protobuf::Message &notifProto) const ::google::protobuf::Message &notifProto)
: notifPrototype(notifProto) : notifPrototype(notifProto)
{ {
@ -36,7 +36,7 @@ PbRpcChannel::PbRpcChannel(QHostAddress ip, quint16 port,
done = NULL; done = NULL;
response = NULL; response = NULL;
mServerAddress = ip; mServerHost = serverName;
mServerPort = port; mServerPort = port;
mpSocket = new QTcpSocket(this); mpSocket = new QTcpSocket(this);
@ -75,12 +75,12 @@ void PbRpcChannel::establish()
{ {
qDebug("In %s", __FUNCTION__); qDebug("In %s", __FUNCTION__);
mpSocket->connectToHost(mServerAddress, mServerPort); mpSocket->connectToHost(mServerHost, mServerPort);
} }
void PbRpcChannel::establish(QHostAddress ip, quint16 port) void PbRpcChannel::establish(QString serverName, quint16 port)
{ {
mServerAddress = ip; mServerHost = serverName;
mServerPort = port; mServerPort = port;
establish(); establish();
} }

View File

@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#ifndef _PB_RPC_CHANNEL_H #ifndef _PB_RPC_CHANNEL_H
#define _PB_RPC_CHANNEL_H #define _PB_RPC_CHANNEL_H
#include <QString>
#include <QTcpServer> #include <QTcpServer>
#include <QTcpSocket> #include <QTcpSocket>
@ -64,7 +65,7 @@ class PbRpcChannel : public QObject, public ::google::protobuf::RpcChannel
const ::google::protobuf::Message &notifPrototype; const ::google::protobuf::Message &notifPrototype;
::google::protobuf::Message *notif; ::google::protobuf::Message *notif;
QHostAddress mServerAddress; QString mServerHost;
quint16 mServerPort; quint16 mServerPort;
QTcpSocket *mpSocket; QTcpSocket *mpSocket;
@ -72,15 +73,18 @@ class PbRpcChannel : public QObject, public ::google::protobuf::RpcChannel
::google::protobuf::io::CopyingOutputStreamAdaptor *outStream; ::google::protobuf::io::CopyingOutputStreamAdaptor *outStream;
public: public:
PbRpcChannel(QHostAddress ip, quint16 port, PbRpcChannel(QString serverName, quint16 port,
const ::google::protobuf::Message &notifProto); const ::google::protobuf::Message &notifProto);
~PbRpcChannel(); ~PbRpcChannel();
void establish(); void establish();
void establish(QHostAddress ip, quint16 port); void establish(QString serverName, quint16 port);
void tearDown(); void tearDown();
const QHostAddress& serverAddress() const { return mServerAddress; } const QString serverName() const
{
return mpSocket->peerName();
}
quint16 serverPort() const { return mServerPort; } quint16 serverPort() const { return mServerPort; }
QAbstractSocket::SocketState state() const QAbstractSocket::SocketState state() const

View File

@ -42,14 +42,15 @@ RpcServer::~RpcServer()
{ {
} }
bool RpcServer::registerService(::google::protobuf::Service *service, bool RpcServer::registerService(::google::protobuf::Service *service,
quint16 tcpPortNum) QHostAddress address, quint16 tcpPortNum)
{ {
this->service = service; this->service = service;
if (!listen(QHostAddress::Any, tcpPortNum)) if (!listen(address, tcpPortNum))
{ {
qDebug("Unable to start the server: %s", qDebug("Unable to start the server on <%s>: %s",
qPrintable(address.toString()),
errorString().toAscii().constData()); errorString().toAscii().constData());
return false; return false;
} }

View File

@ -41,7 +41,7 @@ public:
virtual ~RpcServer(); virtual ~RpcServer();
bool registerService(::google::protobuf::Service *service, bool registerService(::google::protobuf::Service *service,
quint16 tcpPortNum); QHostAddress address, quint16 tcpPortNum);
signals: signals:
void notifyClients(int notifType, SharedProtobufMessage notifData); void notifyClients(int notifType, SharedProtobufMessage notifData);

View File

@ -19,8 +19,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "drone.h" #include "drone.h"
#include "rpcserver.h"
#include "myservice.h" #include "myservice.h"
#include "rpcserver.h"
#include "settings.h"
#include <QMetaType> #include <QMetaType>
@ -43,11 +44,21 @@ Drone::~Drone()
bool Drone::init() bool Drone::init()
{ {
QString addr = appSettings->value(kRpcServerAddress).toString();
QHostAddress address = addr.isEmpty() ?
QHostAddress::Any : QHostAddress(addr);
Q_ASSERT(rpcServer); Q_ASSERT(rpcServer);
qRegisterMetaType<SharedProtobufMessage>("SharedProtobufMessage"); qRegisterMetaType<SharedProtobufMessage>("SharedProtobufMessage");
if (!rpcServer->registerService(service, myport ? myport : 7878)) if (address.isNull()) {
qWarning("Invalid RpcServer Address <%s> specified. Using 'Any'",
qPrintable(addr));
address = QHostAddress::Any;
}
if (!rpcServer->registerService(service, address, myport ? myport : 7878))
{ {
//qCritical(qPrintable(rpcServer->errorString())); //qCritical(qPrintable(rpcServer->errorString()));
return false; return false;

View File

@ -31,6 +31,11 @@ extern QSettings *appSettings;
const QString kRateAccuracyKey("RateAccuracy"); const QString kRateAccuracyKey("RateAccuracy");
const QString kRateAccuracyDefaultValue("High"); const QString kRateAccuracyDefaultValue("High");
//
// RpcServer Section Keys
//
const QString kRpcServerAddress("RpcServer/Address");
// //
// PortList Section Keys // PortList Section Keys
// //