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

}
void C4Network2ClientListBox::ConnectionListItem::OnButtonDisconnect(C4GUI::Control *pButton)
{
	// close connection
	C4Network2IOConnection *pConn = GetConnection();
	if (pConn)
	{
		pConn->Close();
	}
}
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;
}
Exemple #5
0
void C4Network2Client::CloseConns(const char *szMsg) {
  C4PacketConnRe Pkt(false, false, szMsg);
  C4Network2IOConnection *pConn;
  while (pConn = pMsgConn) {
    // send packet, close
    if (pConn->isOpen()) {
      pConn->Send(MkC4NetIOPacket(PID_ConnRe, Pkt));
      pConn->Close();
    }
    // remove
    RemoveConn(pConn);
  }
}
Exemple #6
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
}