Beispiel #1
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;
}
Beispiel #2
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);
    }
}
Beispiel #3
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;
}