Exemplo n.º 1
0
void C4Network2IO::HandleFwdReq(const C4PacketFwd &rFwd, C4Network2IOConnection *pBy)
{
    CStdLock ConnListLock(&ConnListCSec);
    // init packet
    C4PacketFwd nFwd;
    nFwd.SetListType(false);
    // find all clients the message should be forwarded to
    int iClientID;
    C4Network2IOConnection *pConn;
    for (pConn = pConnList; pConn; pConn = pConn->pNext)
        if (pConn->isAccepted())
            if ((iClientID = pConn->getClientID()) >= 0)
                if (iClientID != pBy->getClientID())
                    if (rFwd.DoFwdTo(iClientID) && !nFwd.DoFwdTo(iClientID))
                        nFwd.AddClient(iClientID);
    // check count (hardcoded: broadcast for > 2 clients)
    if (nFwd.getClientCnt() <= 2)
    {
        C4NetIOPacket Pkt(rFwd.getData(), C4NetIO::addr_t());
        for (int i = 0; i < nFwd.getClientCnt(); i++)
            if ((pConn = GetMsgConnection(nFwd.getClient(i))))
            {
                pConn->Send(Pkt);
                pConn->DelRef();
            }
    }
    else
    {
        // Temporarily unlock connection list for getting broadcast lock
        // (might lead to deathlocks otherwise, as the lock is often taken
        //  in the opposite order)
        ConnListLock.Clear();

        BeginBroadcast();
        nFwd.SetData(rFwd.getData());
        // add all clients
        CStdLock ConnListLock(&ConnListCSec);
        for (int i = 0; i < nFwd.getClientCnt(); i++)
            if ((pConn = GetMsgConnection(nFwd.getClient(i))))
            {
                pConn->SetBroadcastTarget(true);
                pConn->DelRef();
            }
        // broadcast
        Broadcast(MkC4NetIOPacket(PID_Fwd, nFwd));
        EndBroadcast();
    }
    // doing a callback here; don't lock!
    ConnListLock.Clear();
    // forward to self?
    if (rFwd.DoFwdTo(LCCore.getID()))
    {
        C4NetIOPacket Packet(rFwd.getData(), pBy->getPeerAddr());
        HandlePacket(Packet, pBy, true);
    }
}
Exemplo n.º 2
0
bool C4Network2IO::BroadcastMsg(const C4NetIOPacket &rPkt) // by both
{
    // TODO: ugly algorithm. do better

    // begin broadcast
    BeginBroadcast(false);
    // select one connection per reachable client
    CStdLock ConnListLock(&ConnListCSec);
    for (C4Network2IOConnection *pConn = pConnList; pConn; pConn = pConn->pNext)
        if (pConn->isAccepted())
        {
            if (pConn->getProtocol() == P_UDP)
                pConn->SetBroadcastTarget(true);
            else if (pConn->getProtocol() == P_TCP)
            {
                C4Network2IOConnection *pConn2 = GetMsgConnection(pConn->getClientID());
                if (pConn == pConn2)
                    pConn->SetBroadcastTarget(true);
                pConn2->DelRef();
            }
        }
    // send
    bool fSuccess = Broadcast(rPkt);
    // end broadcast
    EndBroadcast();
    // return
    return fSuccess;
}
Exemplo n.º 3
0
void C4Network2IO::SendConnPackets()
{
    CStdLock ConnListLock(&ConnListCSec);

    // exlusive conn?
    if (fExclusiveConn)
        // find a live connection
        for (C4Network2IOConnection *pConn = pConnList; pConn; pConn = pConn->pNext)
            if (pConn->isAccepted() || (!pConn->isClosed() && pConn->isConnSent()))
                // do not sent additional conn packets - no other connection should succeed
                return;

    // sent pending welcome packet(s)
    for (C4Network2IOConnection *pConn = pConnList; pConn; pConn = pConn->pNext)
        if (pConn->isOpen() && !pConn->isConnSent())
        {
            // make packet
            CStdLock LCCoreLock(&LCCoreCSec);
            C4NetIOPacket Pkt = MkC4NetIOPacket(PID_Conn, C4PacketConn(LCCore, pConn->getID(), pConn->getPassword()));
            LCCoreLock.Clear();
            // send
            if (!pConn->Send(Pkt))
                pConn->Close();
            else
            {
                // set flag
                pConn->SetConnSent();
                // only one conn packet at a time
                if (fExclusiveConn)
                    return;
            }
        }

}
Exemplo n.º 4
0
void C4Network2IO::CheckTimeout()
{
    // acquire lock
    CStdLock ConnListLock(&ConnListCSec);
    // check all connections for timeout (use deletion-safe iteration method just in case)
    for (C4Network2IOConnection *pConn = pConnList, *pNext; pConn; pConn = pNext)
    {
        pNext = pConn->pNext;
        // status timeout
        if (!pConn->isClosed() && !pConn->isAccepted())
            if (difftime(time(NULL), pConn->getTimestamp()) > C4NetAcceptTimeout)
            {
                Application.InteractiveThread.ThreadLogS("Network: connection accept timeout to %s:%d", inet_ntoa(pConn->getPeerAddr().sin_addr), htons(pConn->getPeerAddr().sin_port));
                pConn->Close();
            }
        // ping timeout
        if (pConn->isAccepted())
            if ((pConn->getLag() != -1 ? pConn->getLag() : 1000 * difftime(time(NULL), pConn->getTimestamp()))
                    > C4NetPingTimeout)
            {
                Application.InteractiveThread.ThreadLogS("%d %d %d", (int)pConn->getLag(), (int)time(NULL), (int)pConn->getTimestamp());
                Application.InteractiveThread.ThreadLogS("Network: ping timeout to %s:%d", inet_ntoa(pConn->getPeerAddr().sin_addr), htons(pConn->getPeerAddr().sin_port));
                pConn->Close();
            }
        // delayed connection removal
        if (pConn->isClosed())
            if (difftime(time(NULL), pConn->getTimestamp()) > C4NetAcceptTimeout)
                RemoveConnection(pConn);
    }
}
Exemplo n.º 5
0
C4Network2IOConnection *C4Network2IO::GetConnectionByID(uint32_t iConnID) // by thread
{
    CStdLock ConnListLock(&ConnListCSec);
    // search
    for (C4Network2IOConnection *pConn = pConnList; pConn; pConn = pConn->pNext)
        if (pConn->getID() == iConnID)
            return pConn;
    return NULL;
}
Exemplo n.º 6
0
C4Network2IOConnection *C4Network2IO::GetConnectionByConnAddr(const C4NetIO::addr_t &addr, C4NetIO *pNetIO) // by both
{
    CStdLock ConnListLock(&ConnListCSec);
    // search
    for (C4Network2IOConnection *pConn = pConnList; pConn; pConn = pConn->pNext)
        if (pConn->getNetClass() == pNetIO && AddrEqual(pConn->getConnectAddr(), addr))
            return pConn;
    return NULL;
}
Exemplo n.º 7
0
void C4Network2IO::AddConnection(C4Network2IOConnection *pConn) // by both
{
    CStdLock ConnListLock(&ConnListCSec);
    // add reference
    pConn->AddRef();
    // add to list
    pConn->pNext = pConnList;
    pConnList = pConn;
}
Exemplo n.º 8
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;
}
Exemplo n.º 9
0
void C4Network2IO::BeginBroadcast(bool fSelectAll)
{
    // lock
    BroadcastCSec.Enter();
    // reset all broadcast flags
    CStdLock ConnListLock(&ConnListCSec);
    for (C4Network2IOConnection *pConn = pConnList; pConn; pConn = pConn->pNext)
        if (pConn->isOpen())
            pConn->SetBroadcastTarget(fSelectAll);
}
Exemplo n.º 10
0
void C4Network2IO::Clear() // by main thread
{
    // process remaining events
    C4InteractiveThread &Thread = Application.InteractiveThread;
    Thread.ProcessEvents();
    // clear event callbacks
    Thread.ClearCallback(Ev_Net_Conn, this);
    Thread.ClearCallback(Ev_Net_Disconn, this);
    Thread.ClearCallback(Ev_Net_Packet, this);
    // close all connections
    CStdLock ConnListLock(&ConnListCSec);
    for (C4Network2IOConnection *pConn = pConnList, *pNext; pConn; pConn = pNext)
    {
        pNext = pConn->pNext;
        // close
        pConn->Close();
        RemoveConnection(pConn);
    }
    // reset list
    pConnList = NULL;
    ConnListLock.Clear();
    // close net i/o classes
    Thread.RemoveProc(this);
    if (pNetIODiscover) {
        Thread.RemoveProc(pNetIODiscover);
        delete pNetIODiscover;
        pNetIODiscover = NULL;
    }
    if (pNetIO_TCP) {
        Thread.RemoveProc(pNetIO_TCP);
        delete pNetIO_TCP;
        pNetIO_TCP = NULL;
    }
    if (pNetIO_UDP) {
        Thread.RemoveProc(pNetIO_UDP);
        delete pNetIO_UDP;
        pNetIO_UDP = NULL;
    }
    if (pRefServer) {
        Thread.RemoveProc(pRefServer);
        delete pRefServer;
        pRefServer = NULL;
    }
    if (UPnPMgr) {
        delete UPnPMgr;
        UPnPMgr = NULL;
    }
    // remove auto-accepts
    ClearAutoAccept();
    // reset flags
    fAllowConnect = fExclusiveConn = false;
    // reset connection ID
    iNextConnID = 0;
}
Exemplo n.º 11
0
bool C4Network2IO::Broadcast(const C4NetIOPacket &rPkt)
{
    bool fSuccess = true;
    // There is no broadcasting atm, emulate it
    CStdLock ConnListLock(&ConnListCSec);
    for (C4Network2IOConnection *pConn = pConnList; pConn; pConn = pConn->pNext)
        if (pConn->isOpen() && pConn->isBroadcastTarget())
            fSuccess &= pConn->Send(rPkt);
    if(!fSuccess)
        Log("Network: Warning! Broadcast failed.");
    return fSuccess;
}
Exemplo n.º 12
0
C4Network2IOConnection *C4Network2IO::GetDataConnection(int iClientID) // by main thread
{
    CStdLock ConnListLock(&ConnListCSec);
    C4Network2IOConnection *pRes = NULL;
    for (C4Network2IOConnection *pConn = pConnList; pConn; pConn = pConn->pNext)
        if (pConn->isAccepted())
            if (pConn->getClientID() == iClientID)
                if (pConn->getProtocol() == P_TCP || !pRes)
                    pRes = pConn;
    // add reference
    if (pRes) pRes->AddRef();
    return pRes;
}
Exemplo n.º 13
0
void C4Network2IO::RemoveConnection(C4Network2IOConnection *pConn) // by both
{
    CStdLock ConnListLock(&ConnListCSec);
    // search & remove
    if (pConnList == pConn)
        pConnList = pConn->pNext;
    else
    {
        C4Network2IOConnection *pAct;
        for (pAct = pConnList; pAct; pAct = pAct->pNext)
            if (pAct->pNext == pConn)
                break;
        if (pAct)
            pAct->pNext = pConn->pNext;
        else
            return;
    }
    // remove reference
    pConn->pNext = NULL;
    pConn->DelRef();
}
Exemplo n.º 14
0
void C4Network2IO::GenerateStatistics(int iInterval)
{
    int iTCPIRateSum = 0, iTCPORateSum = 0, iUDPIRateSum = 0, iUDPORateSum = 0;

    // acquire lock, get connection statistics
    CStdLock ConnListLock(&ConnListCSec);
    for (C4Network2IOConnection *pConn = pConnList; pConn; pConn = pConn->pNext)
        if (pConn->isOpen())
        {
            bool fTCP = pConn->getNetClass() == pNetIO_TCP;
            pConn->DoStatistics(iInterval, fTCP ? &iTCPIRateSum : &iUDPIRateSum,
                                fTCP ? &iTCPORateSum : &iUDPORateSum);
        }
    ConnListLock.Clear();

    // get broadcast statistics
    int inTCPBCRate = 0, inUDPBCRate = 0;
    if (pNetIO_TCP) pNetIO_TCP->GetStatistic(&inTCPBCRate);
    if (pNetIO_UDP) pNetIO_UDP->GetStatistic(&inUDPBCRate);

    // normalize everything
    iTCPIRateSum = iTCPIRateSum * 1000 / iInterval;
    iTCPORateSum = iTCPORateSum * 1000 / iInterval;
    iUDPIRateSum = iUDPIRateSum * 1000 / iInterval;
    iUDPORateSum = iUDPORateSum * 1000 / iInterval;
    inTCPBCRate = inTCPBCRate * 1000 / iInterval;
    inUDPBCRate = inUDPBCRate * 1000 / iInterval;

    // clear
    if (pNetIO_TCP) pNetIO_TCP->ClearStatistic();
    if (pNetIO_UDP) pNetIO_UDP->ClearStatistic();

    // save back
    iTCPIRate = iTCPIRateSum;
    iTCPORate = iTCPORateSum;
    iTCPBCRate = inTCPBCRate;
    iUDPIRate = iUDPIRateSum;
    iUDPORate = iUDPORateSum;
    iUDPBCRate = inUDPBCRate;
}