void C4Network2Players::HandlePacket(char cStatus, const C4PacketBase *pPacket, C4Network2IOConnection *pConn)
{
	if (!pConn) return;

	// find associated client
	C4Network2Client *pClient = ::Network.Clients.GetClient(pConn);
	if (!pClient) pClient = ::Network.Clients.GetClientByID(pConn->getClientID());

#define GETPKT(type, name) \
    assert(pPacket); const type &name = \
     static_cast<const type &>(*pPacket);

	// player join request?
	if (cStatus == PID_PlayerInfoUpdReq)
	{
		GETPKT(C4PacketPlayerInfoUpdRequest, pkPlrInfo);
		// this packet is sent to the host only, and thus cannot have been sent from the host
		if (!::Network.isHost()) return;
		// handle this packet
		HandlePlayerInfoUpdRequest(&pkPlrInfo.Info, false);
	}
	else if (cStatus == PID_LeagueRoundResults)
	{
		GETPKT(C4PacketLeagueRoundResults, pkLeagueInfo);
		// accepted from the host only
		if (!pClient || !pClient->isHost()) return;
		// process
		Game.RoundResults.EvaluateLeague(pkLeagueInfo.sResultsString.getData(), pkLeagueInfo.fSuccess, pkLeagueInfo.Players);
	}

#undef GETPKT
}
示例#2
0
void C4Network2ClientList::HandlePacket(char cStatus, const C4PacketBase *pBasePkt, C4Network2IOConnection *pConn)
{
	// find associated client
	C4Network2Client *pClient = GetClient(pConn);
	if (!pClient) return;

#define GETPKT(type, name) \
    assert(pBasePkt); const type &name = \
     static_cast<const type &>(*pBasePkt);

	switch (cStatus)
	{

	case PID_Addr: // address propagation
	{
		GETPKT(C4PacketAddr, rPkt)
		// find client
		pClient = GetClientByID(rPkt.getClientID());
		if (pClient)
		{
			C4Network2Address addr = rPkt.getAddr();
			// IP zero? Set to IP from where the packet came
			if (addr.isIPNull())
			{
				addr.SetIP(pConn->getPeerAddr());
			}
			// add (no announce)
			if (pClient->AddAddr(addr, true))
				// new address? Try to connect
				pClient->DoConnectAttempt(pIO);
		}
	}
	break;

	case PID_TCPSimOpen:
	{
		GETPKT(C4PacketTCPSimOpen, rPkt)
		pClient = GetClientByID(rPkt.getClientID());
		if (pClient)
		{
			C4Network2Address addr = rPkt.getAddr();
			pClient->DoTCPSimultaneousOpen(pIO, addr);
		}
	}
	break;

	}

#undef GETPKT
}
void C4Network2ResList::HandlePacket(char cStatus, const C4PacketBase *pPacket, C4Network2IOConnection *pConn)
{
	// security
	if (!pConn) return;

#define GETPKT(type, name) \
    assert(pPacket); const type &name = \
     static_cast<const type &>(*pPacket);

	switch (cStatus)
	{

	case PID_NetResDis: // resource discover
	{
		if (!pConn->isOpen()) break;
		GETPKT(C4PacketResDiscover, Pkt);
		// search matching resources
		CStdShareLock ResListLock(&ResListCSec);
		for (C4Network2Res *pRes = pFirst; pRes; pRes = pRes->pNext)
			if (Pkt.isIDPresent(pRes->getResID()))
				// must be binary compatible
				if (pRes->IsBinaryCompatible())
					pRes->OnDiscover(pConn);
	}
	break;

	case PID_NetResStat: // resource status
	{
		if (!pConn->isOpen()) break;
		GETPKT(C4PacketResStatus, Pkt);
		// matching resource?
		CStdShareLock ResListLock(&ResListCSec);
		C4Network2Res *pRes = getRes(Pkt.getResID());
		// present / being loaded? call handler
		if (pRes)
			pRes->OnStatus(Pkt.getChunks(), pConn);
	}
	break;

	case PID_NetResDerive: // resource derive
	{
		GETPKT(C4Network2ResCore, Core);
		if (Core.getDerID() < 0) break;
		// Check if there is a anonymous derived resource with matching parent.
		CStdShareLock ResListLock(&ResListCSec);
		for (C4Network2Res *pRes = pFirst; pRes; pRes = pRes->pNext)
			if (pRes->isAnonymous() && pRes->getCore().getDerID() == Core.getDerID())
				pRes->FinishDerive(Core);
	}
	break;

	case PID_NetResReq: // resource request
	{
		GETPKT(C4PacketResRequest, Pkt);
		// find resource
		CStdShareLock ResListLock(&ResListCSec);
		C4Network2Res *pRes = getRes(Pkt.getReqID());
		// send requested chunk
		if (pRes && pRes->IsBinaryCompatible()) pRes->SendChunk(Pkt.getReqChunk(), pConn->getClientID());
	}
	break;

	case PID_NetResData: // a chunk of data is coming in
	{
		GETPKT(C4Network2ResChunk, Chunk);
		// find resource
		CStdShareLock ResListLock(&ResListCSec);
		C4Network2Res *pRes = getRes(Chunk.getResID());
		// send requested chunk
		if (pRes) pRes->OnChunk(Chunk);
	}
	break;
	}
#undef GETPKT
}
示例#4
0
void C4Network2IO::HandlePacket(char cStatus, const C4PacketBase *pPacket, C4Network2IOConnection *pConn)
{
    // security
    if (!pConn) return;

#define GETPKT(type, name) \
    assert(pPacket); const type &name = \
     static_cast<const type &>(*pPacket);

    switch (cStatus)
    {

    case PID_Conn: // connection request
    {
        if (!pConn->isOpen()) break;
        // get packet
        GETPKT(C4PacketConn, rPkt)
        // set connection ID
        pConn->SetRemoteID(rPkt.getConnID());
        // check auto-accept
        if (doAutoAccept(rPkt.getCCore(), *pConn))
        {
            // send answer back
            C4PacketConnRe pcr(true, false, "auto accept");
            if (!pConn->Send(MkC4NetIOPacket(PID_ConnRe, pcr)))
                pConn->Close();
            // accept
            pConn->SetStatus(CS_HalfAccepted);
            pConn->SetCCore(rPkt.getCCore());
            pConn->SetAutoAccepted();
        }
        // note that this packet will get processed by C4Network2, too (main thread)
    }
    break;

    case PID_ConnRe: // connection request reply
    {
        if (!pConn->isOpen()) break;
        // conn not sent? That's fishy.
        // FIXME: Note this happens if the peer has exclusive connection mode on.
        if (!pConn->isConnSent())
        {
            pConn->Close();
            break;
        }
        // get packet
        GETPKT(C4PacketConnRe, rPkt)
        // auto accept connection
        if (rPkt.isOK())
        {
            if (pConn->isHalfAccepted() && pConn->isAutoAccepted())
                pConn->SetAccepted();
        }
    }
    break;

    case PID_Ping:
    {
        if (!pConn->isOpen()) break;
        GETPKT(C4PacketPing, rPkt)
        // pong
        C4PacketPing PktPong = rPkt;
        pConn->Send(MkC4NetIOPacket(PID_Pong, PktPong));
        // remove received packets from log
        pConn->ClearPacketLog(rPkt.getPacketCounter());
    }
    break;

    case PID_Pong:
    {
        if (!pConn->isOpen()) break;
        GETPKT(C4PacketPing, rPkt);
        // save
        pConn->SetPingTime(rPkt.getTravelTime());
    }
    break;

    case PID_FwdReq:
    {
        GETPKT(C4PacketFwd, rPkt);
        HandleFwdReq(rPkt, pConn);
    }
    break;

    case PID_Fwd:
    {
        GETPKT(C4PacketFwd, rPkt);
        // only received accidently?
        if (!rPkt.DoFwdTo(LCCore.getID())) break;
        // handle
        C4NetIOPacket Packet(rPkt.getData(), pConn->getPeerAddr());
        HandlePacket(Packet, pConn, true);
    }
    break;

    case PID_PostMortem:
    {
        GETPKT(C4PacketPostMortem, rPkt);
        // Get connection
        C4Network2IOConnection *pConn = GetConnectionByID(rPkt.getConnID());
        if (!pConn) return;
        // Handle all packets
        uint32_t iCounter;
        for (iCounter = pConn->getInPacketCounter(); ; iCounter++)
        {
            // Get packet
            const C4NetIOPacket *pPkt = rPkt.getPacket(iCounter);
            if (!pPkt) break;
            // Handle it
            HandlePacket(*pPkt, pConn, true);
        }
        // Log
        if (iCounter > pConn->getInPacketCounter())
            Application.InteractiveThread.ThreadLogS("Network: Recovered %d packets", iCounter - pConn->getInPacketCounter());
        // Remove the connection from our list
        if (!pConn->isClosed())
            pConn->Close();
        RemoveConnection(pConn);
    }
    break;

    }

#undef GETPKT
}