예제 #1
0
int C4Network2IO::getConnectionCount()  // by main thread
{
    int iCount = 0;
    CStdLock ConnListLock(&ConnListCSec);
    for (C4Network2IOConnection *pConn = pConnList; pConn; pConn = pConn->pNext)
        if (!pConn->isClosed())
            iCount++;
    return iCount;
}
예제 #2
0
// C4NetIO interface
bool C4Network2IO::OnConn(const C4NetIO::addr_t &PeerAddr, const C4NetIO::addr_t &ConnectAddr, const C4NetIO::addr_t *pOwnAddr, C4NetIO *pNetIO)
{
    // puncher answer? We just make sure here a connection /can/ be established, so close it instantly.
    if (pNetIO == pNetIO_UDP)
        if (PuncherAddr.sin_addr.s_addr && AddrEqual(PuncherAddr, ConnectAddr))
        {
            // got an address?
            if (pOwnAddr)
                OnPunch(*pOwnAddr);
            // this is only a test connection - close it instantly
            return false;
        }
#if(C4NET2IO_DUMP_LEVEL > 1)
    Application.InteractiveThread.ThreadLogS("OnConn: %s %s",
            C4TimeMilliseconds::Now().AsString().getData(),
            getNetIOName(pNetIO));
#endif
    // search connection
    C4Network2IOConnection *pConn = NULL;
    if (ConnectAddr.sin_addr.s_addr)
        pConn = GetConnectionByConnAddr(ConnectAddr, pNetIO);
    // not found?
    if (!pConn)
    {
        // allow connect?
        if (!fAllowConnect) return false;
        // create new connection object
        uint32_t iConnID = iNextConnID++;
        pConn = new C4Network2IOConnection();
        pConn->Set(pNetIO, getNetIOProt(pNetIO), PeerAddr, ConnectAddr, CS_Connected, NULL, iConnID);
        // add to list
        AddConnection(pConn);
    }
    else
    {
        // already closed this connection (attempt)?
        if (pConn->isClosed())
            return false;
        if (!pConn->isOpen())
        {
            // change status
            pConn->SetStatus(CS_Connected);
            pConn->SetPeerAddr(PeerAddr);
        }
    }
    // send welcome packet, if appropriate
    SendConnPackets();
#if(C4NET2IO_DUMP_LEVEL > 0)
    // log
    Application.InteractiveThread.ThreadLogS("Network: got %s connection from %s:%d", getNetIOName(pNetIO), inet_ntoa(PeerAddr.sin_addr), htons(PeerAddr.sin_port));
#endif
    // do event (disabled - unused)
    // pConn->AddRef(); PushNetEv(NE_Conn, pConn);
    // ok
    return true;
}
예제 #3
0
void C4Network2IO::OnThreadEvent(C4InteractiveEventType eEvent, void *pEventData) // by main thread
{
    switch (eEvent)
    {
    case Ev_Net_Conn: // got a connection
    {
        C4Network2IOConnection *pConn = reinterpret_cast<C4Network2IOConnection *>(pEventData);
        // do callback
        ::Network.OnConn(pConn);
        // remove reference
        pConn->DelRef();
    }
    break;

    case Ev_Net_Disconn: // connection closed
    {
        C4Network2IOConnection *pConn = reinterpret_cast<C4Network2IOConnection *>(pEventData);
        assert(pConn->isClosed());
        // do callback
        ::Network.OnDisconn(pConn);
        // remove reference
        pConn->DelRef();
    }
    break;

    case Ev_Net_Packet: // got packet
    {
        NetEvPacketData *pData = reinterpret_cast<NetEvPacketData *>(pEventData);
        // handle
        HandlePacket(pData->Packet, pData->Conn, false);
        // clear up
        pData->Conn->DelRef();
        delete pData;
    }
    break;

    default:
        // TODO
        break;
    }
}
예제 #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
}