RigsofRods  2023.09
Soft-body Physics Simulation
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Network.cpp
Go to the documentation of this file.
1 /*
2  This source file is part of Rigs of Rods
3  Copyright 2005-2012 Pierre-Michel Ricordel
4  Copyright 2007-2012 Thomas Fischer
5  Copyright 2013-2016 Petr Ohlidal
6 
7  For more information, see http://www.rigsofrods.org/
8 
9  Rigs of Rods is free software: you can redistribute it and/or modify
10  it under the terms of the GNU General Public License version 3, as
11  published by the Free Software Foundation.
12 
13  Rigs of Rods is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with Rigs of Rods. If not, see <http://www.gnu.org/licenses/>.
20 */
21 
22 #ifdef USE_SOCKETW
23 
24 #include "Network.h"
25 
26 #include "Application.h"
27 #include "ChatSystem.h"
28 #include "Console.h"
29 #include "ErrorUtils.h"
30 #include "GameContext.h"
31 #include "GUIManager.h"
32 #include "GUI_TopMenubar.h"
33 #include "Language.h"
34 #include "RoRVersion.h"
35 #include "ScriptEngine.h"
36 #include "Utils.h"
37 
38 #include <Ogre.h>
39 #include <SocketW.h>
40 
41 #include <algorithm>
42 #include <chrono>
43 #include <cstring>
44 
45 using namespace RoR;
46 
47 static Ogre::ColourValue MP_COLORS[] = // Classic RoR multiplayer colors
48 {
49  Ogre::ColourValue(0.0, 0.8, 0.0),
50  Ogre::ColourValue(0.0, 0.4, 0.701960784314),
51  Ogre::ColourValue(1.0, 0.501960784314, 0.0),
52  Ogre::ColourValue(1.0, 0.8, 0.0),
53  //Ogre::ColourValue(0.2, 0.0, 0.6),
54  //Ogre::ColourValue(0.6, 0.0, 0.6),
55  Ogre::ColourValue(0.8, 1.0, 0.0),
56  Ogre::ColourValue(1.0, 0.0, 0.0),
57  Ogre::ColourValue(0.501960784314, 0.501960784314, 0.501960784314),
58  Ogre::ColourValue(0.0, 0.560784313725, 0.0),
59  //Ogre::ColourValue(0.0, 0.282352941176, 0.490196078431),
60  Ogre::ColourValue(0.701960784314, 0.352941176471, 0.0),
61  Ogre::ColourValue(0.701960784314, 0.560784313725, 0.0),
62  //Ogre::ColourValue(0.419607843137, 0.0, 0.419607843137),
63  Ogre::ColourValue(0.560784313725, 0.701960784314, 0.0),
64  Ogre::ColourValue(0.701960784314, 0.0, 0.0),
65  Ogre::ColourValue(0.745098039216, 0.745098039216, 0.745098039216),
66  Ogre::ColourValue(0.501960784314, 1.0, 0.501960784314),
67  Ogre::ColourValue(0.501960784314, 0.788235294118, 1.0),
68  Ogre::ColourValue(1.0, 0.752941176471, 0.501960784314),
69  Ogre::ColourValue(1.0, 0.901960784314, 0.501960784314),
70  Ogre::ColourValue(0.666666666667, 0.501960784314, 1.0),
71  Ogre::ColourValue(0.933333333333, 0.0, 0.8),
72  Ogre::ColourValue(1.0, 0.501960784314, 0.501960784314),
73  Ogre::ColourValue(0.4, 0.4, 0.0),
74  Ogre::ColourValue(1.0, 0.749019607843, 1.0),
75  Ogre::ColourValue(0.0, 1.0, 0.8),
76  Ogre::ColourValue(0.8, 0.4, 0.6),
77  Ogre::ColourValue(0.6, 0.6, 0.0),
78 };
79 
80 using namespace RoRnet;
81 
82 static const unsigned int m_packet_buffer_size = 20;
83 
84 #define LOG_THREAD(_MSG_) { std::stringstream s; s << _MSG_ << " (Thread ID: " << std::this_thread::get_id() << ")"; LOG(s.str()); }
85 #define LOGSTREAM Ogre::LogManager().getSingleton().stream()
86 
87 void Network::PushNetMessage(MsgType type, std::string const & message)
88 {
89  Message m(type);
90  m.description = message;
92 }
93 
94 Ogre::ColourValue Network::GetPlayerColor(int color_num)
95 {
96  int numColours = sizeof(MP_COLORS) / sizeof(Ogre::ColourValue);
97  if (color_num < 0 || color_num >= numColours)
98  return Ogre::ColourValue::White;
99 
100  return MP_COLORS[color_num];
101 }
102 
103 // Internal helper
104 void DebugPacket(const char *name, RoRnet::Header *header, char *buffer)
105 {
106  std::stringstream msg;
107  msg << "++ " << name << ": " << header->source << ", " << header->streamid
108  << ", "<< header->command << ", " << header->size << ", hash: " << HashData(buffer, header->size);
109  LOG(msg.str());
110 }
111 
112 void Network::SetNetQuality(int quality)
113 {
114  m_net_quality = quality;
115 }
116 
118 {
119  return m_net_quality;
120 }
121 
123 {
124  return m_uid;
125 }
126 
127 bool Network::SendMessageRaw(char *buffer, int msgsize)
128 {
129  SWBaseSocket::SWBaseError error;
130 
131  if (m_socket.fsend(buffer, msgsize, &error) < msgsize)
132  {
133  LOG("NET send error: " + error.get_error());
134  return false;
135  }
136 
137  return true;
138 }
139 
140 bool Network::SendNetMessage(int type, unsigned int streamid, int len, char* content)
141 {
142  RoRnet::Header head;
143  memset(&head, 0, sizeof(RoRnet::Header));
144  head.command = type;
145  head.source = m_uid;
146  head.size = len;
147  head.streamid = streamid;
148 
149  const int msgsize = sizeof(RoRnet::Header) + len;
150 
151  if (msgsize >= RORNET_MAX_MESSAGE_LENGTH)
152  {
153  return false;
154  }
155 
156  char buffer[RORNET_MAX_MESSAGE_LENGTH] = {0};
157  memcpy(buffer, (char *)&head, sizeof(RoRnet::Header));
158  memcpy(buffer + sizeof(RoRnet::Header), content, len);
159 
160  return SendMessageRaw(buffer, msgsize);
161 }
162 
163 void Network::QueueStreamData(RoRnet::Header &header, char *buffer, size_t buffer_len)
164 {
165  NetRecvPacket packet;
166  packet.header = header;
167  memcpy(packet.buffer, buffer, std::min(buffer_len, size_t(RORNET_MAX_MESSAGE_LENGTH)));
168 
169  std::lock_guard<std::mutex> lock(m_recv_packetqueue_mutex);
170  m_recv_packet_buffer.push_back(packet);
171 }
172 
173 int Network::ReceiveMessage(RoRnet::Header *head, char* content, int bufferlen)
174 {
175  SWBaseSocket::SWBaseError error;
176 
177 #ifdef DEBUG
178  LOG_THREAD("[RoR|Networking] ReceiveMessage() waiting...");
179 #endif //DEBUG
180 
181  if (m_socket.frecv((char*)head, sizeof(RoRnet::Header), &error) < sizeof(RoRnet::Header))
182  {
183  LOG("NET receive error 1: " + error.get_error());
184  return -1;
185  }
186 
187 #ifdef DEBUG
188  LOG_THREAD("[RoR|Networking] ReceiveMessage() header received");
189 #endif //DEBUG
190 
191  if (head->size > uint32_t(bufferlen))
192  {
193  return -3;
194  }
195 
196  if (head->size > 0)
197  {
198  // Read the packet content
199  std::memset(content, 0, bufferlen);
200  if (m_socket.frecv(content, head->size, &error) < static_cast<int>(head->size))
201  {
202  LOG_THREAD("NET receive error 2: "+ error.get_error());
203  return -1;
204  }
205  }
206 
207 #ifdef DEBUG
208  LOG_THREAD("[RoR|Networking] ReceiveMessage() body received");
209 #endif //DEBUG
210 
211  return 0;
212 }
213 
215 {
216  LOG("[RoR|Networking] SendThread started");
217  while (!m_shutdown)
218  {
219  NetSendPacket packet;
220  {
221  std::unique_lock<std::mutex> queue_lock(m_send_packetqueue_mutex);
222  while (m_send_packet_buffer.empty() && !m_shutdown)
223  {
224  m_send_packet_available_cv.wait(queue_lock);
225  }
226  if (m_shutdown)
227  {
228  break;
229  }
230  packet = m_send_packet_buffer.front();
231  m_send_packet_buffer.pop_front();
232  }
233  SendMessageRaw(packet.buffer, packet.size);
234  }
235  LOG("[RoR|Networking] SendThread stopped");
236 }
237 
239 {
240  LOG_THREAD("[RoR|Networking] RecvThread starting...");
241 
242  RoRnet::Header header;
243 
244  char buffer[RORNET_MAX_MESSAGE_LENGTH] = {0};
245 
246  while (!m_shutdown)
247  {
248  int err = ReceiveMessage(&header, buffer, RORNET_MAX_MESSAGE_LENGTH);
249  //LOG("Received data: " + TOSTRING(header.command) + ", source: " + TOSTRING(header.source) + ":" + TOSTRING(header.streamid) + ", size: " + TOSTRING(header.size));
250  if (err != 0)
251  {
252  LOG_THREAD("[RoR|Networking] RecvThread: Error while receiving data: " + TOSTRING(err));
253  m_shutdown = true; // Atomic; instruct sender thread to stop
254  PushNetMessage(MSG_NET_RECV_ERROR, _LC("Network", "Error receiving data from network"));
255  continue; // Stop receiving data
256  }
257 
258  if (header.command == MSG2_STREAM_REGISTER)
259  {
260  if (header.source == m_uid)
261  continue;
262 
264 
265  LOG(" * received stream registration: " + TOSTRING(header.source) + ": " + TOSTRING(header.streamid) + ", type: " + TOSTRING(reg->type));
266  }
267  else if (header.command == MSG2_STREAM_REGISTER_RESULT)
268  {
270  LOG(" * received stream registration result: " + TOSTRING(header.source) + ": " + TOSTRING(header.streamid) + ", status: " + TOSTRING(reg->status));
271  }
272  else if (header.command == MSG2_STREAM_UNREGISTER)
273  {
274  LOG(" * received stream deregistration: " + TOSTRING(header.source) + ": " + TOSTRING(header.streamid));
275  }
276  else if (header.command == MSG2_UTF8_CHAT || header.command == MSG2_UTF8_PRIVCHAT)
277  {
278  // Chat message
279  }
280  else if (header.command == MSG2_NETQUALITY && header.source == -1)
281  {
282  if (header.size != sizeof(int))
283  {
284  continue;
285  }
286  int quality = *(int *)buffer;
287  SetNetQuality(quality);
288  continue;
289  }
290  else if (header.command == MSG2_USER_LEAVE)
291  {
292  if (header.source == m_uid)
293  {
294  m_shutdown = true; // Atomic; stop sending/receiving data - server closes the connection quickly after kick.
295 
296  std::stringstream msg;
297  msg << _L("disconnected: remote side closed the connection");
298  msg << " ** ";
299  msg << buffer;
300 
301  bool was_kick = (std::strstr(buffer, "disconnected on request") == nullptr); // FIXME: Add a reason code to MSG2_USER_LEAVE, this is ugly!
302  PushNetMessage((was_kick) ? MSG_NET_SERVER_KICK : MSG_NET_USER_DISCONNECT, msg.str());
304 
306  }
307  else
308  {
309  std::lock_guard<std::mutex> lock(m_users_mutex);
310  auto user = std::find_if(m_users.begin(), m_users.end(), [header](const RoRnet::UserInfo& u) { return static_cast<int>(u.uniqueid) == header.source; });
311  if (user != m_users.end())
312  {
313  // Console is now threadsafe, no need to send fake chatmessages to ourselves
314  Str<300> text;
315  text << _L("left the game");
318  LOG_THREAD(text);
319 
320  // Erase matching peer options
321  int peeropt_offset = (int)std::distance(m_users.begin(), user);
322  auto peeropt_itor = m_users_peeropts.begin() + peeropt_offset;
323  m_users_peeropts.erase(peeropt_itor);
324 
325  m_disconnected_users.push_back(*user); // Copy
326  m_users.erase(user);
327  }
328  }
329  }
330  else if (header.command == MSG2_USER_INFO || header.command == MSG2_USER_JOIN)
331  {
332  if (header.source == m_uid)
333  {
334  std::lock_guard<std::mutex> lock(m_userdata_mutex);
335  memcpy(&m_userdata, buffer, sizeof(RoRnet::UserInfo));
336  m_authlevel = m_userdata.authstatus;
337  m_username = std::string(m_userdata.username);
339  // TODO: Update the global variable 'mp_player_name' in a threadsafe way.
340  }
341  else
342  {
343  RoRnet::UserInfo user_info;
344  if (!GetUserInfo(header.source, user_info)) // Check that user doesn't exist yet.
345  {
346  memcpy(&user_info, buffer, sizeof(RoRnet::UserInfo));
347  Str<300> text;
348  if (user_info.authstatus != 0) // Show nothing for guests (no special authorization)
349  {
350  text << "(" << UserAuthToStringShort(user_info) << ") ";
351  }
352  text << _L("joined the game");
353 
354  // NB: Console is threadsafe
356  user_info.uniqueid, Console::CONSOLE_SYSTEM_NOTICE, text.ToCStr());
358  // Lock and update userlist
359  std::lock_guard<std::mutex> lock(m_users_mutex);
360  m_users.push_back(user_info);
361  m_users_peeropts.push_back(BitMask_t(0));
362  } // End of lock scope
363  }
364  continue;
365  }
366  else if (header.command == MSG2_GAME_CMD)
367  {
368 #ifdef USE_ANGELSCRIPT
369  App::GetScriptEngine()->queueStringForExecution(Ogre::String(buffer));
370 #endif // USE_ANGELSCRIPT
371  continue;
372  }
373  //DebugPacket("recv", &header, buffer);
374 
375  QueueStreamData(header, buffer, RORNET_MAX_MESSAGE_LENGTH);
376  }
377 
378  LOG_THREAD("[RoR|Networking] RecvThread stopped");
379 }
380 
381 
382 void Network::CouldNotConnect(std::string const & msg, bool close_socket /*= true*/)
383 {
384  RoR::LogFormat("[RoR|Networking] Failed to connect to server [%s:%d], message: %s", m_net_host.c_str(), m_net_port, msg.c_str());
385  PushNetMessage(MSG_NET_CONNECT_FAILURE, msg);
386 
387  if (close_socket)
388  {
389  m_socket.set_timeout(1, 0);
390  m_socket.disconnect();
391  }
392 }
393 
395 {
396  // Shadow vars for threaded access
397  m_username = App::mp_player_name->getStr();
398  m_token = App::mp_player_token->getStr();
399  m_net_host = App::mp_server_host->getStr();
400  m_net_port = App::mp_server_port->getInt();
401  m_password = App::mp_server_password->getStr();
402 
403  try
404  {
405  m_connect_thread = std::thread(&Network::ConnectThread, this);
406  App::mp_state->setVal((int)MpState::CONNECTING); // Mark connect thread as started
407  PushNetMessage(MSG_NET_CONNECT_STARTED, _LC("Network", "Starting..."));
408  return true;
409  }
410  catch (std::exception& e)
411  {
413  PushNetMessage(MSG_NET_CONNECT_FAILURE, _L("Failed to launch connection thread"));
414  RoR::LogFormat("[RoR|Networking] Failed to launch connection thread, message: %s", e.what());
415  return false;
416  }
417 }
418 
420 {
422 
423  if (m_connect_thread.joinable())
424  m_connect_thread.join(); // Clean up
425 }
426 
428 {
429  RoR::LogFormat("[RoR|Networking] Trying to join server '%s' on port '%d' ...", m_net_host.c_str(), m_net_port);
430 
431  SWBaseSocket::SWBaseError error;
432 
433  PushNetMessage(MSG_NET_CONNECT_PROGRESS, _LC("Network", "Estabilishing connection..."));
434  m_socket = SWInetSocket();
435  m_socket.set_timeout(10, 0);
436  m_socket.connect(m_net_port, m_net_host, &error);
437  if (error != SWBaseSocket::ok)
438  {
439  CouldNotConnect(_L("Could not create connection"), false);
440  return false;
441  }
442 
443  PushNetMessage(MSG_NET_CONNECT_PROGRESS, _LC("Network", "Getting server info..."));
444  if (!SendNetMessage(MSG2_HELLO, 0, (int)strlen(RORNET_VERSION), (char *)RORNET_VERSION))
445  {
446  CouldNotConnect(_L("Establishing network session: error sending hello"));
447  return false;
448  }
449 
450  RoRnet::Header header;
451  char buffer[RORNET_MAX_MESSAGE_LENGTH] = {0};
452 
453  // Receive server (rornet protocol) version
454  if (ReceiveMessage(&header, buffer, RORNET_MAX_MESSAGE_LENGTH))
455  {
456  CouldNotConnect(_L("Establishing network session: error getting server version"));
457  return false;
458  }
459  if (header.command == MSG2_WRONG_VER_LEGACY) // Pre-RoRnet_2.40 server
460  {
462  memcpy(&info, buffer, sizeof(RoRnet::LegacyServerInfo));
463  std::string format_str = _L("Establishing network session: wrong server version, you are using version '%s' and the server is using '%s'");
464  const char* server_ver = (info.protocolversion[0] != 0) ? info.protocolversion : "~ RoRnet_2.38 or earlier (not detected) ~";
465  CouldNotConnect(fmt::format(format_str.c_str(), RORNET_VERSION, server_ver));
466  return false;
467  }
468  if (header.command == MSG2_WRONG_VER)
469  {
470  CouldNotConnect(_L("server uses a different protocol version"));
471  return false;
472  }
473  if (header.command != MSG2_HELLO)
474  {
475  CouldNotConnect(_L("Establishing network session: error getting server hello"));
476  return false;
477  }
478 
479  // Save server settings
480  memcpy(&m_server_settings, buffer, sizeof(RoRnet::ServerInfo));
481 
482  if (strncmp(m_server_settings.protocolversion, RORNET_VERSION, strlen(RORNET_VERSION)))
483  {
484  std::string formatstr = _L("Establishing network session: wrong server version, you are using version '%s' and the server is using '%s'");
485  CouldNotConnect(fmt::format(formatstr, RORNET_VERSION, m_server_settings.protocolversion));
486  return false;
487  }
488 
489  PushNetMessage(MSG_NET_CONNECT_PROGRESS, _LC("Network", "Authorizing..."));
490 
491  // First handshake done, increase the timeout, important!
492  m_socket.set_timeout(0, 0);
493 
494  // Construct user credentials
496  memset(&c, 0, sizeof(RoRnet::UserInfo));
497  // Cut off the UTF string on the highest level, otherwise you will break UTF info
498  strncpy(c.username, m_username.substr(0, RORNET_MAX_USERNAME_LEN).c_str(), RORNET_MAX_USERNAME_LEN);
499  strncpy(c.serverpassword, Sha1Hash(m_password).c_str(), size_t(40));
500  strncpy(c.usertoken, Sha1Hash(m_token).c_str(), size_t(40));
502  strncpy(c.clientname, "RoR", 10);
503  std::string language = App::app_language->getStr().substr(0, 2);
504  std::string country = App::app_country->getStr().substr(0, 2);
505  strncpy(c.language, (language + std::string("_") + country).c_str(), 5);
506  strcpy(c.sessiontype, "normal");
507  if (!SendNetMessage(MSG2_USER_INFO, 0, sizeof(RoRnet::UserInfo), (char*)&c))
508  {
509  CouldNotConnect(_L("Establishing network session: error sending user info"));
510  return false;
511  }
512 
513  // Getting authorization
514  if (ReceiveMessage(&header, buffer, RORNET_MAX_MESSAGE_LENGTH))
515  {
516  CouldNotConnect(_L("Establishing network session: error getting server authorization"));
517  return false;
518  }
519 
520  if (header.command==MSG2_FULL)
521  {
522  CouldNotConnect(_L("Establishing network session: sorry, server has too many players"));
523  return false;
524  }
525  else if (header.command==MSG2_BANNED)
526  {
527  // Do NOT `disconnect()` the m_socket in this case - causes SocketW to terminate RoR.
528  CouldNotConnect(_L("Establishing network session: sorry, you are banned!"), /*close_socket=*/false);
529  return false;
530  }
531  else if (header.command==MSG2_WRONG_PW)
532  {
533  CouldNotConnect(_L("Establishing network session: sorry, wrong password!"));
534  return false;
535  }
536  else if (header.command==MSG2_WRONG_VER)
537  {
538  CouldNotConnect(_L("Establishing network session: sorry, wrong protocol version!"));
539  return false;
540  }
541  else if (header.command==MSG2_NO_RANK)
542  {
543  CouldNotConnect(_L("Establishing network session: sorry, this server requires a user token!"));
544  // ChainMessage() ensures the MP settings request is handled _after_ the MSG_NET_CONNECT_FAILURE with the text above.
546  return false;
547  }
548 
549  if (header.command!=MSG2_WELCOME)
550  {
551  CouldNotConnect(_L("Establishing network session: sorry, unknown server response"));
552  return false;
553  }
554 
555  PushNetMessage(MSG_NET_CONNECT_PROGRESS, _LC("Network", "Finishing..."));
556 
557  m_uid = header.source;
558 
559  // we get our userdata back
560  memcpy(&m_userdata, buffer, std::min<int>(sizeof(RoRnet::UserInfo), header.size));
561 
562  m_shutdown = false;
563 
564  LOG("[RoR|Networking] Connect(): Creating Send/Recv threads");
565  m_send_thread = std::thread(&Network::SendThread, this);
566  m_recv_thread = std::thread(&Network::RecvThread, this);
567  PushNetMessage(MSG_NET_CONNECT_SUCCESS, "");
568 
569  return true;
570 }
571 
573 {
574  LOG("[RoR|Networking] Disconnect() disconnecting...");
575  bool is_clean_disconnect = !m_shutdown; // Hacky detection of invalid network state
576 
577  m_shutdown = true; // Instruct Send/Recv threads to shut down.
578 
579  m_send_packet_available_cv.notify_one();
580 
581  m_send_thread.join();
582  LOG("[RoR|Networking] Disconnect() sender thread cleaned up");
583 
584  m_socket.set_timeout(1, 0);
585 
586  if (is_clean_disconnect)
587  {
588  SendNetMessage(MSG2_USER_LEAVE, 0, 0, 0);
589  }
590 
591  m_recv_thread.join();
592  LOG("[RoR|Networking] Disconnect() receiver thread cleaned up");
593 
594  if (is_clean_disconnect)
595  {
596  m_socket.disconnect();
597  }
598  else
599  {
600  m_socket.close_fd();
601  }
602 
603  SetNetQuality(0);
604  m_users.clear();
605  m_disconnected_users.clear();
606  m_recv_packet_buffer.clear();
607  m_send_packet_buffer.clear();
608  App::GetConsole()->doCommand("clear net");
609 
610  m_shutdown = false;
612 
613  LOG("[RoR|Networking] Disconnect() done");
614 }
615 
616 void Network::AddPacket(int streamid, int type, int len, const char *content)
617 {
618  const auto max_len = RORNET_MAX_MESSAGE_LENGTH - sizeof(RoRnet::Header);
619  if (len > max_len)
620  {
621  LOGSTREAM << "[RoR|Networking] Discarding network packet (StreamID: "
622  <<streamid<<", Type: "<<type<<"), length is " << len << ", max is " << max_len;
623  return;
624  }
625 
626  NetSendPacket packet;
627  memset(&packet, 0, sizeof(NetSendPacket));
628 
629  char *buffer = (char*)(packet.buffer);
630 
631  RoRnet::Header *head = (RoRnet::Header *)buffer;
632  head->command = type;
633  head->source = m_uid;
634  head->size = len;
635  head->streamid = streamid;
636 
637  // then copy the contents
638  char *bufferContent = (char *)(buffer + sizeof(RoRnet::Header));
639  memcpy(bufferContent, content, len);
640 
641  // record the packet size
642  packet.size = len + sizeof(RoRnet::Header);
643 
644  { // Lock scope
645  std::lock_guard<std::mutex> lock(m_send_packetqueue_mutex);
646  if (type == MSG2_STREAM_DATA_DISCARDABLE)
647  {
648  if (m_send_packet_buffer.size() > m_packet_buffer_size)
649  {
650  // buffer full, discard unimportant data packets
651  return;
652  }
653  auto search = std::find_if(m_send_packet_buffer.begin(), m_send_packet_buffer.end(),
654  [&](const NetSendPacket& p) { return !memcmp(packet.buffer, p.buffer, sizeof(RoRnet::Header)); });
655  if (search != m_send_packet_buffer.end())
656  {
657  // Found outdated discardable streamdata -> replace it
658  (*search) = packet;
659  m_send_packet_available_cv.notify_one();
660  return;
661  }
662  }
663  //DebugPacket("send", head, buffer);
664  m_send_packet_buffer.push_back(packet);
665  }
666 
667  m_send_packet_available_cv.notify_one();
668 }
669 
671 {
672  reg->origin_sourceid = m_uid;
673  reg->origin_streamid = m_stream_id;
674  reg->status = 0;
675 
676  AddPacket(m_stream_id, MSG2_STREAM_REGISTER, size, (char*)reg);
677  LOG("adding local stream: " + TOSTRING(m_uid) + ":"+ TOSTRING(m_stream_id) + ", type: " + TOSTRING(reg->type));
678 
679  m_stream_id++;
680 }
681 
682 std::vector<NetRecvPacket> Network::GetIncomingStreamData()
683 {
684  std::lock_guard<std::mutex> lock(m_recv_packetqueue_mutex);
685  std::vector<NetRecvPacket> buf_copy = m_recv_packet_buffer;
686  m_recv_packet_buffer.clear();
687  return buf_copy;
688 }
689 
691 {
692  return m_server_settings.terrain;
693 }
694 
696 {
697  std::lock_guard<std::mutex> lock(m_userdata_mutex);
698  return m_userdata.colournum;
699 }
700 
701 std::string Network::GetUsername()
702 {
703  std::lock_guard<std::mutex> lock(m_userdata_mutex);
704  return m_username;
705 }
706 
708 {
709  std::lock_guard<std::mutex> lock(m_userdata_mutex);
710  return m_userdata;
711 }
712 
713 std::vector<RoRnet::UserInfo> Network::GetUserInfos()
714 {
715  std::lock_guard<std::mutex> lock(m_users_mutex);
716  return m_users;
717 }
718 
719 std::vector<BitMask_t> Network::GetAllUsersPeerOpts()
720 {
721  std::lock_guard<std::mutex> lock(m_users_mutex);
722  return m_users_peeropts;
723 }
724 
726 {
727  std::lock_guard<std::mutex> lock(m_users_mutex);
728  for (RoRnet::UserInfo user : m_users)
729  {
730  if ((int)user.uniqueid == uid)
731  {
732  result = user;
733  return true;
734  }
735  }
736  return false;
737 }
738 
739 bool Network::GetUserPeerOpts(int uid, BitMask_t& result)
740 {
741  std::lock_guard<std::mutex> lock(m_users_mutex);
742  for (size_t i = 0; i < m_users.size(); i++)
743  {
744  if (static_cast<int>(m_users[i].uniqueid) == uid)
745  {
746  result = m_users_peeropts[i];
747  return true;
748  }
749  }
750  return false;
751 }
752 
754 {
755  std::lock_guard<std::mutex> lock(m_users_mutex);
756  for (RoRnet::UserInfo user : m_disconnected_users)
757  {
758  if ((int)user.uniqueid == uid)
759  {
760  result = user;
761  return true;
762  }
763  }
764  return false;
765 }
766 
768 {
769  RoRnet::UserInfo tmp;
770 
771  // Try remote users
772  if (GetUserInfo(uid, tmp))
773  {
774  result = tmp;
775  return true;
776  }
777 
778  // Try local user
779  tmp = GetLocalUserData();
780  if (tmp.uniqueid == uid)
781  {
782  result = tmp;
783  return true;
784  }
785 
786  return false;
787 }
788 
789 bool Network::FindUserInfo(std::string const& username, RoRnet::UserInfo &result)
790 {
791  std::lock_guard<std::mutex> lock(m_users_mutex);
792  for (RoRnet::UserInfo user : m_users)
793  {
794  if (user.username == username)
795  {
796  result = user;
797  return true;
798  }
799  }
800  return false;
801 }
802 
803 
805 {
806  std::lock_guard<std::mutex> lock(m_users_mutex);
807 
808  const bool peeropts_sane = m_users.size() == m_users_peeropts.size();
809  ROR_ASSERT(peeropts_sane);
810  if (!peeropts_sane) return;
811 
812  for (size_t i = 0; i < m_users.size(); i++)
813  {
814  if (static_cast<int>(m_users[i].uniqueid) == rq->por_uid)
815  {
816  BITMASK_SET_1(m_users_peeropts[i], rq->por_peeropts);
817  }
818  }
819 }
820 
822 {
823  std::lock_guard<std::mutex> lock(m_users_mutex);
824 
825  const bool peeropts_sane = m_users.size() == m_users_peeropts.size();
826  ROR_ASSERT(peeropts_sane);
827  if (!peeropts_sane) return;
828 
829  for (size_t i = 0; i < m_users.size(); i++)
830  {
831  if (static_cast<int>(m_users[i].uniqueid) == rq->por_uid)
832  {
833  BITMASK_SET_0(m_users_peeropts[i], rq->por_peeropts);
834  }
835  }
836 }
837 
838 void Network::BroadcastChatMsg(const char* msg)
839 {
840  AddPacket(m_stream_id, RoRnet::MSG2_UTF8_CHAT, (int)std::strlen(msg), msg);
841 }
842 
843 void Network::WhisperChatMsg(RoRnet::UserInfo const& user, const char* msg)
844 {
845  // Prepare buffer
846  char payload[RORNET_MAX_MESSAGE_LENGTH - sizeof(RoRnet::Header)];
847  size_t payload_len = 0;
848 
849  // Write client ID
850  std::memcpy(payload, &user.uniqueid, sizeof(user.uniqueid));
851  payload_len += sizeof(user.uniqueid);
852 
853  // Write text
854  std::strncpy(payload + payload_len, msg, sizeof(payload) - payload_len);
855  payload_len += std::strlen(msg);
856 
857  // Queue packet
858  AddPacket(m_stream_id, RoRnet::MSG2_UTF8_PRIVCHAT, (int)payload_len, msg);
859 }
860 
862 {
863  if (user.authstatus & AUTH_ADMIN) { return _LC("NetUserAuth", "Admin"); }
864  else if (user.authstatus & AUTH_MOD) { return _LC("NetUserAuth", "Mod"); }
865  else if (user.authstatus & AUTH_BOT) { return _LC("NetUserAuth", "Bot"); }
866  else if (user.authstatus & AUTH_RANKED) { return _LC("NetUserAuth", "Ranked"); }
867  else if (user.authstatus & AUTH_BANNED) { return _LC("NetUserAuth", "Banned"); }
868  else { return _LC("NetUserAuth", "Guest"); }
869 }
870 
872 {
873  if (user.authstatus & AUTH_ADMIN) { return _LC("NetUserAuth","Server Administrator"); }
874  else if (user.authstatus & AUTH_MOD) { return _LC("NetUserAuth","Server Moderator"); }
875  else if (user.authstatus & AUTH_BOT) { return _LC("NetUserAuth","Bot"); }
876  else if (user.authstatus & AUTH_RANKED) { return _LC("NetUserAuth","Ranked user"); }
877  else if (user.authstatus & AUTH_BANNED) { return _LC("NetUserAuth","Banned user"); }
878  else { return _LC("NetUserAuth","Guest"); }
879 }
880 
881 #endif // USE_SOCKETW
ROR_ASSERT
#define ROR_ASSERT(_EXPR)
Definition: Application.h:40
GameContext.h
Game state manager and message-queue provider.
RoR::Network::Disconnect
void Disconnect()
Definition: Network.cpp:572
RoRnet::MSG2_STREAM_UNREGISTER
@ MSG2_STREAM_UNREGISTER
remove stream
Definition: RoRnet.h:65
RoR::Network::GetUserInfos
std::vector< RoRnet::UserInfo > GetUserInfos()
Definition: Network.cpp:713
RoR::Network::PushNetMessage
void PushNetMessage(MsgType type, std::string const &message)
Definition: Network.cpp:87
RoR::Network::StartConnecting
bool StartConnecting()
Launches connecting on background.
Definition: Network.cpp:394
RoR::Network::ConnectThread
bool ConnectThread()
Definition: Network.cpp:427
RoR::Network::UserAuthToStringShort
std::string UserAuthToStringShort(RoRnet::UserInfo const &user)
Definition: Network.cpp:861
RoRnet::LegacyServerInfo
Definition: RoRnet.h:221
RoR::MSG_NET_USER_DISCONNECT
@ MSG_NET_USER_DISCONNECT
Definition: Application.h:105
RoR::Network::GetUserColor
int GetUserColor()
Definition: Network.cpp:695
m_packet_buffer_size
static const unsigned int m_packet_buffer_size
Definition: Network.cpp:82
RoRnet::UserInfo
Definition: RoRnet.h:180
RoR::Network::GetUID
int GetUID()
Definition: Network.cpp:122
RoRnet::Header::source
int32_t source
source of this command: 0 = server
Definition: RoRnet.h:145
RoRnet::MSG2_WRONG_PW
@ MSG2_WRONG_PW
server send that on wrong pw
Definition: RoRnet.h:43
DebugPacket
void DebugPacket(const char *name, RoRnet::Header *header, char *buffer)
Definition: Network.cpp:104
RoR::App::mp_player_name
CVar * mp_player_name
Definition: Application.cpp:124
RORNET_MAX_USERNAME_LEN
#define RORNET_MAX_USERNAME_LEN
bytes.
Definition: RoRnet.h:33
RoR::App::mp_player_token
CVar * mp_player_token
Definition: Application.cpp:125
RORNET_VERSION
#define RORNET_VERSION
Definition: RoRnet.h:35
GUI_TopMenubar.h
RoR::Network::QueueStreamData
void QueueStreamData(RoRnet::Header &header, char *buffer, size_t buffer_len)
Definition: Network.cpp:163
format
Truck file format(technical spec)
RoR::App::app_language
CVar * app_language
Definition: Application.cpp:80
RoR::Network::GetIncomingStreamData
std::vector< NetRecvPacket > GetIncomingStreamData()
Definition: Network.cpp:682
RoR::MSG_NET_CONNECT_STARTED
@ MSG_NET_CONNECT_STARTED
Definition: Application.h:99
RoR::PeerOptionsRequest::por_uid
int por_uid
RoRnet unique user ID.
Definition: Network.h:106
RoRnet::Header::command
uint32_t command
the command of this packet: MSG2_*
Definition: RoRnet.h:144
RoR::LogFormat
void LogFormat(const char *format,...)
Improved logging utility. Uses fixed 2Kb buffer.
Definition: Application.cpp:443
RoRnet::StreamRegister::origin_sourceid
int32_t origin_sourceid
origin sourceid
Definition: RoRnet.h:154
RoR::HashData
Ogre::String HashData(const char *key, int len)
Definition: Utils.cpp:54
RoRnet::AUTH_ADMIN
@ AUTH_ADMIN
admin on the server
Definition: RoRnet.h:78
Console.h
RoR::MSG_NET_RECV_ERROR
@ MSG_NET_RECV_ERROR
Definition: Application.h:106
RoRnet::ServerInfo
Definition: RoRnet.h:212
RoR::App::app_country
CVar * app_country
Definition: Application.cpp:81
RoR::ScriptEngine::queueStringForExecution
void queueStringForExecution(const Ogre::String command)
Queues a string for execution.
Definition: ScriptEngine.cpp:503
Utils.h
RoRnet
Definition: ForwardDeclarations.h:276
RoR::Network::GetAnyUserInfo
bool GetAnyUserInfo(int uid, RoRnet::UserInfo &result)
Also considers local client.
Definition: Network.cpp:767
RoR::Network::GetUserPeerOpts
bool GetUserPeerOpts(int uid, BitMask_t &result)
Definition: Network.cpp:739
RoRnet::AUTH_BANNED
@ AUTH_BANNED
banned
Definition: RoRnet.h:82
RoRnet::MSG2_FULL
@ MSG2_FULL
no more slots for us
Definition: RoRnet.h:42
RoRnet::MSG2_BANNED
@ MSG2_BANNED
client not allowed to join
Definition: RoRnet.h:45
Language.h
RoR::NetRecvPacket::header
RoRnet::Header header
Definition: Network.h:95
RoRnet::MSG2_USER_JOIN
@ MSG2_USER_JOIN
new user joined
Definition: RoRnet.h:57
RoRnet::MSG2_WRONG_VER_LEGACY
@ MSG2_WRONG_VER_LEGACY
Wrong version.
Definition: RoRnet.h:72
RoR::MSG_NET_SERVER_KICK
@ MSG_NET_SERVER_KICK
Definition: Application.h:103
GUIManager.h
RoR::Network::GetUserInfo
bool GetUserInfo(int uid, RoRnet::UserInfo &result)
Definition: Network.cpp:725
RoR::App::GetScriptEngine
ScriptEngine * GetScriptEngine()
Definition: Application.cpp:298
RoR::Console::CONSOLE_SYSTEM_NOTICE
@ CONSOLE_SYSTEM_NOTICE
Definition: Console.h:51
RoRnet::MSG2_UTF8_CHAT
@ MSG2_UTF8_CHAT
broadcast chat line in UTF8 encoding; Payload: const char*(text)
Definition: RoRnet.h:59
RoR::NetSendPacket::size
int size
Definition: Network.h:90
RoR::NetSendPacket::buffer
char buffer[RORNET_MAX_MESSAGE_LENGTH]
Definition: Network.h:89
RoR::App::mp_state
CVar * mp_state
Definition: Application.cpp:115
BITMASK_SET_0
#define BITMASK_SET_0(VAR, FLAGS)
Definition: BitFlags.h:16
TOSTRING
#define TOSTRING(x)
Definition: Application.h:57
RoR::MSG_GUI_OPEN_MP_SETTINGS_REQUESTED
@ MSG_GUI_OPEN_MP_SETTINGS_REQUESTED
Definition: Application.h:149
RoRnet::MSG2_GAME_CMD
@ MSG2_GAME_CMD
Script message. Can be sent in both directions.
Definition: RoRnet.h:56
RoR::GameContext::ChainMessage
void ChainMessage(Message m)
Add to last pushed message's chain.
Definition: GameContext.cpp:73
RoRnet::UserInfo::authstatus
int32_t authstatus
auth status set by server: AUTH_*
Definition: RoRnet.h:183
RoRnet::MSG2_UTF8_PRIVCHAT
@ MSG2_UTF8_PRIVCHAT
private chat line in UTF8 encoding; Payload: uint32_t(uniqueid), const char*(text)
Definition: RoRnet.h:60
RoR::Network::GetTerrainName
Ogre::String GetTerrainName()
Definition: Network.cpp:690
RoR::CVar::getStr
std::string const & getStr() const
Definition: CVar.h:95
RoR::Str
Wrapper for classic c-string (local buffer) Refresher: strlen() excludes '\0' terminator; strncat() A...
Definition: Str.h:35
RoR::Network::GetAllUsersPeerOpts
std::vector< BitMask_t > GetAllUsersPeerOpts()
Definition: Network.cpp:719
RoRnet::UserInfo::serverpassword
char serverpassword[40]
server password
Definition: RoRnet.h:189
ErrorUtils.h
RoRnet::LegacyServerInfo::protocolversion
char protocolversion[20]
protocol version being used
Definition: RoRnet.h:223
RoRnet::AUTH_MOD
@ AUTH_MOD
moderator status
Definition: RoRnet.h:80
RoR::MSG_GUI_MP_CLIENTS_REFRESH
@ MSG_GUI_MP_CLIENTS_REFRESH
Definition: Application.h:142
RoRnet::MSG2_STREAM_REGISTER
@ MSG2_STREAM_REGISTER
create new stream
Definition: RoRnet.h:63
ScriptEngine.h
BITMASK_SET_1
#define BITMASK_SET_1(VAR, FLAGS)
Definition: BitFlags.h:17
RoR::GameContext::PushMessage
void PushMessage(Message m)
Doesn't guarantee order! Use ChainMessage() if order matters.
Definition: GameContext.cpp:66
strnlen
#define strnlen(str, len)
Definition: InputEngine.cpp:400
RoR::Network::BroadcastChatMsg
void BroadcastChatMsg(const char *msg)
Definition: Network.cpp:838
RoR::App::mp_server_password
CVar * mp_server_password
Definition: Application.cpp:123
RoR::Network::GetDisconnectedUserInfo
bool GetDisconnectedUserInfo(int uid, RoRnet::UserInfo &result)
Definition: Network.cpp:753
RoR::Network::GetNetQuality
int GetNetQuality()
Definition: Network.cpp:117
ChatSystem.h
RoR::Str::ToCStr
const char * ToCStr() const
Definition: Str.h:46
RORNET_MAX_MESSAGE_LENGTH
#define RORNET_MAX_MESSAGE_LENGTH
maximum size of a RoR message. 8192 bytes = 8 kibibytes
Definition: RoRnet.h:31
RoR::Network::SendNetMessage
bool SendNetMessage(int type, unsigned int streamid, int len, char *content)
Definition: Network.cpp:140
RoR::PeerOptionsRequest::por_peeropts
BitMask_t por_peeropts
See RoRnet::PeerOptions.
Definition: Network.h:107
RoR::Network::CouldNotConnect
void CouldNotConnect(std::string const &msg, bool close_socket=true)
Definition: Network.cpp:382
RoR::Network::AddPeerOptions
void AddPeerOptions(PeerOptionsRequest *rq)
Definition: Network.cpp:804
RoR::MsgType
MsgType
Global gameplay message loop, see struct Message in GameContext.h.
Definition: Application.h:75
Application.h
Central state/object manager and communications hub.
RoR::App::GetConsole
Console * GetConsole()
Definition: Application.cpp:289
RoRnet::Header
< Common header for every packet
Definition: RoRnet.h:142
RoRnet::MSG2_STREAM_REGISTER_RESULT
@ MSG2_STREAM_REGISTER_RESULT
result of a stream creation
Definition: RoRnet.h:64
RoR::Network::GetLocalUserData
RoRnet::UserInfo GetLocalUserData()
Definition: Network.cpp:707
RoR::App::GetGameContext
GameContext * GetGameContext()
Definition: Application.cpp:299
RoRnet::Header::streamid
uint32_t streamid
streamid for this command
Definition: RoRnet.h:146
RoR::Console::doCommand
void doCommand(std::string msg)
Identify and execute any console line.
Definition: ConsoleCmd.cpp:706
RoR::Network::ReceiveMessage
int ReceiveMessage(RoRnet::Header *head, char *content, int bufferlen)
Definition: Network.cpp:173
RoRnet::UserInfo::sessiontype
char sessiontype[10]
the requested session type. For example "normal", "bot", "rcon"
Definition: RoRnet.h:194
RoRVersion.h
RoRnet::UserInfo::clientversion
char clientversion[25]
a version number of the client. For example 1 for RoR 0.35
Definition: RoRnet.h:192
RoRnet::AUTH_RANKED
@ AUTH_RANKED
ranked status
Definition: RoRnet.h:79
ROR_VERSION_STRING
const char *const ROR_VERSION_STRING
RoR::Message::description
std::string description
Definition: GameContext.h:58
RoRnet::UserInfo::clientname
char clientname[10]
the name and version of the client. For exmaple: "ror" or "gamebot"
Definition: RoRnet.h:191
_LC
#define _LC(ctx, str)
Definition: Language.h:38
RoR::Network::SendMessageRaw
bool SendMessageRaw(char *buffer, int msgsize)
Definition: Network.cpp:127
RoRnet::StreamRegister::status
int32_t status
initial stream status
Definition: RoRnet.h:153
RoR::Network::GetPlayerColor
Ogre::ColourValue GetPlayerColor(int color_num)
Definition: Network.cpp:94
RoR::MSG_NET_CONNECT_SUCCESS
@ MSG_NET_CONNECT_SUCCESS
Definition: Application.h:101
RoR::NetSendPacket
Definition: Network.h:87
RoRnet::MSG2_WRONG_VER
@ MSG2_WRONG_VER
wrong version
Definition: RoRnet.h:44
RoRnet::StreamRegister::type
int32_t type
0 = Actor, 1 = Character, 3 = ChatSystem
Definition: RoRnet.h:152
RoR::Sha1Hash
std::string Sha1Hash(std::string const &data)
Definition: Utils.cpp:141
RoR::Network::FindUserInfo
bool FindUserInfo(std::string const &username, RoRnet::UserInfo &result)
Definition: Network.cpp:789
RoR::Network::RecvThread
void RecvThread()
Definition: Network.cpp:238
RoRnet::UserInfo::username
char username[RORNET_MAX_USERNAME_LEN]
the nickname of the user (UTF-8)
Definition: RoRnet.h:187
RoRnet::UserInfo::uniqueid
uint32_t uniqueid
user unique id
Definition: RoRnet.h:182
RoR::Network::RemovePeerOptions
void RemovePeerOptions(PeerOptionsRequest *rq)
Definition: Network.cpp:821
RoR::Network::SetNetQuality
void SetNetQuality(int quality)
Definition: Network.cpp:112
RoR::Network::GetUsername
std::string GetUsername()
Definition: Network.cpp:701
RoR::App::mp_server_port
CVar * mp_server_port
Definition: Application.cpp:122
RoR::PeerOptionsRequest
Payload of MSG_NET_{ADD/REMOVE}_PEEROPTIONS_REQUESTED.
Definition: Network.h:104
RoR::Message
Unified game event system - all requests and state changes are reported using a message.
Definition: GameContext.h:51
RoR::App::mp_server_host
CVar * mp_server_host
Definition: Application.cpp:121
RoRnet::MSG2_STREAM_DATA_DISCARDABLE
@ MSG2_STREAM_DATA_DISCARDABLE
stream data that is allowed to be discarded
Definition: RoRnet.h:67
RoR::CVar::setVal
void setVal(T val)
Definition: CVar.h:72
_L
#define _L
Definition: ErrorUtils.cpp:35
RoR::Console::putNetMessage
void putNetMessage(int user_id, MessageType type, const char *text)
Definition: Console.cpp:108
RoR::MpState::DISABLED
@ DISABLED
Not connected for whatever reason.
RoRnet::AUTH_BOT
@ AUTH_BOT
bot status
Definition: RoRnet.h:81
RoRnet::StreamRegister::origin_streamid
int32_t origin_streamid
origin streamid
Definition: RoRnet.h:155
MP_COLORS
static Ogre::ColourValue MP_COLORS[]
Definition: Network.cpp:47
RoR::MSG_NET_CONNECT_FAILURE
@ MSG_NET_CONNECT_FAILURE
Definition: Application.h:102
RoR::NetRecvPacket::buffer
char buffer[RORNET_MAX_MESSAGE_LENGTH]
Definition: Network.h:96
BitMask_t
uint32_t BitMask_t
Definition: BitFlags.h:7
RoRnet::MSG2_NETQUALITY
@ MSG2_NETQUALITY
network quality information
Definition: RoRnet.h:53
RoR::Network::UserAuthToStringLong
std::string UserAuthToStringLong(RoRnet::UserInfo const &user)
Definition: Network.cpp:871
RoRnet::MSG2_HELLO
@ MSG2_HELLO
client sends its version as first message
Definition: RoRnet.h:39
RoR::CVar::getInt
int getInt() const
Definition: CVar.h:97
RoRnet::MSG2_NO_RANK
@ MSG2_NO_RANK
client has no ranked status
Definition: RoRnet.h:69
RoR::MSG_NET_CONNECT_PROGRESS
@ MSG_NET_CONNECT_PROGRESS
Definition: Application.h:100
RoRnet::MSG2_USER_INFO
@ MSG2_USER_INFO
user data that is sent from the server to the clients
Definition: RoRnet.h:51
RoR::Network::AddLocalStream
void AddLocalStream(RoRnet::StreamRegister *reg, int size)
Definition: Network.cpp:670
RoR::NetRecvPacket
Definition: Network.h:93
LOGSTREAM
#define LOGSTREAM
Definition: Network.cpp:85
RoRnet::MSG2_WELCOME
@ MSG2_WELCOME
we can proceed
Definition: RoRnet.h:46
RoR::Network::AddPacket
void AddPacket(int streamid, int type, int len, const char *content)
Definition: Network.cpp:616
RoR
Definition: AppContext.h:36
Network.h
RoRnet::UserInfo::language
char language[10]
user's language. For example "de-DE" or "en-US"
Definition: RoRnet.h:190
RoRnet::MSG2_USER_LEAVE
@ MSG2_USER_LEAVE
user leaves
Definition: RoRnet.h:58
RoRnet::UserInfo::usertoken
char usertoken[40]
user token
Definition: RoRnet.h:188
RoR::Network::SendThread
void SendThread()
Definition: Network.cpp:214
RoRnet::Header::size
uint32_t size
size of the attached data block
Definition: RoRnet.h:147
RoR::MpState::CONNECTING
@ CONNECTING
RoR::Network::WhisperChatMsg
void WhisperChatMsg(RoRnet::UserInfo const &user, const char *msg)
Definition: Network.cpp:843
RoRnet::StreamRegister
< Sent from the client to server and vice versa, to broadcast a new stream
Definition: RoRnet.h:150
LOG_THREAD
#define LOG_THREAD(_MSG_)
Definition: Network.cpp:84
RoR::Network::StopConnecting
void StopConnecting()
Definition: Network.cpp:419