OpenClonk
main.cpp
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
5  * Copyright (c) 2010-2016, The OpenClonk Team and contributors
6  *
7  * Distributed under the terms of the ISC license; see accompanying file
8  * "COPYING" for details.
9  *
10  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11  * See accompanying file "TRADEMARK" for details.
12  *
13  * To redistribute this file separately, substitute the full license texts
14  * for the above references.
15  */
16 
17 #include "C4Include.h"
20 #include "network/C4Network2.h"
21 
22 #include <random>
23 #include <unordered_map>
24 
26 {
27 public:
31  rng = std::bind(std::uniform_int_distribution<CID>(1/*, max*/), std::ref(random_device));
32  }
33 private:
34  std::random_device random_device;
35  std::function<CID()> rng;
36  std::unordered_map<addr_t, CID> peer_ids;
37  std::unordered_map<CID, addr_t> peer_addrs;
38  // Event handlers
39  bool OnConn(const addr_t &AddrPeer, const addr_t &AddrConnect, const addr_t *OwnAddr, C4NetIO *pNetIO) override {
40  CID nid;
41  do {
42  nid = rng();
43  } while(peer_addrs.count(nid) && !nid);
44  peer_ids.emplace(AddrPeer, nid);
45  peer_addrs.emplace(nid, AddrPeer);
46  printf("Punched %s... #%u\n", AddrPeer.ToString().getData(), nid);
47  return true;
48  }
49  void OnPacket(const class C4NetIOPacket &rPacket, C4NetIO *pNetIO) override {
50  auto& addr = rPacket.getAddr();
51  auto unpack = C4NetpuncherPacket::Construct(rPacket);
52  if (!unpack) { Close(addr); return; }
53  switch (unpack->GetType()) {
54  case PID_Puncher_IDReq: {
55  auto it = peer_ids.find(addr);
56  if (it != peer_ids.end()) {
57  Send(C4NetpuncherPacketAssID(it->second).PackTo(addr));
58  printf("Host: #%u\n", it->second);
59  }
60  break;
61  }
62  case PID_Puncher_SReq: {
63  auto other_it = peer_addrs.find(dynamic_cast<C4NetpuncherPacketSReq*>(unpack.get())->GetID());
64  if (other_it == peer_addrs.end()) return; // Might be nice to return some kind of error, for purposes of debugging.
65  Send(C4NetpuncherPacketCReq(other_it->second).PackTo(addr));
66  Send(C4NetpuncherPacketCReq(addr).PackTo(other_it->second));
67  break;
68  }
69  default:
70  Close(addr);
71  }
72  }
73  void OnDisconn(const addr_t &AddrPeer, C4NetIO *pNetIO, const char *szReason) override {
74  auto it = peer_ids.find(AddrPeer);
75  if (it == peer_ids.end()) {
76  printf("ERROR: closing connection for %s: (%s) but no connection is known\n", AddrPeer.ToString().getData(), szReason);
77  return;
78  }
79  peer_addrs.erase(it->second);
80  peer_ids.erase(it);
81  printf("Stopped punching %s: %s...\n", AddrPeer.ToString().getData(), szReason);
82  };
84 
85 int main(int argc, char * argv[])
86 {
87  // Log
88  printf("Starting puncher...\n");
89 
90  // Get port
91  uint16_t iPort = C4NetStdPortPuncher;
92  if (argc == 2)
93  {
94  iPort = strtoul(argv[1], nullptr, 10);
95  if (!iPort) iPort = C4NetStdPortPuncher;
96  }
97 
98  // Initialize
99  if (!Puncher.Init(iPort))
100  {
101  fprintf(stderr, "Could not initialize puncher: %s", Puncher.GetError());
102  return 1;
103  }
104 
105  // Log
106  printf("Listening on port %d...\n", iPort);
107 
108  // Execute forever
109  for (;;)
110  {
111  Puncher.ExecuteUntil(-1);
112  fprintf(stderr, "ERROR: %s\n", Puncher.GetError());
113  }
114 
115  return 0;
116 }
117 
118 // Necessary to satisfy the linker.
119 void RecordRandom(uint32_t range, uint32_t val) {}
const int16_t C4NetStdPortPuncher
Definition: C4Network2.h:33
@ PID_Puncher_SReq
@ PID_Puncher_IDReq
virtual const char * GetError() const
Definition: C4NetIO.h:286
EndpointAddress addr_t
Definition: C4NetIO.h:213
const C4NetIO::addr_t & getAddr() const
Definition: C4NetIO.h:317
bool Send(const C4NetIOPacket &rPacket) override
Definition: C4NetIO.cpp:2734
void SetCallback(CBClass *pnCallback) override
Definition: C4NetIO.h:937
bool Init(uint16_t iPort=addr_t::IPPORT_NONE) override
Definition: C4NetIO.cpp:2472
bool Close() override
Definition: C4NetIO.cpp:2639
C4NetIOPacket PackTo(const C4NetIO::addr_t &) const
static std::unique_ptr< C4NetpuncherPacket > Construct(const C4NetIOPacket &rpack)
C4NetpuncherID::value CID
Definition: main.cpp:28
C4PuncherServer()
Definition: main.cpp:29
bool ExecuteUntil(int iTimeout=-1)
int main(int argc, char *argv[])
Definition: main.cpp:85
void RecordRandom(uint32_t range, uint32_t val)
Definition: main.cpp:119
C4PuncherServer Puncher