Torque3D Documentation / _generateds / netInterface.cpp

netInterface.cpp

Engine/source/sim/netInterface.cpp

More...

Public Defines

define
F1(x, y, z) (z ^ (x & (y ^ z)))
define
F2(x, y, z) (z, x, y)
define
F3(x, y, z) (x ^ y ^ z)
define
F4(x, y, z) (y ^ (x | ~z))
define
MD5STEP(f, w, x, y, z, data, s) w = (w + f(x, y, z) + data, s) + x

Public Variables

The global net interface instance.

Public Functions

ConsoleFunctionGroupBegin(NetInterface , "Global <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> functions <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the netInterfaces." )
DefineConsoleFunction(allowConnections , void , (bool allow) , "allowConnections(bool allow)" "@brief Sets whether or not the global <a href="/coding/class/classnetinterface/">NetInterface</a> allows connections from remote <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">hosts.\n\n</a>" "@param allow Set <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> true <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> allow remote <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">connections.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Networking\n</a>" )

Detailed Description

Public Defines

F1(x, y, z) (z ^ (x & (y ^ z)))
F2(x, y, z) (z, x, y)
F3(x, y, z) (x ^ y ^ z)
F4(x, y, z) (y ^ (x | ~z))
MD5STEP(f, w, x, y, z, data, s) w = (w + f(x, y, z) + data, s) + x

Public Variables

NetInterface * GNet 

The global net interface instance.

Public Functions

ConsoleFunctionGroupBegin(NetInterface , "Global <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> functions <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the netInterfaces." )

ConsoleFunctionGroupEnd(NetInterface )

DefineConsoleFunction(allowConnections , void , (bool allow) , "allowConnections(bool allow)" "@brief Sets whether or not the global <a href="/coding/class/classnetinterface/">NetInterface</a> allows connections from remote <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">hosts.\n\n</a>" "@param allow Set <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> true <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> allow remote <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">connections.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Networking\n</a>" )

