void NetInterface::continuePuzzleSolution(NetConnection *conn) { ConnectionParameters &theParams = conn->getConnectionParameters(); bool solved = ClientPuzzleManager::solvePuzzle(&theParams.mPuzzleSolution, theParams.mNonce, theParams.mServerNonce, theParams.mPuzzleDifficulty, theParams.mClientIdentity); if(solved) { logprintf("Client puzzle solved in %d ms.", Platform::getRealMilliseconds() - conn->mConnectLastSendTime); conn->setConnectionState(NetConnection::AwaitingConnectResponse); sendConnectRequest(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::handleConnectChallengeResponse(const NetAddress *address, BitStream *stream) { Con::printf("Got Connect challenge Response"); U32 connectSequence; stream->read(&connectSequence); NetConnection *conn = findPendingConnection(address, connectSequence); if(!conn || conn->getConnectionState() != NetConnection::AwaitingChallengeResponse) return; U32 addressDigest[4]; stream->read(&addressDigest[0]); stream->read(&addressDigest[1]); stream->read(&addressDigest[2]); stream->read(&addressDigest[3]); conn->setAddressDigest(addressDigest); conn->setConnectionState(NetConnection::AwaitingConnectResponse); conn->mConnectSendCount = 0; Con::printf("Sending Connect Request"); sendConnectRequest(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; } } }
bool EClientSocket::eConnectImpl(int clientId, bool extraAuth, ConnState* stateOutPt) { // resolve host struct hostent* hostEnt = gethostbyname( host().c_str()); if ( !hostEnt) { getWrapper()->error( NO_VALID_ID, CONNECT_FAIL.code(), CONNECT_FAIL.msg()); return false; } // create socket m_fd = socket(AF_INET, SOCK_STREAM, 0); // cannot create socket if( m_fd < 0) { getWrapper()->error( NO_VALID_ID, FAIL_CREATE_SOCK.code(), FAIL_CREATE_SOCK.msg()); return false; } // starting to connect to server struct sockaddr_in sa; memset( &sa, 0, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_port = htons( port()); sa.sin_addr.s_addr = ((in_addr*)hostEnt->h_addr)->s_addr; // try to connect if( (connect( m_fd, (struct sockaddr *) &sa, sizeof( sa))) < 0) { // error connecting SocketClose( m_fd); m_fd = -1; getWrapper()->error( NO_VALID_ID, CONNECT_FAIL.code(), CONNECT_FAIL.msg()); return false; } getTransport()->fd(m_fd); // set client id setClientId( clientId); setExtraAuth( extraAuth); int res = sendConnectRequest(); if (res < 0 && !handleSocketError()) return false; if( !isConnected()) { if( connState() != CS_DISCONNECTED) { assert( connState() == CS_REDIRECT); if( stateOutPt) { *stateOutPt = connState(); } eDisconnect(); } return false; } // set socket to non-blocking state if ( !SetSocketNonBlocking(m_fd)) { // error setting socket to non-blocking eDisconnect(); getWrapper()->error( NO_VALID_ID, CONNECT_FAIL.code(), CONNECT_FAIL.msg()); return false; } assert( connState() == CS_CONNECTED); if( stateOutPt) { *stateOutPt = connState(); } if (!m_asyncEConnect) { EReader reader(this, m_pSignal); while (m_pSignal && !m_serverVersion && isSocketOK()) { reader.checkClient(); m_pSignal->waitForSignal(); reader.processMsgs(); } } // successfully connected return isSocketOK(); }