bool Reliable::Init( UdpCommunicator* communicator, UdpConnection* connection ) { K_ASSERT( communicator != 0 ); K_ASSERT( connection != 0 ); m_communicator = communicator; m_connection = connection; m_sendList.clear(); m_recvList.clear(); m_sendSeq = 0; m_recvCumAck = 0; // suppose seq starts from 1 always m_sendCumAck = 0; // suppose seq starts from 1 always m_outstandingSegs = 0; m_zeroSendCount = 0; m_averageRtt = START_RTT; m_cumAckInterval = CUMULATIVE_ACK_INTERVAL; m_tickCumulativeAck.Reset(); m_tickResend.Reset(); return true; }
void Reliable::processZeroSend() { if ( m_zeroSendCount == 0 && m_outstandingSegs >= MAX_OUTSTANDING_SEGMENTS ) { return; } SendBlockList::iterator i( m_sendList.begin() ); for ( ; i != m_sendList.end(); ++i ) { UdpSendBlock* sb = *i; K_ASSERT( sb != 0 ); if ( sb->rxCount == 0 ) { if ( resend( sb ) ) { --m_zeroSendCount; K_ASSERT( m_zeroSendCount >= 0 ); } else { return; // we still cannot send 'cause there are too many outstanding segments } } } }
void NetClient::onGroupPrepare( MessagePtr m ) { K_ASSERT( m_groupId == 0 ); K_ASSERT( m_selfTag == 0 ); m_groupId = 0; m_selfTag = 0; NmGroupPrepare* gp = static_cast<NmGroupPrepare*>( m.Get() ); TcpConnection* c = m_tcp.FindById( gp->remote ); if ( c == 0 ) { LOG( FT_WARN, _T("NetClient::onGroupPrepare> Connection %d not found"), gp->remote ); return; } m_udp.Fini(); m_groupId = gp->groupId; m_selfTag = gp->connectionId; // init udp with c as a relay connection // use same ip:port as TCP connection bool rc = m_udp.Init( this, &m_ios, c->GetSocket()->GetAddress(), m_selfTag, gp->sl, gp->challenge, c ); if ( !rc ) { LOG( FT_WARN, _T("NetClient::onGroupPrepare> Failed to init udp") ); return; } NmGroupPrepared* p = new NmGroupPrepared; p->remote = gp->remote; p->groupId = gp->groupId; p->connectionId = gp->connectionId; p->in = c->GetSocket()->GetAddress(); m_tcp.Send( m->remote, MessagePtr( p ) ); LOG( FT_DEBUG, _T("NetClient::onGroupPrepare> Prepared group %d connection %d"), gp->groupId, gp->connectionId ); }
void Reliable::OnAck( const UdpHeader& header ) { K_ASSERT( header.ack > 0 ); if ( m_recvCumAck >= header.ack ) { LOG( FT_DEBUG, _T("Reliable::OnAck> self[%d] remote[%d] duplicate cum ack %d"), m_connection->GetSelfTag(), m_connection->GetRemoteTag(), header.ack ); return; } m_recvCumAck = header.ack; LOG( FT_DEBUG, _T("Reliable::OnAck> ack %d"), header.ack ); SendBlockList::iterator i( m_sendList.begin() ); int totalRtt = 0; int totalCount = 0; for ( ; i != m_sendList.end(); ) { UdpSendBlock* sb = *i; K_ASSERT( sb != 0 ); if ( sb->header.seq > header.ack ) { break; } totalRtt += sb->rxmt.Elapsed(); ++totalCount; i = m_sendList.erase( i++ ); --m_outstandingSegs; K_ASSERT( m_outstandingSegs >= 0 ); delete sb; } if ( totalCount > 0 ) { // moving average. slowly converges. m_averageRtt = ( totalRtt / totalCount + m_averageRtt ) / 2; } }
bool Reliable::Send( void* data, uint len, bool ordered ) { K_ASSERT( data != 0 ); K_ASSERT( len > 0 ); processZeroSend(); // To send previously asked ones first. UdpSendBlock* sb = allocSendBlock(); sb->header.Set( UdpHeader::RLE ); sb->header.Set( UdpHeader::ACK ); if ( ordered ) { sb->header.Set( UdpHeader::ORD ); } sb->header.seq = ++m_sendSeq; sb->header.ack = m_sendCumAck; sb->header.srcId = m_connection->GetSelfTag(); sb->header.dstId = m_connection->GetRemoteTag(); sb->header.length = sizeof( UdpHeader ); sb->header.bodyLen = len; sb->data = (byte*)allocData( sizeof( UdpHeader ) + len ); ::memcpy( sb->data, (void*)&sb->header, sizeof( UdpHeader ) ); ::memcpy( (void*)(sb->data + sb->header.length), data, len ); sb->len = sizeof( UdpHeader ) + len; if ( m_outstandingSegs < MAX_OUTSTANDING_SEGMENTS ) { m_connection->SendRaw( sb->data, sb->len ); ++sb->rxCount; ++m_outstandingSegs; m_tickCumulativeAck.Reset(); } else { ++m_zeroSendCount; } m_sendList.push_back( sb ); return true; }
bool Acceptor::Init( TcpCommunicator* communicator, Socket* socket, SecurityLevel sl ) { K_ASSERT( communicator != 0 ); K_ASSERT( socket != 0 ); m_communicator = communicator; m_socket = socket; m_sl = sl; Start(); return true; }
void NetClient::onGroupJoin( MessagePtr m ) { K_ASSERT( m_groupId != 0 ); NmGroupJoin* join = static_cast<NmGroupJoin*>( m.Get() ); K_ASSERT( join->groupId == m_groupId ); LOG( FT_DEBUG, _T("NetClient::onGroupJoin> Group %d Members %d"), join->groupId, join->members.size() ); NmGroupJoin::MemberList::iterator i( join->members.begin() ); NmGroupJoin::MemberList::iterator iEnd( join->members.end() ); for ( ; i != iEnd; ++i ) { NetGroupMember& member = *i; if ( member.connectionId != m_selfTag ) { UdpConnection* c = m_udp.FindByTag( member.connectionId ); if ( c != 0 ) { continue; } // tag is used for communication (void)m_udp.Connect( member.connectionId, member.in, member.ex ); NmGroupJoined* joined = new NmGroupJoined; joined->groupId = join->groupId; joined->connectionId = member.connectionId; joined->extra = member.extra; m_listener->Notify( MessagePtr( joined ) ); LOG( FT_DEBUG, _T("NetClient::onGroupJoin> Self %d Tag %d joined In %s Ex %s"), m_selfTag, member.connectionId, member.in.ToString().c_str(), member.ex.ToString().c_str() ); } } }
void Reliable::runRecvBlockList() { RecvBlockList::iterator i( m_recvList.begin() ); for ( ; i != m_recvList.end(); ) { UdpRecvBlock* p = *i; K_ASSERT( p->seq > m_sendCumAck ); if ( p->seq == ( m_sendCumAck + 1) ) // in order { if ( p->ordered ) // ordered QoS { K_ASSERT( p->data != 0 ); K_ASSERT( p->len > 0 ); // deliver and free LOG( FT_DEBUG, _T("Reliable::runRecvBlockList> self[%d] remote[%d] seq %d made available in order"), m_connection->GetSelfTag(), m_connection->GetRemoteTag(), p->seq ); m_communicator->OnRecv( m_connection->GetRemoteTag(), p->data, p->len ); freeData( p->data, p->len ); } ++m_sendCumAck; K_ASSERT( p->seq == m_sendCumAck ); i = m_recvList.erase( i++ ); freeRecvBlock( p ); } else { LOG( FT_DEBUG, _T("Reliable>runRecvBlockList> Not in order %d, Cum %d, waiting..."), p->seq, m_sendCumAck ); return; } } }
void NetClient::Send( MessagePtr m ) { K_ASSERT( m.Get() != 0 ); m_sendQ.Put( m ); }
void Reliable::processResend() { uint rtt = m_averageRtt; int resendCount = 0; if ( m_tickResend.Elapsed() > RESEND_CHECK_INTERVAL ) { SendBlockList::iterator i( m_sendList.begin() ); SendBlockList::iterator iEnd( m_sendList.end() ); for ( ; i != iEnd; ++i ) { UdpSendBlock* sb = *i; K_ASSERT( sb != 0 ); if ( sb->rxmt.Elapsed() > rtt + rtt * sb->rxCount ) { resend( sb, true ); ++resendCount; } } m_tickResend.Reset(); } }
void Reliable::freeSendBlock( UdpSendBlock* p ) { K_ASSERT( p != 0 ); delete p; }
void NetServer::onLeaveUdpGroup( const NetGroupOp& op ) { NetGroupMap::iterator i = m_groups.find( op.groupId ); if ( i == m_groups.end() ) { LOG( FT_WARN, _T("NetServer::onLeaveUdpGroup> %d not found"), op.groupId ); return; } TcpConnection* c = m_tcp.FindById( op.connectionId ); if ( c != 0 ) { c->SetGroup( 0 ); } NetGroup* group = i->second; K_ASSERT( group != 0 ); group->Leave( op.connectionId ); LOG( FT_DEBUG, _T("NetServer::onLeaveUdpGroup> %d left from %d"), op.connectionId, group->GetId() ); }
void NetServer::onStateMessage( MessagePtr m ) { K_ASSERT( m.Get() != 0 ); NetStateMessage* nsm = static_cast<NetStateMessage*>( m.Get() ); switch ( nsm->state ) { case NetStateMessage::TCP_CLOSED: { NetGroupMap::iterator i = m_groups.find( nsm->groupId ); if ( i != m_groups.end() ) { NetGroup* group = i->second; if ( group != 0 ) { group->Leave( nsm->connectionId ); } } } break; } m_listener->Notify( m ); }
ActionState* ActionState::GetState( int id ) { if ( id == m_id ) { return this; } if ( !HasState( id ) ) { return (ActionState*)0; } StateList::iterator i( m_childs.begin() ); StateList::iterator iEnd( m_childs.end() ); for ( ; i != iEnd; ++i ) { ActionState* child = *i; K_ASSERT( child != 0 ); if ( child->HasState( id ) ) { return child->GetState( id ); } } return (ActionState*)0; }
void NetServer::Send( MessagePtr m ) { K_ASSERT( m.Get() != 0 ); m_sendQ.Put( m ); }
void Reliable::freeRecvBlock( UdpRecvBlock* p ) { K_ASSERT( p != 0 ); delete p; }
int Acceptor::Run() { while ( IsRunning() ) { Socket* socket = m_socket->Accept(); K_ASSERT( socket != 0 ); if ( !IsRunning() ) // check running state again { break; } NetStateMessage* m = new NetStateMessage; m->state = NetStateMessage::TCP_ACCEPTED; m->addr = socket->GetPeerAddress(); m->socket = socket; m->sl = m_sl; m_communicator->Notify( MessagePtr( m ) ); LOG( FT_DEBUG, _T("Accepted new connection %d from %s"), socket->GetSystemSocket(), m->addr.ToString().c_str() ); } return 0; }
bool TextureManager::LoadTexture(const KFbxFileTexture * pTexture, unsigned int * pTextureObject) { TextureMapType::RecordType * lTextureRecord = mTextureMap.Find(pTexture); if (lTextureRecord) { if (pTextureObject) *pTextureObject = lTextureRecord->GetValue(); return true; } const KString lFileName = pTexture->GetFileName(); unsigned int lTextureObject = 0; bool lStatus = LoadTextureFromFile(lFileName, lTextureObject); if (!lStatus) { const KString lRelativeFileName = mWorkingDir + "/" + pTexture->GetFileName(); lStatus = LoadTextureFromFile(lRelativeFileName, lTextureObject); } if (lStatus) { K_ASSERT(glIsTexture(lTextureObject)); mTextureMap.Insert(pTexture, lTextureObject); if (pTextureObject) *pTextureObject = lTextureObject; return true; } return false; }
void NetClient::Notify( MessagePtr m ) { K_ASSERT( m.Get() != 0 ); m_recvQ.Put( m ); }
bool NetServer::Init( MessageListener* listener ) { K_ASSERT( listener != 0 ); Socket::Startup(); m_listener = listener; bool rc = m_ios.Init(); if ( !rc ) { LOG( FT_ERROR, _T("NetServer::Init> IoService init failed") ); return false; } rc = m_tcp.Init( this, &m_ios ); if ( !rc ) { LOG( FT_ERROR, _T("NetServer::Init> TcpCommunicator init failed") ); return false; } MessageFactory::Instance()->Register( new NmGroupPrepared ); MessageFactory::Instance()->Register( new NmGroupRelay ); Start(); return true; }
bool AsyncPool::Init( Node* node, bool luaMode ) { K_ASSERT( node != 0 ); m_node = node; m_luaMode = luaMode; return true; }
void Reliable::freeSendBlocks() { SendBlockList::iterator i( m_sendList.begin() ); SendBlockList::iterator iEnd( m_sendList.end() ); for ( ; i != iEnd; ++i ) { UdpSendBlock* sb = *i; K_ASSERT( sb->data != 0 ); K_ASSERT( sb->len > 0 ); freeData( sb->data, sb->len ); freeSendBlock( sb ); } m_sendList.clear(); }
void ActionState::attach( ActionState* state ) { K_ASSERT( state != 0 ); if ( HasState( state->GetId() ) ) { return; } m_childs.push_back( state ); }
bool ActionState::getChildPathTo( int target, Path& path ) { StateList::iterator i( m_childs.begin() ); StateList::iterator iEnd( m_childs.end() ); for ( ; i != iEnd; ++i ) { ActionState* child = *i; K_ASSERT( child != 0 ); if ( child->HasState( target ) ) { return child->GetTransitionPathTo( target, path ); } } K_ASSERT( !_T("Should not reach here") ); return false; // No child is in the path }
/** * Get current count. */ u32 timer_get_count(int tmr_id) { switch (tmr_id) { case TIMER1_ID: return timer1_count; case TIMER2_ID: return timer2_count; case TIMER3_ID: return timer3_count; default: K_ASSERT(0); } }
u32 timer_get_tick(int tmr_id) { switch (tmr_id) { case TIMER1_ID: return readl(TIMER1_STATUS_REG); case TIMER2_ID: return readl(TIMER2_STATUS_REG); case TIMER3_ID: return readl(TIMER3_STATUS_REG); default: K_ASSERT(0); } }
void Reliable::OnEak( const UdpHeader& header, void* data, uint len ) { // only 1 EAK under current protocol K_ASSERT( data != 0 ); K_ASSERT( len > 0 ); byte* p = (byte*)data; byte* head = (byte*)(p + header.length); byte eakCount = *head; int* eakHead = (int*)((byte*)( head + 1 )); for ( byte i=0; i<eakCount; ++i ) { int eak = eakHead[i]; runEak( eak ); } }
void Reliable::insertRecvBlock( UdpRecvBlock* rv ) { K_ASSERT( rv != 0 ); K_ASSERT( !isDuplicateRecv( rv->seq ) ); RecvBlockList::iterator i( m_recvList.begin() ); RecvBlockList::iterator iEnd( m_recvList.end() ); for ( ; i != iEnd; ++i ) { UdpRecvBlock* rb = *i; if ( rb->seq > rv->seq ) { m_recvList.insert( i, rv ); return; } } m_recvList.push_back( rv ); }
void TransDispatcher::Subscribe( ushort type, ActionPtr action ) { K_ASSERT( type > 0 ); K_ASSERT( action.Get() != 0 ); ActionMap::iterator i( m_actions.find( type ) ); if ( i == m_actions.end() ) { ActionList lst; lst.push_back( action ); m_actions.insert( ActionMap::value_type( type, lst ) ); } else { ActionList& lst = i->second; lst.push_back( action ); } }
/** * Reset the count. */ void timer_reset_count(int tmr_id) { switch (tmr_id) { case TIMER1_ID: timer1_count = 0; break; case TIMER2_ID: timer2_count = 0; break; case TIMER3_ID: timer3_count = 0; break; default: K_ASSERT(0); } }