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