Skip to content

Commit

Permalink
Server|Client: Pinging the server via ServerLink and ServerInfoDialog
Browse files Browse the repository at this point in the history
  • Loading branch information
skyjake committed Feb 6, 2017
1 parent 032b160 commit 56043a7
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 1 deletion.
3 changes: 3 additions & 0 deletions doomsday/apps/client/include/network/serverlink.h
Expand Up @@ -38,6 +38,7 @@ class ServerLink : public de::shell::AbstractLink

public:
DENG2_DEFINE_AUDIENCE2(DiscoveryUpdate, void linkDiscoveryUpdate(ServerLink const &link))
DENG2_DEFINE_AUDIENCE2(PingResponse, void pingResponse(de::Address const &, de::TimeDelta))
DENG2_DEFINE_AUDIENCE2(MapOutline, void mapOutlineReceived(de::Address const &, de::shell::MapOutlinePacket const &))

DENG2_DEFINE_AUDIENCE2(Join, void networkGameJoined())
Expand Down Expand Up @@ -89,6 +90,8 @@ class ServerLink : public de::shell::AbstractLink

void requestMapOutline(de::Address const &address);

void ping(de::Address const &address);

void connectDomain(de::String const &domain, de::TimeDelta const &timeout = 0) override;
void connectHost(de::Address const &address) override;

Expand Down
53 changes: 53 additions & 0 deletions doomsday/apps/client/src/network/serverlink.cpp
Expand Up @@ -45,6 +45,8 @@
#include <de/shell/ServerFinder>
#include <doomsday/DoomsdayApp>
#include <doomsday/Games>

#include <QElapsedTimer>
#include <QTimer>

using namespace de;
Expand All @@ -53,13 +55,17 @@ enum LinkState
{
None,
Discovering,
Pinging,
WaitingForPong,
QueryingMapOutline,
WaitingForInfoResponse,
Joining,
WaitingForJoinResponse,
InGame
};

static int const NUM_PINGS = 5;

DENG2_PIMPL(ServerLink)
{
std::unique_ptr<shell::ServerFinder> finder; ///< Finding local servers.
Expand All @@ -68,6 +74,9 @@ DENG2_PIMPL(ServerLink)
typedef QMap<Address, shell::ServerInfo> Servers;
Servers discovered;
Servers fromMaster;
QElapsedTimer pingTimer;
QList<TimeDelta> pings;
int pingCounter;
std::unique_ptr<GameProfile> serverProfile; ///< Profile used when joining.
std::function<void (GameProfile const *)> profileResultCallback;
std::function<void (Address, GameProfile const *)> profileResultCallbackWithAddress;
Expand Down Expand Up @@ -326,12 +335,14 @@ DENG2_PIMPL(ServerLink)
}

DENG2_PIMPL_AUDIENCE(DiscoveryUpdate)
DENG2_PIMPL_AUDIENCE(PingResponse)
DENG2_PIMPL_AUDIENCE(MapOutline)
DENG2_PIMPL_AUDIENCE(Join)
DENG2_PIMPL_AUDIENCE(Leave)
};

DENG2_AUDIENCE_METHOD(ServerLink, DiscoveryUpdate)
DENG2_AUDIENCE_METHOD(ServerLink, PingResponse)
DENG2_AUDIENCE_METHOD(ServerLink, MapOutline)
DENG2_AUDIENCE_METHOD(ServerLink, Join)
DENG2_AUDIENCE_METHOD(ServerLink, Leave)
Expand Down Expand Up @@ -462,6 +473,12 @@ void ServerLink::requestMapOutline(Address const &address)
LOG_NET_VERBOSE("Querying %s for map outline") << address;
}

void ServerLink::ping(const Address &address)
{
AbstractLink::connectHost(address);
d->state = Pinging;
}

