openclonk/src/network/C4Network2Discover.cpp

124 lines
3.5 KiB
C++
Raw Normal View History

2009-05-08 13:28:41 +00:00
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
2016-04-03 18:18:29 +00:00
* Copyright (c) 2013-2016, The OpenClonk Team and contributors
2009-05-08 13:28:41 +00:00
*
* Distributed under the terms of the ISC license; see accompanying file
* "COPYING" for details.
2009-05-08 13:28:41 +00:00
*
* "Clonk" is a registered trademark of Matthes Bender, used with permission.
* See accompanying file "TRADEMARK" for details.
2009-05-08 13:28:41 +00:00
*
* To redistribute this file separately, substitute the full license texts
* for the above references.
2009-05-08 13:28:41 +00:00
*/
#include "C4Include.h"
#include "network/C4Network2Discover.h"
2009-05-08 13:28:41 +00:00
// *** C4Network2IODiscover
//
// Quick multicast discovery guide by Luchs:
//
// All engines in network mode join a multicast group (defined by C4NetDiscoveryAddress).
//
// Engines searching for a game ("client") send a single byte c = 3 to that multicast group. This
// happens while on the network list on each refresh.
//
// Engines hosting a game (when going into the lobby) send a byte c = 4 plus their reference server
// port to the multicast group. Additionally, they listen for the c = 3 bytes and will reply with
// another multicast answer.
2009-05-08 13:28:41 +00:00
struct C4Network2IODiscoverReply
{
char c;
uint16_t Port;
2009-05-08 13:28:41 +00:00
};
void C4Network2IODiscover::OnPacket(const class C4NetIOPacket &rPacket, C4NetIO *pNetIO)
{
// discovery?
2010-03-28 18:58:01 +00:00
if (fEnabled && rPacket.getSize() == 1 && rPacket.getStatus() == 3)
Announce();
2009-05-08 13:28:41 +00:00
}
bool C4Network2IODiscover::Init(uint16_t iPort)
{
// Reuse address
C4NetIOSimpleUDP::SetReUseAddress(true);
// Regular init (bind to port)
2010-03-28 18:58:01 +00:00
if (!C4NetIOSimpleUDP::Init(iPort))
2009-05-08 13:28:41 +00:00
return false;
// Set callback
C4NetIOSimpleUDP::SetCallback(this);
// Build broadcast address
2013-02-18 14:30:00 +00:00
DiscoveryAddr.SetAddress(C4NetDiscoveryAddress);
DiscoveryAddr.SetPort(iPort);
2009-05-08 13:28:41 +00:00
// Initialize broadcast
2010-03-28 18:58:01 +00:00
if (!C4NetIOSimpleUDP::InitBroadcast(&DiscoveryAddr))
2009-05-08 13:28:41 +00:00
return false;
// Enable multicast loopback
return C4NetIOSimpleUDP::SetMCLoopback(true);
}
bool C4Network2IODiscover::Announce()
{
2010-03-28 18:58:01 +00:00
// Announce our presence
2017-01-07 16:52:54 +00:00
C4Network2IODiscoverReply Reply = { 4, iRefServerPort };
2010-03-28 18:58:01 +00:00
return Send(C4NetIOPacket(&Reply, sizeof(Reply), false, DiscoveryAddr));
2009-05-08 13:28:41 +00:00
}
// *** C4Network2IODiscoverClient
void C4Network2IODiscoverClient::OnPacket(const class C4NetIOPacket &rPacket, C4NetIO *pNetIO)
{
// discovery?
2010-03-28 18:58:01 +00:00
if (rPacket.getSize() == sizeof(C4Network2IODiscoverReply) && rPacket.getStatus() == 4)
2009-05-08 13:28:41 +00:00
{
// save discovered address
2010-03-28 18:58:01 +00:00
if (iDiscoverCount < C4NetMaxDiscover)
2009-05-08 13:28:41 +00:00
{
const C4Network2IODiscoverReply *pReply = reinterpret_cast<const C4Network2IODiscoverReply *>(rPacket.getData());
Discovers[iDiscoverCount] = rPacket.getAddr();
2013-02-18 14:30:00 +00:00
Discovers[iDiscoverCount].SetPort(pReply->Port);
2009-05-08 13:28:41 +00:00
iDiscoverCount++;
}
}
}
bool C4Network2IODiscoverClient::Init(uint16_t iPort)
{
// Reuse address
C4NetIOSimpleUDP::SetReUseAddress(true);
// Bind to port
2010-03-28 18:58:01 +00:00
if (!C4NetIOSimpleUDP::Init(iPort))
2009-05-08 13:28:41 +00:00
return false;
// Set callback
C4NetIOSimpleUDP::SetCallback(this);
// Build broadcast address
2013-02-18 14:30:00 +00:00
DiscoveryAddr.SetAddress(C4NetDiscoveryAddress);
DiscoveryAddr.SetPort(iPort);
2009-05-08 13:28:41 +00:00
// Initialize broadcast
2010-03-28 18:58:01 +00:00
if (!C4NetIOSimpleUDP::InitBroadcast(&DiscoveryAddr))
2009-05-08 13:28:41 +00:00
return false;
// Enable multicast loopback
return C4NetIOSimpleUDP::SetMCLoopback(true);
}
bool C4Network2IODiscoverClient::StartDiscovery()
{
// Multicast discovery byte
char c = 3;
return Send(C4NetIOPacket(&c, sizeof(c), false, DiscoveryAddr));
}
bool C4Network2IODiscoverClient::PopDiscover(C4NetIO::addr_t &Discover)
{
// Discovers left?
2010-03-28 18:58:01 +00:00
if (!getDiscoverCount())
2009-05-08 13:28:41 +00:00
return false;
// Return one
Discover = Discovers[--iDiscoverCount];
return true;
}