void NetInterface::startConnection(NetConnection *conn) { TNLAssert(conn->getConnectionState() == NetConnection::NotConnected, "Cannot start unless it is in the NotConnected state."); addPendingConnection(conn); conn->mConnectSendCount = 0; conn->setConnectionState(NetConnection::AwaitingChallengeResponse); sendConnectChallengeRequest(conn); }
void NetInterface::checkTimeouts() { U32 time = Platform::getVirtualMilliseconds(); if(time > mLastTimeoutCheckTime + TimeoutCheckInterval) { for(U32 i = 0; i < mPendingConnections.size();) { NetConnection *pending = mPendingConnections[i]; if(pending->getConnectionState() == NetConnection::AwaitingChallengeResponse && time > pending->mConnectLastSendTime + ChallengeRetryTime) { if(pending->mConnectSendCount > ChallengeRetryCount) { pending->onConnectTimedOut(); removePendingConnection(pending); pending->deleteObject(); continue; } else sendConnectChallengeRequest(pending); } else if(pending->getConnectionState() == NetConnection::AwaitingConnectResponse && time > pending->mConnectLastSendTime + ConnectRetryTime) { if(pending->mConnectSendCount > ConnectRetryCount) { pending->onConnectTimedOut(); removePendingConnection(pending); pending->deleteObject(); continue; } else sendConnectRequest(pending); } i++; } mLastTimeoutCheckTime = time; NetConnection *walk = NetConnection::getConnectionList(); while(walk) { NetConnection *next = walk->getNext(); if(walk->checkTimeout(time)) { // this baddie timed out walk->onTimedOut(); walk->deleteObject(); } walk = next; } } }
void NetInterface::startConnection(NetConnection *conn) { addPendingConnection(conn); conn->mConnectionSendCount = 0; conn->setConnectSequence(Platform::getVirtualMilliseconds()); conn->setConnectionState(NetConnection::AwaitingChallengeResponse); // This is a the client side of the connection, so set the connection to // server flag. We need to set this early so that if the connection times // out, its onRemove() will handle the cleanup properly. conn->setIsConnectionToServer(); // Everything set, so send off the request. sendConnectChallengeRequest(conn); }
void NetInterface::handleConnectReject(const Address &address, BitStream *stream) { Nonce nonce; Nonce serverNonce; nonce.read(stream); serverNonce.read(stream); NetConnection *conn = findPendingConnection(address); if(!conn || (conn->getConnectionState() != NetConnection::AwaitingChallengeResponse && conn->getConnectionState() != NetConnection::AwaitingConnectResponse)) return; ConnectionParameters &p = conn->getConnectionParameters(); if(p.mNonce != nonce || p.mServerNonce != serverNonce) return; NetConnection::TerminationReason reason = (NetConnection::TerminationReason) stream->readEnum(NetConnection::TerminationReasons); char reasonStr[256]; stream->readString(reasonStr); logprintf(LogConsumer::LogNetInterface, "Received Connect Reject - reason code %d (%s)", reason, reasonStr); // If the reason is a bad puzzle solution, try once more with a new nonce if(reason == NetConnection::ReasonPuzzle && !p.mPuzzleRetried) { p.mPuzzleRetried = true; conn->setConnectionState(NetConnection::AwaitingChallengeResponse); conn->mConnectSendCount = 0; p.mNonce.getRandom(); // Generate new nonce sendConnectChallengeRequest(conn); return; } conn->setConnectionState(NetConnection::ConnectRejected); conn->onConnectTerminated(reason, reasonStr); removePendingConnection(conn); }
void NetInterface::handleConnectReject(const Address &address, BitStream *stream) { Nonce nonce; Nonce serverNonce; nonce.read(stream); serverNonce.read(stream); NetConnection *conn = findPendingConnection(address); if(!conn || (conn->getConnectionState() != NetConnection::AwaitingChallengeResponse && conn->getConnectionState() != NetConnection::AwaitingConnectResponse)) return; ConnectionParameters &p = conn->getConnectionParameters(); if(p.mNonce != nonce || p.mServerNonce != serverNonce) return; char reason[256]; stream->readString(reason); TNLLogMessageV(LogNetInterface, ("Received Connect Reject - reason %s", reason)); // if the reason is a bad puzzle solution, try once more with a // new nonce. if(!strcmp(reason, "Puzzle") && !p.mPuzzleRetried) { p.mPuzzleRetried = true; conn->setConnectionState(NetConnection::AwaitingChallengeResponse); conn->mConnectSendCount = 0; p.mNonce.getRandom(); sendConnectChallengeRequest(conn); return; } conn->setConnectionState(NetConnection::ConnectRejected); conn->onConnectTerminated(NetConnection::ReasonRemoteHostRejectedConnection, reason); removePendingConnection(conn); }
void NetInterface::processConnections() { mCurrentTime = Platform::getRealMilliseconds(); mPuzzleManager.tick(mCurrentTime); // first see if there are any delayed packets that need to be sent... while(mSendPacketList && mSendPacketList->sendTime < getCurrentTime()) { DelaySendPacket *next = mSendPacketList->nextPacket; mSocket.sendto(mSendPacketList->remoteAddress, mSendPacketList->packetData, mSendPacketList->packetSize); free(mSendPacketList); mSendPacketList = next; } NetObject::collapseDirtyList(); // collapse all the mask bits... for(S32 i = 0; i < mConnectionList.size(); i++) mConnectionList[i]->checkPacketSend(false, getCurrentTime()); if(getCurrentTime() > mLastTimeoutCheckTime + TimeoutCheckInterval) { for(S32 i = 0; i < mPendingConnections.size();) { NetConnection *pending = mPendingConnections[i]; if(pending->getConnectionState() == NetConnection::AwaitingChallengeResponse && getCurrentTime() > pending->mConnectLastSendTime + ChallengeRetryTime) { if(pending->mConnectSendCount > ChallengeRetryCount) { pending->setConnectionState(NetConnection::ConnectTimedOut); pending->onConnectTerminated(NetConnection::ReasonTimedOut, "Timeout"); removePendingConnection(pending); continue; } else sendConnectChallengeRequest(pending); } else if(pending->getConnectionState() == NetConnection::AwaitingConnectResponse && getCurrentTime() > pending->mConnectLastSendTime + ConnectRetryTime) { if(pending->mConnectSendCount > ConnectRetryCount) { pending->setConnectionState(NetConnection::ConnectTimedOut); pending->onConnectTerminated(NetConnection::ReasonTimedOut, "Timeout"); removePendingConnection(pending); continue; } else { if(pending->getConnectionParameters().mIsArranged) sendArrangedConnectRequest(pending); else sendConnectRequest(pending); } } else if(pending->getConnectionState() == NetConnection::SendingPunchPackets && getCurrentTime() > pending->mConnectLastSendTime + PunchRetryTime) { if(pending->mConnectSendCount > PunchRetryCount) { pending->setConnectionState(NetConnection::ConnectTimedOut); pending->onConnectTerminated(NetConnection::ReasonTimedOut, "Timeout"); removePendingConnection(pending); continue; } else sendPunchPackets(pending); } else if(pending->getConnectionState() == NetConnection::ComputingPuzzleSolution && getCurrentTime() > pending->mConnectLastSendTime + PuzzleSolutionTimeout) { pending->setConnectionState(NetConnection::ConnectTimedOut); pending->onConnectTerminated(NetConnection::ReasonTimedOut, "Timeout"); removePendingConnection(pending); } i++; } mLastTimeoutCheckTime = getCurrentTime(); for(S32 i = 0; i < mConnectionList.size();) { if(mConnectionList[i]->checkTimeout(getCurrentTime())) { mConnectionList[i]->setConnectionState(NetConnection::TimedOut); mConnectionList[i]->onConnectionTerminated(NetConnection::ReasonTimedOut, "Timeout"); removeConnection(mConnectionList[i]); } else i++; } } // check if we're trying to solve any client connection puzzles for(S32 i = 0; i < mPendingConnections.size(); i++) { if(mPendingConnections[i]->getConnectionState() == NetConnection::ComputingPuzzleSolution) { continuePuzzleSolution(mPendingConnections[i]); break; } } }