libvwad: updated -- vwadwrite: free file buffers on close (otherwise archive creation...
[k8vavoom.git] / source / net / net_main.cpp
blob066438edea6e59a9243349302f476134529defd1
1 //**************************************************************************
2 //**
3 //** ## ## ## ## ## #### #### ### ###
4 //** ## ## ## ## ## ## ## ## ## ## #### ####
5 //** ## ## ## ## ## ## ## ## ## ## ## ## ## ##
6 //** ## ## ######## ## ## ## ## ## ## ## ### ##
7 //** ### ## ## ### ## ## ## ## ## ##
8 //** # ## ## # #### #### ## ##
9 //**
10 //** Copyright (C) 1999-2006 Jānis Legzdiņš
11 //** Copyright (C) 2018-2.020 Ketmar Dark
12 //**
13 //** This program is free software: you can redistribute it and/or modify
14 //** it under the terms of the GNU General Public License as published by
15 //** the Free Software Foundation, version 3 of the License ONLY.
16 //**
17 //** This program is distributed in the hope that it will be useful,
18 //** but WITHOUT ANY WARRANTY; without even the implied warranty of
19 //** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 //** GNU General Public License for more details.
21 //**
22 //** You should have received a copy of the GNU General Public License
23 //** along with this program. If not, see <http://www.gnu.org/licenses/>.
24 //**
25 //**************************************************************************
26 #include "../gamedefs.h"
27 #include "net_local.h"
30 static const char *cli_Port = nullptr;
31 //static int cli_Listen = 0;
33 /*static*/ bool cliRegister_netmain_args =
34 VParsedArgs::RegisterStringOption("-port", "explicitly set your host port (default is 26000)", &cli_Port)
35 /*&& VParsedArgs::RegisterFlagSet("-listen", nullptr, &cli_Listen)*/;
38 static VCvarS net_ui_last_join_address("net_ui_last_join_address", "127.0.0.1", "Last server address for manual connection (used in UI).", CVAR_Archive|CVAR_NoShadow);
41 // ////////////////////////////////////////////////////////////////////////// //
42 class VNetwork : public VNetworkLocal {
43 private:
44 VNetPollProcedure SlistSendProcedure;
45 VNetPollProcedure SlistPollProcedure;
46 VNetPollProcedure MasterListSendProcedure;
47 VNetPollProcedure MasterListPollProcedure;
49 bool SlistInProgress;
50 bool SlistSilent;
51 bool SlistLocal;
52 bool SlistSorted;
53 bool SlistMaster;
54 double SlistStartTime;
55 int SlistLastShown;
57 slist_t slist;
59 VNetPollProcedure *PollProcedureList;
61 public:
62 // public API
63 VNetwork ();
64 virtual ~VNetwork () override;
66 virtual void Init () override;
67 virtual void Shutdown () override;
68 virtual VSocketPublic *Connect (const char *) override;
69 virtual VSocketPublic *CheckNewConnections (bool rconOnly) override;
70 virtual void Poll () override;
71 virtual void StartSearch (bool) override;
72 virtual slist_t *GetSlist () override;
73 virtual void UpdateMaster () override;
74 virtual void QuitMaster () override;
76 // API only for network drivers!
77 virtual void SchedulePollProcedure (VNetPollProcedure *, double) override;
79 void MasterList ();
80 virtual void Slist () override;
82 private:
83 static void Slist_Send (void *);
84 static void Slist_Poll (void *);
85 void Slist_Send ();
86 void Slist_Poll ();
87 static void MasterList_Send (void *);
88 static void MasterList_Poll (void *);
89 void MasterList_Send ();
90 void MasterList_Poll ();
91 void PrintSlistHeader ();
92 void PrintSlist ();
93 void PrintSlistTrailer ();
97 // ////////////////////////////////////////////////////////////////////////// //
98 VNetworkPublic *GNet = nullptr;
100 VCvarS VNetworkLocal::HostName("hostname", "UNNAMED", "Name of this host.", CVAR_PreInit|CVAR_NoShadow);
102 VNetDriver *VNetworkLocal::Drivers[MAX_NET_DRIVERS];
103 int VNetworkLocal::NumDrivers = 0;
105 VNetLanDriver *VNetworkLocal::LanDrivers[MAX_NET_DRIVERS];
106 int VNetworkLocal::NumLanDrivers = 0;
109 //==========================================================================
111 // VNetworkPublic::Create
113 //==========================================================================
114 VNetworkPublic *VNetworkPublic::Create () {
115 return new VNetwork();
119 //==========================================================================
121 // VNetworkPublic::VNetworkPublic
123 //==========================================================================
124 VNetworkPublic::VNetworkPublic ()
125 : UnreliableMessagesSent(0)
126 , UnreliableMessagesReceived(0)
127 , packetsSent(0)
128 , packetsReSent(0)
129 , packetsReceived(0)
130 , receivedDuplicateCount(0)
131 , shortPacketCount(0)
132 , droppedDatagrams(0)
133 , bytesSent(0)
134 , bytesReceived(0)
135 , bytesRejected(0)
136 , minimalSentPacket(0)
137 , maximalSentPacket(0)
138 , CheckUserAbortCB(nullptr)
139 , CheckUserAbortUData(nullptr)
140 , CurrNetTime(-1)
145 //==========================================================================
147 // VNetworkPublic::UpdateNetTime
149 //==========================================================================
150 void VNetworkPublic::UpdateNetTime () noexcept {
151 CurrNetTime = Sys_Time();
155 //==========================================================================
157 // VNetworkPublic::GetNetTime
159 //==========================================================================
160 double VNetworkPublic::GetNetTime () noexcept {
161 if (CurrNetTime < 0) UpdateNetTime();
162 return CurrNetTime;
166 //==========================================================================
168 // VNetworkPublic::UpdateSentStats
170 //==========================================================================
171 void VNetworkPublic::UpdateSentStats (vuint32 length) noexcept {
172 if (length) {
173 bytesSent += length;
174 if (!minimalSentPacket || minimalSentPacket > length) minimalSentPacket = length;
175 if (maximalSentPacket < length) maximalSentPacket = length;
180 //==========================================================================
182 // VNetworkPublic::UpdateReceivedStats
184 //==========================================================================
185 void VNetworkPublic::UpdateReceivedStats (vuint32 length) noexcept {
186 bytesReceived += length;
190 //==========================================================================
192 // VNetworkPublic::UpdateRejectedStats
194 //==========================================================================
195 void VNetworkPublic::UpdateRejectedStats (vuint32 length) noexcept {
196 bytesRejected += length;
200 //==========================================================================
202 // VNetworkLocal::VNetworkLocal
204 //==========================================================================
205 VNetworkLocal::VNetworkLocal ()
206 : VNetworkPublic()
207 , ActiveSockets(nullptr)
208 , HostCacheCount(0)
209 , HostPort(0)
210 , DefaultHostPort(26000)
211 , IpAvailable(false)
212 , Listening(false)
214 MyIpAddress[0] = 0;
215 ReturnReason[0] = 0;
216 memset((void *)HostCache, 0, sizeof(HostCache));
220 //==========================================================================
222 // VNetwork::VNetwork
224 //==========================================================================
225 VNetwork::VNetwork()
226 : SlistSendProcedure(Slist_Send, this)
227 , SlistPollProcedure(Slist_Poll, this)
228 , MasterListSendProcedure(MasterList_Send, this)
229 , MasterListPollProcedure(MasterList_Poll, this)
230 , SlistInProgress(false)
231 , SlistSilent(false)
232 , SlistLocal(true)
233 , SlistSorted(true)
234 , SlistMaster(false)
235 , SlistStartTime(0.0)
236 , SlistLastShown(0)
237 , PollProcedureList(nullptr)
242 //==========================================================================
244 // VNetwork::~VNetwork
246 //==========================================================================
247 VNetwork::~VNetwork () {
248 Shutdown();
252 //==========================================================================
254 // VNetwork::Init
256 //==========================================================================
257 void VNetwork::Init () {
258 const char *p = cli_Port;
259 if (p && p[0]) {
260 DefaultHostPort = VStr::atoi(p);
261 if (DefaultHostPort < 1 || DefaultHostPort > 65535) DefaultHostPort = 26000;
263 HostPort = DefaultHostPort;
265 #ifdef CLIENT
266 //if (cli_Listen || cls.state == ca_dedicated) Listening = true;
267 #else
268 Listening = true;
269 #endif
271 // initialise all the drivers
272 for (int i = 0; i < NumDrivers; ++i) {
273 Drivers[i]->Net = this;
274 if (Drivers[i]->Init() != -1) {
275 Drivers[i]->initialised = true;
276 if (Listening) Drivers[i]->Listen(true);
280 if (developer && *MyIpAddress) GCon->Logf(NAME_DevNet, "TCP/IP address %s", MyIpAddress);
284 //==========================================================================
286 // VNetwork::Shutdown
288 //==========================================================================
289 void VNetwork::Shutdown () {
290 while (ActiveSockets) {
291 delete ActiveSockets;
292 ActiveSockets = nullptr;
295 // shutdown the drivers
296 for (int i = 0; i < NumDrivers; ++i) {
297 if (Drivers[i]->initialised) {
298 Drivers[i]->Shutdown();
299 Drivers[i]->initialised = false;
305 //==========================================================================
307 // VNetwork::Poll
309 //==========================================================================
310 void VNetwork::Poll () {
311 UpdateNetTime();
312 const double ctt = GetNetTime();
313 for (VNetPollProcedure *pp = PollProcedureList; pp; pp = pp->next) {
314 if (pp->nextTime > ctt) break;
315 PollProcedureList = pp->next;
316 pp->procedure(pp->arg);
321 //==========================================================================
323 // VNetwork::SchedulePollProcedure
325 //==========================================================================
326 void VNetwork::SchedulePollProcedure (VNetPollProcedure *proc, double timeOffset) {
327 VNetPollProcedure *pp, *prev;
329 proc->nextTime = Sys_Time()+timeOffset;
330 for (pp = PollProcedureList, prev = nullptr; pp; pp = pp->next) {
331 if (pp->nextTime >= proc->nextTime) break;
332 prev = pp;
335 if (prev == nullptr) {
336 proc->next = PollProcedureList;
337 PollProcedureList = proc;
338 } else {
339 proc->next = pp;
340 prev->next = proc;
345 //==========================================================================
347 // VNetwork::Slist
349 //==========================================================================
350 void VNetwork::Slist () {
351 if (SlistInProgress) return;
353 if (!SlistSilent) {
354 GCon->Log(NAME_DevNet, "Looking for k8vavoom servers");
355 PrintSlistHeader();
358 SlistMaster = false;
359 SlistInProgress = true;
360 SlistStartTime = Sys_Time();
362 SchedulePollProcedure(&SlistSendProcedure, 0.0);
363 SchedulePollProcedure(&SlistPollProcedure, 0.1);
365 HostCacheCount = 0;
369 //==========================================================================
371 // VNetwork::Slist_Send
373 //==========================================================================
374 void VNetwork::Slist_Send (void *Arg) {
375 ((VNetwork *)Arg)->Slist_Send();
379 //==========================================================================
381 // VNetwork::Slist_Poll
383 //==========================================================================
384 void VNetwork::Slist_Poll (void *Arg) {
385 ((VNetwork *)Arg)->Slist_Poll();
389 //==========================================================================
391 // VNetwork::Slist_Send
393 //==========================================================================
394 void VNetwork::Slist_Send () {
395 for (int i = 0; i < NumDrivers; ++i) {
396 if (!SlistLocal && i == 0) continue;
397 if (Drivers[i]->initialised == false) continue;
398 Drivers[i]->SearchForHosts(true, SlistMaster);
401 if ((Sys_Time()-SlistStartTime) < 0.5) SchedulePollProcedure(&SlistSendProcedure, 0.75);
405 //==========================================================================
407 // VNetwork::Slist_Poll
409 //==========================================================================
410 void VNetwork::Slist_Poll () {
411 for (int i = 0; i < NumDrivers; ++i) {
412 if (!SlistLocal && i == 0) continue;
413 if (Drivers[i]->initialised == false) continue;
414 Drivers[i]->SearchForHosts(false, SlistMaster);
417 if (!SlistSilent) PrintSlist();
419 if ((Sys_Time()-SlistStartTime) < 1.5) {
420 SchedulePollProcedure(&SlistPollProcedure, 0.1);
421 return;
424 if (!SlistSilent) PrintSlistTrailer();
425 SlistInProgress = false;
426 SlistSilent = false;
427 SlistLocal = true;
428 SlistSorted = false;
432 //==========================================================================
434 // VNetwork::MasterList
436 //==========================================================================
437 void VNetwork::MasterList () {
438 if (SlistInProgress) return;
440 if (!SlistSilent) {
441 GCon->Log(NAME_DevNet, "Looking for k8vavoom servers");
442 PrintSlistHeader();
445 SlistMaster = true;
446 SlistInProgress = true;
447 SlistStartTime = Sys_Time();
449 SchedulePollProcedure(&MasterListSendProcedure, 0.0);
450 SchedulePollProcedure(&MasterListPollProcedure, 0.1);
452 HostCacheCount = 0;
456 //==========================================================================
458 // VNetwork::MasterList_Send
460 //==========================================================================
461 void VNetwork::MasterList_Send (void *Arg) {
462 ((VNetwork *)Arg)->MasterList_Send();
466 //==========================================================================
468 // VNetwork::MasterList_Poll
470 //==========================================================================
471 void VNetwork::MasterList_Poll (void *Arg) {
472 ((VNetwork *)Arg)->MasterList_Poll();
476 //==========================================================================
478 // VNetwork::MasterList_Send
480 //==========================================================================
481 void VNetwork::MasterList_Send () {
482 for (int i = 0; i < NumDrivers; ++i) {
483 if (Drivers[i]->initialised == false) continue;
484 Drivers[i]->QueryMaster(true);
487 if ((Sys_Time()-SlistStartTime) < 0.5) SchedulePollProcedure(&MasterListSendProcedure, 0.75);
491 //==========================================================================
493 // VNetwork::MasterList_Poll
495 //==========================================================================
496 void VNetwork::MasterList_Poll () {
497 // check for reply from master server
498 bool GotList = false;
499 for (int i = 0; i < NumDrivers; ++i) {
500 if (Drivers[i]->initialised == false) continue;
501 if (Drivers[i]->QueryMaster(false)) GotList = true;
504 // if no reply, try again
505 if (!GotList && (Sys_Time()-SlistStartTime) < 1.5) {
506 SchedulePollProcedure(&MasterListPollProcedure, 0.1);
507 return;
510 // close socket for communicating with master server
511 for (int i = 0; i < NumDrivers; ++i) {
512 if (Drivers[i]->initialised) Drivers[i]->EndQueryMaster();
515 // if we got list, server info command has been sent to all servers, so start listening for their replies
516 if (GotList) {
517 SlistStartTime = Sys_Time();
518 SchedulePollProcedure(&SlistPollProcedure, 0.1);
519 return;
522 // could not connect to the master server
523 if (!SlistSilent) {
524 GCon->Log(NAME_DevNet, "Could not connect to the master server.");
527 SlistInProgress = false;
528 SlistSilent = false;
529 SlistLocal = true;
530 SlistSorted = false;
534 //==========================================================================
536 // VNetwork::PrintSlistHeader
538 //==========================================================================
539 void VNetwork::PrintSlistHeader () {
540 GCon->Log(NAME_DevNet, "Server Map Users");
541 GCon->Log(NAME_DevNet, "--------------- --------------- -----");
542 SlistLastShown = 0;
546 //==========================================================================
548 // VNetwork::PrintSlist
550 //==========================================================================
551 void VNetwork::PrintSlist () {
552 int n;
553 for (n = SlistLastShown; n < HostCacheCount; ++n) {
554 if (HostCache[n].MaxUsers) {
555 GCon->Logf(NAME_DevNet, "%-15s %-15s %2d/%2d", *HostCache[n].Name, *HostCache[n].Map, HostCache[n].Users, HostCache[n].MaxUsers);
556 } else {
557 GCon->Logf(NAME_DevNet, "%-15s %-15s", *HostCache[n].Name, *HostCache[n].Map);
560 SlistLastShown = n;
564 //==========================================================================
566 // VNetwork::PrintSlistTrailer
568 //==========================================================================
569 void VNetwork::PrintSlistTrailer () {
570 if (HostCacheCount) {
571 GCon->Log(NAME_DevNet, "== end list ==");
572 } else {
573 GCon->Log(NAME_DevNet, "No k8vavoom servers found.");
575 GCon->Log(NAME_DevNet, "");
579 //==========================================================================
581 // VNetwork::StartSearch
583 //==========================================================================
584 void VNetwork::StartSearch (bool Master) {
585 SlistSilent = true;
586 SlistLocal = false;
587 GCon->Logf(NAME_DevNet, "VNetwork::StartSearch: Master=%d", (int)Master);
588 if (Master) {
589 MasterList();
590 } else {
591 Slist();
596 //==========================================================================
598 // VNetwork::GetSlist
600 //==========================================================================
601 slist_t *VNetwork::GetSlist () {
602 if (!SlistSorted) {
603 if (HostCacheCount > 1) {
604 vuint8 temp[sizeof(hostcache_t)];
605 for (int i = 0; i < HostCacheCount; ++i) {
606 for (int j = i+1; j < HostCacheCount; ++j) {
607 if (HostCache[j].Name.Cmp(HostCache[i].Name) < 0) {
608 memcpy(&temp, (void *)(&HostCache[j]), sizeof(hostcache_t));
609 memcpy((void *)(&HostCache[j]), (void *)(&HostCache[i]), sizeof(hostcache_t));
610 memcpy((void *)(&HostCache[i]), &temp, sizeof(hostcache_t));
615 SlistSorted = true;
616 memset(ReturnReason, 0, sizeof(ReturnReason));
619 if (SlistInProgress) {
620 slist.Flags |= slist_t::SF_InProgress;
621 } else {
622 slist.Flags &= ~slist_t::SF_InProgress;
624 slist.Count = HostCacheCount;
625 slist.Cache = HostCache;
626 slist.ReturnReason = ReturnReason;
627 return &slist;
631 //==========================================================================
633 // VNetwork::Connect
635 //==========================================================================
636 VSocketPublic *VNetwork::Connect (const char *InHost) {
637 VStr host = InHost;
638 VSocket *ret;
639 int numdrivers = NumDrivers;
640 int n;
642 if (host.IsNotEmpty()) {
643 if (host == "local") {
644 numdrivers = 1;
645 goto JustDoIt;
648 if (HostCacheCount) {
649 for (n = 0; n < HostCacheCount; ++n) {
650 if (HostCache[n].Name.ICmp(host) == 0) {
651 host = HostCache[n].CName;
652 break;
655 if (n < HostCacheCount) goto JustDoIt;
659 SlistSilent = host.IsNotEmpty();
660 Slist();
662 while (SlistInProgress && !CheckForUserAbort()) {
663 Poll();
666 if (host.IsEmpty()) {
667 if (HostCacheCount != 1) return nullptr;
668 host = HostCache[0].CName;
669 GCon->Log(NAME_DevNet, "Connecting to");
670 GCon->Logf(NAME_DevNet, "%s @ %s", *HostCache[0].Name, *host);
673 if (HostCacheCount) {
674 for (n = 0; n < HostCacheCount; ++n) {
675 if (HostCache[n].Name.ICmp(host) == 0) {
676 host = HostCache[n].CName;
677 break;
682 JustDoIt:
683 for (int i = 0; i < numdrivers; ++i) {
684 if (Drivers[i]->initialised == false) continue;
685 ret = Drivers[i]->Connect(*host);
686 if (ret) return ret;
689 if (host.IsNotEmpty()) {
690 PrintSlistHeader();
691 PrintSlist();
692 PrintSlistTrailer();
695 return nullptr;
699 //==========================================================================
701 // VNetwork::CheckNewConnections
703 //==========================================================================
704 VSocketPublic *VNetwork::CheckNewConnections (bool rconOnly) {
705 for (int i = 0; i < NumDrivers; ++i) {
706 if (Drivers[i]->initialised == false) continue;
707 if (i && Listening == false) continue;
708 VSocket *ret = Drivers[i]->CheckNewConnections(rconOnly);
709 if (ret) return ret;
711 return nullptr;
715 //==========================================================================
717 // VNetwork::UpdateMaster
719 //==========================================================================
720 void VNetwork::UpdateMaster () {
721 for (int i = 0; i < NumDrivers; ++i) {
722 if (!Drivers[i]->initialised) continue;
723 Drivers[i]->UpdateMaster();
728 //==========================================================================
730 // VNetwork::QuitMaster
732 //==========================================================================
733 void VNetwork::QuitMaster () {
734 for (int i = 0; i < NumDrivers; ++i) {
735 if (!Drivers[i]->initialised) continue;
736 Drivers[i]->QuitMaster();
741 //==========================================================================
743 // VSocketPublic::u64str
745 //==========================================================================
746 VStr VSocketPublic::u64str (vuint64 v, bool comatose) noexcept {
747 if (!v) return VStr("0");
748 char buf[128];
749 unsigned dpos = (unsigned)sizeof(buf);
750 int digitsPut = (comatose ? 0 : 666);
751 buf[--dpos] = 0;
752 do {
753 if (digitsPut == 3) {
754 if (!dpos) abort();
755 buf[--dpos] = ',';
756 digitsPut = 0;
758 if (!dpos) abort();
759 buf[--dpos] = '0'+(int)(v%10);
760 ++digitsPut;
761 } while (v /= 10);
762 return VStr(buf+dpos);
766 //==========================================================================
768 // VSocketPublic::DumpStats
770 //==========================================================================
771 void VSocketPublic::DumpStats () {
772 if (bytesSent|bytesReceived|bytesRejected) {
773 if (bytesRejected) {
774 GCon->Logf(NAME_DevNet, "Closing stats for %s: %s bytes sent, %s bytes received (%s rejected)", *Address, *u64str(bytesSent), *u64str(bytesReceived), *u64str(bytesRejected));
775 } else {
776 GCon->Logf(NAME_DevNet, "Closing stats for %s: %s bytes sent, %s bytes received", *Address, *u64str(bytesSent), *u64str(bytesReceived));
782 //==========================================================================
784 // VSocketPublic::UpdateSentStats
786 //==========================================================================
787 void VSocketPublic::UpdateSentStats (vuint32 length) noexcept {
788 if (length) {
789 bytesSent += length;
790 if (!minimalSentPacket || minimalSentPacket > length) minimalSentPacket = length;
791 if (maximalSentPacket < length) maximalSentPacket = length;
796 //==========================================================================
798 // VSocketPublic::UpdateReceivedStats
800 //==========================================================================
801 void VSocketPublic::UpdateReceivedStats (vuint32 length) noexcept {
802 bytesReceived += length;
806 //==========================================================================
808 // VSocketPublic::UpdateRejectedStats
810 //==========================================================================
811 void VSocketPublic::UpdateRejectedStats (vuint32 length) noexcept {
812 bytesRejected += length;
816 //==========================================================================
818 // VSocket::VSocket
820 //==========================================================================
821 VSocket::VSocket (VNetDriver *Drv) : Driver(Drv) {
822 // add it to active list
823 Next = Driver->Net->ActiveSockets;
824 Driver->Net->ActiveSockets = this;
826 Driver->Net->UpdateNetTime();
827 ConnectTime = Driver->Net->GetNetTime();
828 Address = "UNSET ADDRESS";
829 LastMessageTime = ConnectTime;
833 //==========================================================================
835 // VSocket::~VSocket
837 //==========================================================================
838 VSocket::~VSocket () {
839 // remove it from active list
840 if (this == Driver->Net->ActiveSockets) {
841 Driver->Net->ActiveSockets = Driver->Net->ActiveSockets->Next;
842 } else {
843 VSocket *s = nullptr;
844 for (s = Driver->Net->ActiveSockets; s; s = s->Next) {
845 if (s->Next == this) {
846 s->Next = this->Next;
847 break;
850 if (!s) Sys_Error("NET_FreeQSocket: not active");
855 //==========================================================================
857 // VSocket::UpdateSentStats
859 //==========================================================================
860 void VSocket::UpdateSentStats (vuint32 length) noexcept {
861 VSocketPublic::UpdateSentStats(length);
862 if (Driver && Driver->Net) Driver->Net->UpdateSentStats(length);
866 //==========================================================================
868 // VSocket::UpdateReceivedStats
870 //==========================================================================
871 void VSocket::UpdateReceivedStats (vuint32 length) noexcept {
872 VSocketPublic::UpdateReceivedStats(length);
873 if (Driver && Driver->Net) Driver->Net->UpdateReceivedStats(length);
877 //==========================================================================
879 // VSocket::UpdateRejectedStats
881 //==========================================================================
882 void VSocket::UpdateRejectedStats (vuint32 length) noexcept {
883 VSocketPublic::UpdateRejectedStats(length);
884 if (Driver && Driver->Net) Driver->Net->UpdateRejectedStats(length);
888 //==========================================================================
890 // VNetDriver::VNetDriver
892 //==========================================================================
893 VNetDriver::VNetDriver (int Level, const char *AName) : name(AName), initialised(false) {
894 VNetwork::Drivers[Level] = this;
895 if (VNetwork::NumDrivers <= Level) VNetwork::NumDrivers = Level+1;
899 //==========================================================================
901 // VNetLanDriver::VNetLanDriver
903 //==========================================================================
904 VNetLanDriver::VNetLanDriver (int Level, const char *AName)
905 : name(AName)
906 , initialised(false)
907 , controlSock(-1)
908 , MasterQuerySocket(-1)
909 , net_acceptsocket(-1)
910 , net_controlsocket(-1)
911 , net_broadcastsocket(-1)
912 , myAddr(0)
914 memset(&broadcastaddr, 0, sizeof(broadcastaddr));
915 VNetwork::LanDrivers[Level] = this;
916 if (VNetwork::NumLanDrivers <= Level) VNetwork::NumLanDrivers = Level+1;
920 //==========================================================================
922 // VNetUtils::TVMsecs
924 //==========================================================================
925 void VNetUtils::TVMsecs (timeval *dest, int msecs) noexcept {
926 if (!dest) return;
927 if (msecs < 0) msecs = 0;
928 dest->tv_sec = msecs/1000;
929 dest->tv_usec = msecs%1000;
930 dest->tv_usec *= 1000;
934 //==========================================================================
936 // VNetUtils::CRC32C
938 // start with 0, continuous
940 //==========================================================================
941 vuint32 VNetUtils::CRC32C (vuint32 crc32, const void *buf, size_t length) noexcept {
942 return crc32cBuffer(crc32, buf, length);
946 //==========================================================================
948 // VNetUtils::ChaCha20XCrypt
950 // encrypts or decrypts a full message
951 // cypher is symmetric, so `ciphertextdata` and `plaintextdata`
952 // can point to the same address
954 //==========================================================================
955 void VNetUtils::ChaCha20XCrypt (const vuint8 keydata[ChaCha20KeySize], const vuint32 nonce,
956 void *ciphertextdata, const void *plaintextdata, vuint32 msglen) noexcept
958 vuint8 noncebuf[8];
959 memset(noncebuf, 0, sizeof(noncebuf));
960 noncebuf[0] = nonce&0xffu;
961 noncebuf[1] = (nonce>>8)&0xffu;
962 noncebuf[2] = (nonce>>16)&0xffu;
963 noncebuf[3] = (nonce>>24)&0xffu;
964 noncebuf[5] = 0x02;
965 noncebuf[6] = 0x9a;
966 (void)crypto_chacha20_djb((uint8_t *)ciphertextdata, (const uint8_t *)plaintextdata, msglen, keydata, noncebuf, 0/*ctr*/);
970 //==========================================================================
972 // VNetUtils::GenerateKey
974 //==========================================================================
975 void VNetUtils::GenerateKey (vuint8 key[ChaCha20KeySize]) noexcept {
977 vuint32 *dest = (vuint32 *)key;
978 for (int f = 0; f < ChaCha20KeySize/4; ++f) *dest++ = GenRandomU32();
980 prng_randombytes(key, ChaCha20KeySize);
984 //==========================================================================
986 // VNetUtils::DerivePublicKey
988 // derive public key from secret one
990 //==========================================================================
991 void VNetUtils::DerivePublicKey (vuint8 mypk[ChaCha20KeySize], const vuint8 mysk[ChaCha20KeySize]) {
992 //curve25519_donna_public(mypk, mysk);
993 crypto_x25519_public_key(mypk, mysk);
997 //==========================================================================
999 // VNetUtils::DeriveSharedKey
1001 // derive shared secret from our secret and their public
1003 //==========================================================================
1004 void VNetUtils::DeriveSharedKey (vuint8 sharedk[ChaCha20KeySize], const vuint8 mysk[ChaCha20KeySize], const vuint8 theirpk[ChaCha20KeySize]) {
1005 //curve25519_donna_shared(sharedk, mysk, theirpk);
1006 crypto_x25519(sharedk, mysk, theirpk);
1010 //==========================================================================
1012 // VNetUtils::EncryptInfoPacket
1014 // WARNING! cannot do it in-place
1015 // needs 24 extra bytes (key, nonce, crc)
1016 // returns new length or -1 on error
1018 //==========================================================================
1019 int VNetUtils::EncryptInfoPacket (void *destbuf, const void *srcbuf, int srclen, const vuint8 key[ChaCha20KeySize]) noexcept {
1020 if (srclen < 0) return -1;
1021 if (!destbuf) return -1;
1022 if (srclen > 0 && !srcbuf) return -1;
1023 //const vuint32 nonce = GenRandomU32();
1024 vuint32 nonce;
1025 prng_randombytes(&nonce, sizeof(nonce));
1026 vuint8 *dest = (vuint8 *)destbuf;
1027 // copy key
1028 memcpy(dest, key, ChaCha20KeySize);
1029 // copy nonce
1030 dest[ChaCha20KeySize+0] = nonce&0xffU;
1031 dest[ChaCha20KeySize+1] = (nonce>>8)&0xffU;
1032 dest[ChaCha20KeySize+2] = (nonce>>16)&0xffU;
1033 dest[ChaCha20KeySize+3] = (nonce>>24)&0xffU;
1034 // copy crc32
1035 const vuint32 crc32 = CRC32C(0, srcbuf, (unsigned)srclen);
1036 dest[ChaCha20KeySize+4] = crc32&0xffU;
1037 dest[ChaCha20KeySize+5] = (crc32>>8)&0xffU;
1038 dest[ChaCha20KeySize+6] = (crc32>>16)&0xffU;
1039 dest[ChaCha20KeySize+7] = (crc32>>24)&0xffU;
1040 // copy data
1041 if (srclen) memcpy(dest+ChaCha20HeaderSize, srcbuf, (unsigned)srclen);
1042 // encrypt crc32 and data
1043 ChaCha20XCrypt(key, nonce, dest+ChaCha20KeySize+ChaCha20NonceSize, dest+ChaCha20KeySize+ChaCha20NonceSize, (unsigned)(srclen+ChaCha20CheckSumSize));
1044 return srclen+ChaCha20HeaderSize;
1048 //==========================================================================
1050 // VNetUtils::DecryptInfoPacket
1052 // it can decrypt in-place
1053 // returns new length or -1 on error
1054 // also sets key
1056 //==========================================================================
1057 int VNetUtils::DecryptInfoPacket (vuint8 key[ChaCha20KeySize], void *destbuf, const void *srcbuf, int srclen) noexcept {
1058 if (srclen < ChaCha20HeaderSize) return -1;
1059 if (!destbuf) return -1;
1060 if (!srcbuf) return -1;
1061 srclen -= ChaCha20KeySize+ChaCha20NonceSize; // key and nonce
1062 const vuint8 *src = (const vuint8 *)srcbuf;
1063 vuint8 *dest = (vuint8 *)destbuf;
1064 // get key
1065 memcpy(key, srcbuf, ChaCha20KeySize);
1066 // get nonce
1067 vuint32 nonce =
1068 ((vuint32)src[ChaCha20KeySize+0])|
1069 (((vuint32)src[ChaCha20KeySize+1])<<8)|
1070 (((vuint32)src[ChaCha20KeySize+2])<<16)|
1071 (((vuint32)src[ChaCha20KeySize+3])<<24);
1072 // decrypt packet
1073 ChaCha20XCrypt(key, nonce, dest, src+ChaCha20KeySize+ChaCha20NonceSize, (unsigned)srclen);
1074 // calculate and check crc32
1075 srclen -= ChaCha20CheckSumSize;
1076 vassert(srclen >= 0);
1077 vuint32 crc32 = CRC32C(0, dest+ChaCha20CheckSumSize, (unsigned)srclen);
1078 if ((crc32&0xff) != dest[0] ||
1079 ((crc32>>8)&0xff) != dest[1] ||
1080 ((crc32>>16)&0xff) != dest[2] ||
1081 ((crc32>>24)&0xff) != dest[3])
1083 // oops
1084 return -1;
1086 // copy decrypted data
1087 if (srclen > 0) memcpy(dest, dest+ChaCha20CheckSumSize, (unsigned)srclen);
1088 return srclen;
1093 #if defined(CLIENT) && defined(SERVER) /* I think like this */
1094 //==========================================================================
1096 // COMMAND Listen
1098 //==========================================================================
1099 COMMAND(Listen) {
1100 VNetwork *Net = (VNetwork *)GNet;
1101 if (Args.length() != 2) {
1102 GCon->Logf(NAME_DevNet, "\"listen\" is \"%d\"", Net->Listening ? 1 : 0);
1103 return;
1105 Net->Listening = (VStr::atoi(*Args[1]) ? true : false);
1106 for (int i = 0; i < VNetwork::NumDrivers; ++i) {
1107 if (VNetwork::Drivers[i]->initialised == false) continue;
1108 VNetwork::Drivers[i]->Listen(Net->Listening);
1111 #endif
1114 //==========================================================================
1116 // COMMAND Port
1118 //==========================================================================
1119 COMMAND(Port) {
1120 int n;
1122 VNetwork *Net = (VNetwork *)GNet;
1123 if (Args.length() != 2) {
1124 GCon->Logf(NAME_DevNet, "\"port\" is \"%d\"", Net->HostPort);
1125 return;
1128 n = VStr::atoi(*Args[1]);
1129 if (n < 1 || n > 65534) {
1130 GCon->Log(NAME_Error, "Bad value, must be between 1 and 65534");
1131 return;
1134 Net->DefaultHostPort = n;
1135 Net->HostPort = n;
1137 if (Net->Listening) {
1138 // force a change to the new port
1139 GCmdBuf << "listen 0\n";
1140 GCmdBuf << "listen 1\n";
1145 //==========================================================================
1147 // COMMAND Slist
1149 //==========================================================================
1150 COMMAND(Slist) {
1151 ((VNetwork *)GNet)->Slist();
1155 //==========================================================================
1157 // COMMAND MasterList
1159 //==========================================================================
1160 COMMAND(MasterList) {
1161 ((VNetwork *)GNet)->MasterList();