void ServerLink::connectDomain(String const &domain, TimeDelta const &timeout)
{
LOG_AS("ServerLink::connectDomain");
Expand Down Expand Up @@ -601,6 +618,14 @@ void ServerLink::initiateCommunications()
d->state = WaitingForInfoResponse;
break;

case Pinging:
*this << ByteRefArray("Ping?", 5);
d->state = WaitingForPong;
d->pingCounter = NUM_PINGS;
d->pings.clear();
d->pingTimer.start();
break;

case QueryingMapOutline:
*this << ByteRefArray("MapOutline?", 11);
d->state = WaitingForInfoResponse;
Expand Down Expand Up @@ -663,6 +688,34 @@ void ServerLink::handleIncomingPackets()
if (!d->handleJoinResponse(*packet)) return;
break;

case WaitingForPong:
if (packet->size() == 4 && *packet == "Pong" &&
d->pingCounter-- > 0)
{
d->pings.append(TimeDelta::fromMilliSeconds(d->pingTimer.elapsed()));
*this << ByteRefArray("Ping?", 5);
d->pingTimer.restart();
}
else
{
Address const svAddress = address();
disconnect();

// Notify about the average ping time.
if (d->pings.count())
{
TimeDelta average = 0;
for (auto const &d : d->pings) average += d;
average = average / d->pings.count();

DENG2_FOR_AUDIENCE2(PingResponse, i)
{
i->pingResponse(svAddress, average);
}
}
}
break;

case InGame: {
/// @todo The incoming packets should be handled immediately.

Expand Down
15 changes: 14 additions & 1 deletion doomsday/apps/client/src/ui/dialogs/serverinfodialog.cpp
Expand Up @@ -45,6 +45,7 @@ static DialogWidget::RoleFlags const ID_JOIN = DialogWidget::Id2;

DENG_GUI_PIMPL(ServerInfoDialog)
, DENG2_OBSERVES(ServerLink, MapOutline)
, DENG2_OBSERVES(ServerLink, PingResponse)
, public PackagesWidget::IPackageStatus
{
// Server info & status.
Expand All @@ -60,6 +61,7 @@ DENG_GUI_PIMPL(ServerInfoDialog)
{
QueryNone,
QueryStatus,
QueryPing,
QueryMapOutline,
};
Query pendingQuery = QueryNone;
Expand All @@ -80,7 +82,8 @@ DENG_GUI_PIMPL(ServerInfoDialog)
, serverInfo(sv)
, link(ServerLink::ManualConnectionOnly)
{
link.audienceForMapOutline() += this;
link.audienceForMapOutline() += this;
link.audienceForPingResponse() += this;
connect(&queryTimer, &QTimer::timeout, [this] () { beginPendingQuery(); });

self().useInfoStyle();
Expand Down Expand Up @@ -386,6 +389,10 @@ DENG_GUI_PIMPL(ServerInfoDialog)
}
break;

case QueryPing:
link.ping(host);
break;

case QueryMapOutline:
link.requestMapOutline(host);
break;
Expand All @@ -412,6 +419,12 @@ DENG_GUI_PIMPL(ServerInfoDialog)
void mapOutlineReceived(Address const &, shell::MapOutlinePacket const &packet)
{
mapOutline->setOutline(packet);
startQuery(QueryPing);
}

void pingResponse(Address const &, TimeDelta pingTime)
{
qDebug() << "Ping:" << pingTime.asMilliSeconds() << "ms";
}
};

Expand Down
4 changes: 4 additions & 0 deletions doomsday/apps/server/src/remoteuser.cpp
Expand Up @@ -136,6 +136,10 @@ DENG2_PIMPL(RemoteUser)
LOGDEV_NET_VERBOSE("Info reply:\n%s") << String::fromUtf8(msg);
self() << msg;
}
else if (command == "Ping?")
{
self() << Block("Pong");
}
else if (command == "MapOutline?")
{
shell::MapOutlinePacket packet;
Expand Down

0 comments on commit 56043a7

Please sign in to comment.