rotlFixed(U32 x, U32 y)

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "platform/platform.h"
 25#include "sim/netConnection.h"
 26#include "sim/netInterface.h"
 27#include "core/stream/bitStream.h"
 28#include "math/mRandom.h"
 29#include "core/util/journal/journal.h"
 30#include "console/engineAPI.h"
 31
 32#ifdef GGC_PLUGIN
 33#include "GGCNatTunnel.h" 
 34extern void HandleGGCPacket(NetAddress* addr, unsigned char* data, U32 dataSize);
 35#endif
 36
 37NetInterface *GNet = NULL;
 38
 39NetInterface::NetInterface()
 40{
 41   AssertFatal(GNet == NULL, "ERROR: Multiple net interfaces declared.");
 42   GNet = this;
 43
 44   mLastTimeoutCheckTime = 0;
 45   mAllowConnections = false;
 46
 47}
 48
 49void NetInterface::initRandomData()
 50{
 51   mRandomDataInitialized = true;
 52   U32 seed = Platform::getRealMilliseconds();
 53
 54   if(Journal::IsPlaying())
 55      Journal::Read(&seed);
 56   else if(Journal::IsRecording())
 57      Journal::Write(seed);
 58
 59   MRandomR250 myRandom(seed);
 60   for(U32 i = 0; i < 12; i++)
 61      mRandomHashData[i] = myRandom.randI();
 62}
 63
 64void NetInterface::addPendingConnection(NetConnection *connection)
 65{
 66   Con::printf("Adding a pending connection");
 67   mPendingConnections.push_back(connection);
 68}
 69
 70void NetInterface::removePendingConnection(NetConnection *connection)
 71{
 72   for(U32 i = 0; i < mPendingConnections.size(); i++)
 73      if(mPendingConnections[i] == connection)
 74         mPendingConnections.erase(i);
 75}
 76
 77NetConnection *NetInterface::findPendingConnection(const NetAddress *address, U32 connectSequence)
 78{
 79   for(U32 i = 0; i < mPendingConnections.size(); i++)
 80      if(Net::compareAddresses(address, mPendingConnections[i]->getNetAddress()) &&
 81            connectSequence == mPendingConnections[i]->getSequence())
 82         return mPendingConnections[i];
 83   return NULL;
 84}
 85
 86void NetInterface::processPacketReceiveEvent(NetAddress srcAddress, RawData packetData)
 87{
 88
 89   U32 dataSize = packetData.size;
 90   BitStream pStream(packetData.data, dataSize);
 91
 92   // Determine what to do with this packet:
 93
 94   if(packetData.data[0] & 0x01) // it's a protocol packet...
 95   {
 96      // if the LSB of the first byte is set, it's a game data packet
 97      // so pass it to the appropriate connection.
 98
 99      // lookup the connection in the addressTable
100      NetConnection *conn = NetConnection::lookup(&srcAddress);
101      if(conn)
102         conn->processRawPacket(&pStream);
103   }
104   else
105   {
106      // Otherwise, it's either a game info packet or a
107      // connection handshake packet.
108
109      U8 packetType;
110      pStream.read(&packetType);
111      NetAddress *addr = &srcAddress;
112
113      if(packetType <= GameHeartbeat || packetType == MasterServerExtendedListResponse)
114         handleInfoPacket(addr, packetType, &pStream);
115#ifdef GGC_PLUGIN
116      else if (packetType == GGCPacket)
117      {
118         HandleGGCPacket(addr, (U8*)packetData.data, dataSize);
119      }
120#endif
121      else
122      {
123         // check if there's a connection already:
124         switch(packetType)
125         {
126            case ConnectChallengeRequest:
127               handleConnectChallengeRequest(addr, &pStream);
128               break;
129            case ConnectRequest:
130               handleConnectRequest(addr, &pStream);
131               break;
132            case ConnectChallengeResponse:
133               handleConnectChallengeResponse(addr, &pStream);
134               break;
135            case ConnectAccept:
136               handleConnectAccept(addr, &pStream);
137               break;
138            case Disconnect:
139               handleDisconnect(addr, &pStream);
140               break;
141            case ConnectReject:
142               handleConnectReject(addr, &pStream);
143               break;
144         }
145      }
146   }
147}
148
149//-----------------------------------------------------------------------------
150//-----------------------------------------------------------------------------
151// Connection handshaking basic overview:
152// The torque engine does a two phase connect handshake to
153// prevent a spoofed source address Denial-of-Service (DOS) attack
154//
155// Basically, the initiator of a connection (client) sends a
156// Connect Challenge Request packet to the server to initiate the connection
157// The server then hashes the source address of the client request
158// with some random magic server data to come up with a 16-byte key that
159// the client can then use to gain entry to the server.
160// This way there are no partially active connection records on the
161// server at all.
162//
163// The client then sends a Connect Request packet to the server,
164// including any game specific data necessary to start a connection (a
165// server password, for instance), along with the key the server sent
166// on the Connect Challenge Response packet.
167//
168// The server, on receipt of the Connect Request, compares the
169// entry key with a computed key, makes sure it can create the requested
170// NetConnection subclass, and then passes all processing on to the connection
171// instance.
172//
173// If the subclass reads and accepts he connect request successfully, the
174// server sends a Connect Accept packet - otherwise the connection
175// is rejected with the sendConnectReject function
176//-----------------------------------------------------------------------------
177//-----------------------------------------------------------------------------
178
179
180void NetInterface::sendConnectChallengeRequest(NetConnection *conn)
181{
182   Con::printf("Sending Connect challenge Request");
183   BitStream *out = BitStream::getPacketStream();
184
185   out->write(U8(ConnectChallengeRequest));
186   out->write(conn->getSequence());
187
188   conn->mConnectSendCount++;
189   conn->mConnectLastSendTime = Platform::getVirtualMilliseconds();
190
191   BitStream::sendPacketStream(conn->getNetAddress());
192}
193
194void NetInterface::handleConnectChallengeRequest(const NetAddress *addr, BitStream *stream)
195{
196   char buf[256];
197   Net::addressToString(addr, buf);
198   Con::printf("Got Connect challenge Request from %s", buf);
199   if(!mAllowConnections)
200      return;
201
202   U32 connectSequence;
203   stream->read(&connectSequence);
204
205   if(!mRandomDataInitialized)
206      initRandomData();
207
208   U32 addressDigest[4];
209   computeNetMD5(addr, connectSequence, addressDigest);
210
211   BitStream *out = BitStream::getPacketStream();
212   out->write(U8(ConnectChallengeResponse));
213   out->write(connectSequence);
214   out->write(addressDigest[0]);
215   out->write(addressDigest[1]);
216   out->write(addressDigest[2]);
217   out->write(addressDigest[3]);
218
219   BitStream::sendPacketStream(addr);
220}
221
222//-----------------------------------------------------------------------------
223
224void NetInterface::handleConnectChallengeResponse(const NetAddress *address, BitStream *stream)
225{
226   Con::printf("Got Connect challenge Response");
227   U32 connectSequence;
228   stream->read(&connectSequence);
229
230   NetConnection *conn = findPendingConnection(address, connectSequence);
231   if(!conn || conn->getConnectionState() != NetConnection::AwaitingChallengeResponse)
232      return;
233
234   U32 addressDigest[4];
235   stream->read(&addressDigest[0]);
236   stream->read(&addressDigest[1]);
237   stream->read(&addressDigest[2]);
238   stream->read(&addressDigest[3]);
239   conn->setAddressDigest(addressDigest);
240
241   conn->setConnectionState(NetConnection::AwaitingConnectResponse);
242   conn->mConnectSendCount = 0;
243   Con::printf("Sending Connect Request");
244   sendConnectRequest(conn);
245}
246
247//-----------------------------------------------------------------------------
248
249void NetInterface::sendConnectRequest(NetConnection *conn)
250{
251   BitStream *out = BitStream::getPacketStream();
252   out->write(U8(ConnectRequest));
253   out->write(conn->getSequence());
254
255   U32 addressDigest[4];
256   conn->getAddressDigest(addressDigest);
257   out->write(addressDigest[0]);
258   out->write(addressDigest[1]);
259   out->write(addressDigest[2]);
260   out->write(addressDigest[3]);
261
262   out->writeString(conn->getClassName());
263   conn->writeConnectRequest(out);
264   conn->mConnectSendCount++;
265   conn->mConnectLastSendTime = Platform::getVirtualMilliseconds();
266
267   BitStream::sendPacketStream(conn->getNetAddress());
268}
269
270//-----------------------------------------------------------------------------
271
272void NetInterface::handleConnectRequest(const NetAddress *address, BitStream *stream)
273{
274   if(!mAllowConnections)
275      return;
276   Con::printf("Got Connect Request");
277   U32 connectSequence;
278   stream->read(&connectSequence);
279
280   // see if the connection is in the main connection table:
281
282   NetConnection *connect = NetConnection::lookup(address);
283   if(connect && connect->getSequence() == connectSequence)
284   {
285      sendConnectAccept(connect);
286      return;
287   }
288   U32 addressDigest[4];
289   U32 computedAddressDigest[4];
290
291   stream->read(&addressDigest[0]);
292   stream->read(&addressDigest[1]);
293   stream->read(&addressDigest[2]);
294   stream->read(&addressDigest[3]);
295
296   computeNetMD5(address, connectSequence, computedAddressDigest);
297   if(addressDigest[0] != computedAddressDigest[0] ||
298      addressDigest[1] != computedAddressDigest[1] ||
299      addressDigest[2] != computedAddressDigest[2] ||
300      addressDigest[3] != computedAddressDigest[3])
301      return; // bogus connection attempt
302
303   if(connect)
304   {
305      if(connect->getSequence() > connectSequence)
306         return; // the existing connection should be kept - the incoming request is stale.
307      else
308         connect->deleteObject(); // disconnect this one, and allow the new one to be created.
309   }
310
311   char connectionClass[255];
312   stream->readString(connectionClass);
313
314   ConsoleObject *co = ConsoleObject::create(connectionClass);
315   NetConnection *conn = dynamic_cast<NetConnection *>(co);
316   if(!conn || !conn->canRemoteCreate())
317   {
318      delete co;
319      return;
320   }
321   conn->registerObject();
322   conn->setNetAddress(address);
323   conn->setNetworkConnection(true);
324   conn->setSequence(connectSequence);
325
326   const char *errorString = NULL;
327   if(!conn->readConnectRequest(stream, &errorString))
328   {
329      sendConnectReject(conn, errorString);
330      conn->deleteObject();
331      return;
332   }
333   conn->setNetworkConnection(true);
334   conn->onConnectionEstablished(false);
335   conn->setEstablished();
336   conn->setConnectSequence(connectSequence);
337   sendConnectAccept(conn);
338}
339
340//-----------------------------------------------------------------------------
341
342void NetInterface::sendConnectAccept(NetConnection *conn)
343{
344   BitStream *out = BitStream::getPacketStream();
345   out->write(U8(ConnectAccept));
346   out->write(conn->getSequence());
347   conn->writeConnectAccept(out);
348   BitStream::sendPacketStream(conn->getNetAddress());
349}
350
351void NetInterface::handleConnectAccept(const NetAddress *address, BitStream *stream)
352{
353   U32 connectSequence;
354   stream->read(&connectSequence);
355   NetConnection *conn = findPendingConnection(address, connectSequence);
356   if(!conn || conn->getConnectionState() != NetConnection::AwaitingConnectResponse)
357      return;
358   const char *errorString = NULL;
359   if(!conn->readConnectAccept(stream, &errorString))
360   {
361      conn->handleStartupError(errorString);
362      removePendingConnection(conn);
363      conn->deleteObject();
364      return;
365   }
366
367   removePendingConnection(conn); // remove from the pending connection list
368   conn->setNetworkConnection(true);
369   conn->onConnectionEstablished(true); // notify the connection that it has been established
370   conn->setEstablished(); // installs the connection in the connection table, and causes pings/timeouts to happen
371   conn->setConnectSequence(connectSequence);
372}
373
374void NetInterface::sendConnectReject(NetConnection *conn, const char *reason)
375{
376   if(!reason)
377      return; // if the stream is NULL, we reject silently
378
379   BitStream *out = BitStream::getPacketStream();
380   out->write(U8(ConnectReject));
381   out->write(conn->getSequence());
382   out->writeString(reason);
383   BitStream::sendPacketStream(conn->getNetAddress());
384}
385
386void NetInterface::handleConnectReject(const NetAddress *address, BitStream *stream)
387{
388   U32 connectSequence;
389   stream->read(&connectSequence);
390   NetConnection *conn = findPendingConnection(address, connectSequence);
391   if(!conn || (conn->getConnectionState() != NetConnection::AwaitingChallengeResponse &&
392                conn->getConnectionState() != NetConnection::AwaitingConnectResponse))
393      return;
394   removePendingConnection(conn);
395   char reason[256];
396   stream->readString(reason);
397   conn->onConnectionRejected(reason);
398   conn->deleteObject();
399}
400
401void NetInterface::handleDisconnect(const NetAddress *address, BitStream *stream)
402{
403   NetConnection *conn = NetConnection::lookup(address);
404   if(!conn)
405      return;
406
407   U32 connectSequence;
408   char reason[256];
409
410   stream->read(&connectSequence);
411   stream->readString(reason);
412
413   if(conn->getSequence() != connectSequence)
414      return;
415
416   conn->onDisconnect(reason);
417   conn->deleteObject();
418}
419
420void NetInterface::handleInfoPacket(const NetAddress *address, U8 packetType, BitStream *stream)
421{
422}
423
424void NetInterface::processClient()
425{
426   NetObject::collapseDirtyList(); // collapse all the mask bits...
427   for(NetConnection *walk = NetConnection::getConnectionList();
428      walk; walk = walk->getNext())
429   {
430      if(walk->isConnectionToServer() && (walk->isLocalConnection() || walk->isNetworkConnection()))
431         walk->checkPacketSend(false);
432   }
433}
434
435void NetInterface::processServer()
436{
437   NetObject::collapseDirtyList(); // collapse all the mask bits...
438   for(NetConnection *walk = NetConnection::getConnectionList();
439      walk; walk = walk->getNext())
440   {
441      if(!walk->isConnectionToServer() && (walk->isLocalConnection() || walk->isNetworkConnection()))
442         walk->checkPacketSend(false);
443   }
444}
445
446void NetInterface::startConnection(NetConnection *conn)
447{
448   addPendingConnection(conn);
449   conn->mConnectionSendCount = 0;
450   conn->setConnectSequence(Platform::getVirtualMilliseconds());
451   conn->setConnectionState(NetConnection::AwaitingChallengeResponse);
452
453   // This is a the client side of the connection, so set the connection to
454   // server flag. We need to set this early so that if the connection times
455   // out, its onRemove() will handle the cleanup properly.
456   conn->setIsConnectionToServer();
457
458   // Everything set, so send off the request.
459   sendConnectChallengeRequest(conn);
460}
461
462void NetInterface::sendDisconnectPacket(NetConnection *conn, const char *reason)
463{
464   Con::printf("Issuing Disconnect packet.");
465
466   // send a disconnect packet...
467   U32 connectSequence = conn->getSequence();
468
469   BitStream *out = BitStream::getPacketStream();
470   out->write(U8(Disconnect));
471   out->write(connectSequence);
472   out->writeString(reason);
473
474   BitStream::sendPacketStream(conn->getNetAddress());
475}
476
477void NetInterface::checkTimeouts()
478{
479   U32 time = Platform::getVirtualMilliseconds();
480   if(time > mLastTimeoutCheckTime + TimeoutCheckInterval)
481   {
482      for(U32 i = 0; i < mPendingConnections.size();)
483      {
484         NetConnection *pending = mPendingConnections[i];
485
486         if(pending->getConnectionState() == NetConnection::AwaitingChallengeResponse &&
487            time > pending->mConnectLastSendTime + ChallengeRetryTime)
488         {
489            if(pending->mConnectSendCount > ChallengeRetryCount)
490            {
491               pending->onConnectTimedOut();
492               removePendingConnection(pending);
493               pending->deleteObject();
494               continue;
495            }
496            else
497               sendConnectChallengeRequest(pending);
498         }
499         else if(pending->getConnectionState() == NetConnection::AwaitingConnectResponse &&
500            time > pending->mConnectLastSendTime + ConnectRetryTime)
501         {
502            if(pending->mConnectSendCount > ConnectRetryCount)
503            {
504               pending->onConnectTimedOut();
505               removePendingConnection(pending);
506               pending->deleteObject();
507               continue;
508            }
509            else
510               sendConnectRequest(pending);
511         }
512         i++;
513      }
514      mLastTimeoutCheckTime = time;
515      NetConnection *walk = NetConnection::getConnectionList();
516
517      while(walk)
518      {
519         NetConnection *next = walk->getNext();
520         if(walk->checkTimeout(time))
521         {
522            // this baddie timed out
523            walk->onTimedOut();
524            walk->deleteObject();
525         }
526         walk = next;
527      }
528   }
529}
530
531#define F1(x, y, z) (z ^ (x & (y ^ z)))
532#define F2(x, y, z) F1(z, x, y)
533#define F3(x, y, z) (x ^ y ^ z)
534#define F4(x, y, z) (y ^ (x | ~z))
535
536inline U32 rotlFixed(U32 x, U32 y)
537{
538   return (x >> y) | (x << (32 - y));
539}
540
541#define MD5STEP(f, w, x, y, z, data, s) w = rotlFixed(w + f(x, y, z) + data, s) + x
542
543void NetInterface::computeNetMD5(const NetAddress *address, U32 connectSequence, U32 digest[4])
544{
545   digest[0] = 0x67452301L;
546   digest[1] = 0xefcdab89L;
547   digest[2] = 0x98badcfeL;
548   digest[3] = 0x10325476L;
549
550
551   U32 a, b, c, d;
552
553   a=digest[0];
554   b=digest[1];
555   c=digest[2];
556   d=digest[3];
557
558   U32 in[16];
559   in[0] = address->type;
560   in[1] = address->getHash();
561   in[2] = address->port;
562   in[3] = connectSequence;
563   for(U32 i = 0; i < 12; i++)
564      in[i + 4] = mRandomHashData[i];
565
566   MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
567   MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
568   MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
569   MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
570   MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
571   MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
572   MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
573   MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
574   MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
575   MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
576   MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
577   MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
578   MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
579   MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
580   MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
581   MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
582
583   MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
584   MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
585   MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
586   MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
587   MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
588   MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
589   MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
590   MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
591   MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
592   MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
593   MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
594   MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
595   MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
596   MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
597   MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
598   MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
599
600   MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
601   MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
602   MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
603   MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
604   MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
605   MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
606   MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
607   MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
608   MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
609   MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
610   MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
611   MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
612   MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
613   MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
614   MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
615   MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
616
617   MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
618   MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
619   MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
620   MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
621   MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
622   MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
623   MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
624   MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
625   MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
626   MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
627   MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
628   MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
629   MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
630   MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
631   MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
632   MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
633
634   digest[0]+=a;
635   digest[1]+=<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a>;
636   digest[2]+=c;
637   digest[3]+=d;
638}
639
640ConsoleFunctionGroupBegin(NetInterface, "Global control functions for the netInterfaces.");
641
642DefineConsoleFunction( allowConnections, void, ( bool allow ), , "allowConnections(bool allow)"
643   "@brief Sets whether or not the global NetInterface allows connections from remote hosts.\n\n"
644
645   "@param allow Set to true to allow remote connections.\n"
646
647   "@ingroup Networking\n")
648{
649   GNet->setAllowsConnections(allow);
650}
651
652ConsoleFunctionGroupEnd(NetInterface);
653
654