libvwad: updated -- vwadwrite: free file buffers on close (otherwise archive creation...
[k8vavoom.git] / source / net / net_loopback.cpp
blob279c5fc7c9d2b4487d37bfe1a050af52e66d5c27
1 //**************************************************************************
2 //**
3 //** ## ## ## ## ## #### #### ### ###
4 //** ## ## ## ## ## ## ## ## ## ## #### ####
5 //** ## ## ## ## ## ## ## ## ## ## ## ## ## ##
6 //** ## ## ######## ## ## ## ## ## ## ## ### ##
7 //** ### ## ## ### ## ## ## ## ## ##
8 //** # ## ## # #### #### ## ##
9 //**
10 //** Copyright (C) 1999-2006 Jānis Legzdiņš
11 //** Copyright (C) 2018-2023 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 "../server/server.h"
28 #include "net_local.h"
31 // ////////////////////////////////////////////////////////////////////////// //
32 struct VLoopbackMessage {
33 TArray<vuint8> Data;
37 // ////////////////////////////////////////////////////////////////////////// //
38 class VLoopbackSocket : public VSocket {
39 public:
40 VLoopbackSocket *OtherSock;
41 TArray<VLoopbackMessage> LoopbackMessages;
43 public:
44 VLoopbackSocket (VNetDriver *Drv) : VSocket(Drv), OtherSock(nullptr) {}
45 virtual ~VLoopbackSocket () override;
47 virtual int GetMessage (void *dest, size_t destSize) override;
48 virtual int SendMessage (const vuint8 *, vuint32) override;
49 virtual bool IsLocalConnection () const noexcept override;
53 // ////////////////////////////////////////////////////////////////////////// //
54 class VLoopbackDriver : public VNetDriver {
55 public:
56 bool localconnectpending;
57 VLoopbackSocket *loop_client;
58 VLoopbackSocket *loop_server;
60 public:
61 VLoopbackDriver ();
63 virtual int Init () override;
64 virtual void Listen (bool) override;
65 virtual void SearchForHosts (bool, bool) override;
66 virtual VSocket *Connect (const char *) override;
67 virtual VSocket *CheckNewConnections (bool rconOnly) override;
68 virtual void UpdateMaster () override;
69 virtual void QuitMaster () override;
70 virtual bool QueryMaster (bool) override;
71 virtual void EndQueryMaster () override;
72 virtual void Shutdown () override;
74 static int IntAlign (int);
78 static VLoopbackDriver Impl;
81 //==========================================================================
83 // VLoopbackDriver::VLoopbackDriver
85 //==========================================================================
86 VLoopbackDriver::VLoopbackDriver ()
87 : VNetDriver(0, "Loopback")
88 , localconnectpending(false)
89 , loop_client(nullptr)
90 , loop_server(nullptr)
95 //==========================================================================
97 // VLoopbackDriver::Init
99 //==========================================================================
100 int VLoopbackDriver::Init () {
101 #ifdef CLIENT
102 if (GGameInfo && GGameInfo->NetMode == NM_DedicatedServer) return -1;
103 return 0;
104 #else
105 return -1;
106 #endif
110 //==========================================================================
112 // VLoopbackDriver::Listen
114 //==========================================================================
115 void VLoopbackDriver::Listen (bool) {
119 //==========================================================================
121 // VLoopbackDriver::SearchForHosts
123 //==========================================================================
124 void VLoopbackDriver::SearchForHosts (bool, bool ForMaster) {
125 #ifdef SERVER
126 if (GGameInfo->NetMode == NM_None || GGameInfo->NetMode == NM_Client || ForMaster) return;
127 Net->HostCacheCount = 1;
128 if (VStr::Cmp(Net->HostName, "UNNAMED") == 0) {
129 Net->HostCache[0].Name = "local";
130 } else {
131 Net->HostCache[0].Name = Net->HostName;
133 Net->HostCache[0].Map = VStr(GLevel->MapName);
134 Net->HostCache[0].Users = svs.num_connected;
135 Net->HostCache[0].MaxUsers = svs.max_clients;
136 Net->HostCache[0].CName = "local";
137 #endif
141 //==========================================================================
143 // VLoopbackDriver::Connect
145 //==========================================================================
146 VSocket *VLoopbackDriver::Connect (const char *host) {
147 if (VStr::Cmp(host, "local") != 0) return nullptr;
149 localconnectpending = true;
151 if (!loop_client) {
152 loop_client = new VLoopbackSocket(this);
153 loop_client->Address = "localhost";
156 if (!loop_server) {
157 loop_server = new VLoopbackSocket(this);
158 loop_server->Address = "LOCAL";
161 vuint8 origkey[VNetUtils::ChaCha20KeySize];
162 VNetUtils::GenerateKey(origkey);
164 memcpy(loop_client->AuthKey, origkey, VNetUtils::ChaCha20KeySize);
165 memcpy(loop_client->ClientKey, origkey, VNetUtils::ChaCha20KeySize);
166 memcpy(loop_server->AuthKey, origkey, VNetUtils::ChaCha20KeySize);
167 memcpy(loop_server->ClientKey, origkey, VNetUtils::ChaCha20KeySize);
169 loop_client->OtherSock = loop_server;
170 loop_server->OtherSock = loop_client;
172 return loop_client;
176 //==========================================================================
178 // VLoopbackDriver::CheckNewConnections
180 //==========================================================================
181 VSocket *VLoopbackDriver::CheckNewConnections (bool rconOnly) {
182 if (rconOnly) return nullptr;
183 if (!localconnectpending) return nullptr;
184 localconnectpending = false;
185 return loop_server;
189 //==========================================================================
191 // VLoopbackDriver::IntAlign
193 //==========================================================================
194 int VLoopbackDriver::IntAlign (int value) {
195 return (value+(sizeof(int)-1))&(~(sizeof(int)-1));
199 //==========================================================================
201 // VLoopbackDriver::UpdateMaster
203 //==========================================================================
204 void VLoopbackDriver::UpdateMaster () {
208 //==========================================================================
210 // VLoopbackDriver::QuitMaster
212 //==========================================================================
213 void VLoopbackDriver::QuitMaster () {
217 //==========================================================================
219 // VLoopbackDriver::QueryMaster
221 //==========================================================================
222 bool VLoopbackDriver::QueryMaster (bool) {
223 return false;
227 //==========================================================================
229 // VLoopbackDriver::EndQueryMaster
231 //==========================================================================
232 void VLoopbackDriver::EndQueryMaster () {
236 //==========================================================================
238 // VLoopbackDriver::Shutdown
240 //==========================================================================
241 void VLoopbackDriver::Shutdown () {
245 //==========================================================================
247 // VLoopbackSocket::~VLoopbackSocket
249 //==========================================================================
250 VLoopbackSocket::~VLoopbackSocket () {
251 if (OtherSock) OtherSock->OtherSock = nullptr;
252 if (this == ((VLoopbackDriver *)Driver)->loop_client) {
253 ((VLoopbackDriver *)Driver)->loop_client = nullptr;
254 } else {
255 ((VLoopbackDriver *)Driver)->loop_server = nullptr;
260 //==========================================================================
262 // VLoopbackSocket::GetMessage
264 //==========================================================================
265 int VLoopbackSocket::GetMessage (void *dest, size_t destSize) {
266 if (!LoopbackMessages.length()) return 0;
267 int res = LoopbackMessages[0].Data.length();
268 if (res > (int)destSize) return -1;
269 if (res) memcpy(dest, LoopbackMessages[0].Data.ptr(), res);
270 LoopbackMessages.RemoveIndex(0);
271 return res;
275 //==========================================================================
277 // VLoopbackSocket::SendMessage
279 // Send a packet over the net connection.
280 // returns 1 if the packet was sent properly
281 // returns -1 if the connection died
283 //==========================================================================
284 int VLoopbackSocket::SendMessage (const vuint8 *Data, vuint32 Length) {
285 if (!OtherSock) return -1;
286 VLoopbackMessage &Msg = OtherSock->LoopbackMessages.Alloc();
287 Msg.Data.setLength(Length);
288 if (Length) memcpy(Msg.Data.Ptr(), Data, Length);
289 return 1;
293 //==========================================================================
295 // VLoopbackSocket::IsLocalConnection
297 //==========================================================================
298 bool VLoopbackSocket::IsLocalConnection () const noexcept {
299 return true;