netInterface.cpp
Engine/source/sim/netInterface.cpp
Public Defines
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
