Ejemplo n.º 1
0
std::unique_ptr<C4NetpuncherPacket> C4NetpuncherPacket::Construct(const C4NetIOPacket& rpack) {
	if (!rpack.getPData() || *rpack.getPData() != C4NetpuncherProtocolVersion) return nullptr;
	try {
		switch (rpack.getStatus())
		{
			case PID_Puncher_AssID: return uptr(new C4NetpuncherPacketAssID(rpack));
			case PID_Puncher_SReq:  return uptr(new C4NetpuncherPacketSReq(rpack));
			case PID_Puncher_CReq:  return uptr(new C4NetpuncherPacketCReq(rpack));
			case PID_Puncher_IDReq: return uptr(new C4NetpuncherPacketIDReq(rpack));
			default: return nullptr;
		}
	}
	catch (StdCompiler::Exception *e) { delete e; return nullptr; }
	catch (...) { return nullptr; }
}
Ejemplo n.º 2
0
void C4Network2IRCClient::PackPacket(const C4NetIOPacket &rPacket, StdBuf &rOutBuf)
	{
	// Enlarge buffer
	int iSize = rPacket.getSize(),
			iPos = rOutBuf.getSize();
	rOutBuf.Grow(iSize + 2);
	// Write packet
	rOutBuf.Write(rPacket, iPos);
	// Terminate
	uint8_t *pPos = getMBufPtr<uint8_t>(rOutBuf, iPos + iSize);
	*pPos = '\r'; *(pPos + 1) = '\n';
	}
Ejemplo n.º 3
0
bool C4Network2IOConnection::Send(const C4NetIOPacket &rPkt)
{
    // some packets shouldn't go into the log
    if (rPkt.getStatus() < PID_PacketLogStart)
    {
        assert(isOpen());
        C4NetIOPacket Copy(rPkt);
        Copy.SetAddr(PeerAddr);
        return pNetClass->Send(Copy);
    }
    CStdLock PacketLogLock(&PacketLogCSec);
    // create log entry
    PacketLogEntry *pLogEntry = new PacketLogEntry();
    pLogEntry->Number = iOutPacketCounter++;
    pLogEntry->Pkt = rPkt;
    pLogEntry->Next = pPacketLog;
    pPacketLog = pLogEntry;
    // set address
    pLogEntry->Pkt.SetAddr(PeerAddr);
    // closed? No sweat, post mortem will reroute it later.
    if (!isOpen())
    {
        // post mortem already sent? This shouldn't happen
        if (fPostMortemSent) {
            assert(false);
            return false;
        }
        // okay then
        return true;
    }
    // send
    bool fSuccess = pNetClass->Send(pLogEntry->Pkt);
    if (fSuccess)
        assert(!fPostMortemSent);
    else {
        // Not being able to send a packet is actually a big deal,
        // as this means that we will have hole in the packet
        // order. Better close the connection - post mortem should
        // ideally sort everything out from here.
        LogF("Network: Fatal: Send failed (%s)", pNetClass->GetError());
        pNetClass->ResetError();
        Close();
    }
    return fSuccess;
}
Ejemplo n.º 4
0
C4NetIOPacket C4NetpuncherPacket::PackTo(const C4NetIO::addr_t& addr) const {
	C4NetIOPacket pkt;
	pkt.SetAddr(addr);
	StdBuf content(PackInto());
	char type = GetType();
	pkt.New(sizeof(type) + sizeof(C4NetpuncherProtocolVersion) + content.getSize());
	size_t offset = 0;
	pkt.Write(&type, sizeof(type), offset);
	offset += sizeof(type);
	pkt.Write(&C4NetpuncherProtocolVersion, sizeof(C4NetpuncherProtocolVersion), offset);
	offset += sizeof(C4NetpuncherProtocolVersion);
	pkt.Write(content, offset);
	return pkt;
}
Ejemplo n.º 5
0
void C4PacketBase::unpack(const C4NetIOPacket &Pkt, char *pStatus)
{
	if (pStatus) *pStatus = Pkt.getStatus();
	CompileFromBuf<StdCompilerBinRead>(*this, pStatus ? Pkt.getPBuf() : Pkt.getRef());
}
Ejemplo n.º 6
0
bool C4Network2IO::HandlePacket(const C4NetIOPacket &rPacket, C4Network2IOConnection *pConn, bool fThread)
{
    // security: add connection reference
    if (!pConn) return false;
    pConn->AddRef();

    // accept only PID_Conn and PID_Ping on non-accepted connections
    if(!pConn->isHalfAccepted())
        if(rPacket.getStatus() != PID_Conn && rPacket.getStatus() != PID_Ping && rPacket.getStatus() != PID_ConnRe)
            return false;

    // unpack packet (yet another no-idea-why-it's-needed-cast)
    C4IDPacket Pkt;
    C4PacketBase &PktB = Pkt;
    try
    {
        PktB.unpack(rPacket);
    }
    catch (StdCompiler::Exception *pExc)
    {
        Application.InteractiveThread.ThreadLog("Network: error: Failed to unpack packet id %02x: %s", rPacket.getStatus(), pExc->Msg.getData());
        delete pExc;
#ifndef _DEBUG
        pConn->Close();
#endif
        return false;
    }

    // dump packet (network thread only)
#if(C4NET2IO_DUMP_LEVEL > 0)
    if (Config.Network.PacketLogging && fThread && Pkt.getPktType() != PID_Ping && Pkt.getPktType() != PID_Pong && Pkt.getPktType() != PID_NetResData)
    {
        // StdStrBuf PacketDump = DecompileToBuf<StdCompilerINIWrite>(mkNamingAdaptrPacket);
        StdStrBuf PacketHeader = FormatString("HandlePacket: %s by %s:%d (%lu bytes, counter %d)",
                                              C4TimeMilliseconds::Now().AsString().getData(),
                                              inet_ntoa(pConn->getPeerAddr().sin_addr), htons(pConn->getPeerAddr().sin_port),
                                              static_cast<unsigned long>(rPacket.getSize()), pConn->getInPacketCounter());
        StdStrBuf Dump = DecompileToBuf<StdCompilerINIWrite>(mkNamingAdapt(Pkt, PacketHeader.getData()));
        // Put it directly. The standard functions behind StdBuf.Format seem to choke when you pass them too much data.
        Application.InteractiveThread.PushEvent(Ev_LogSilent, Dump.GrabPointer());
    }
#endif

    // search packet handling data
    bool fSendToMainThread = false, fHandled = false;
    for (const C4PktHandlingData *pHData = PktHandlingData; pHData->ID != PID_None; pHData++)
        if (pHData->ID == rPacket.getStatus())
        {
            // correct thread?
            if (!pHData->ProcByThread == !fThread)
            {
                // connection accepted?
                if (pHData->AcceptedOnly || pConn->isAccepted() || pConn->isClosed())
                {
                    fHandled = true;
#if(C4NET2IO_DUMP_LEVEL > 2)
                    C4TimeMilliseconds tStart = C4TimeMilliseconds::Now();
#endif

                    // call handler(s)
                    CallHandlers(pHData->HandlerID, &Pkt, pConn, fThread);

#if(C4NET2IO_DUMP_LEVEL > 2)
                    uint32_t iBlockedTime = C4TimeMilliseconds::Now() - tStart;
                    if (fThread && iBlockedTime > 100)
                    {
                        Application.InteractiveThread.ThreadLogS("HandlePacket: ... blocked for %u ms!", iBlockedTime);
                    }
#endif

                }
            }
            // transfer to main thread?
            else if (!pHData->ProcByThread && fThread)
            {
                fHandled = true;
                fSendToMainThread = true;
            }
        }

    // send to main thread?
    if (fSendToMainThread)
    {
        // create data
        NetEvPacketData *pEvData = new NetEvPacketData;
        pEvData->Packet.Take(rPacket.Duplicate());
        pEvData->Conn = pConn;
        pConn->AddRef();
        // trigger event
        if (!Application.InteractiveThread.PushEvent(Ev_Net_Packet, pEvData))
            Application.InteractiveThread.ThreadLogS("...push event ");
    }

    // unhandled?
    if (!fHandled && !pConn->isClosed())
        Application.InteractiveThread.ThreadLog("Network: Unhandled packet (status %02x)", rPacket.getStatus());

    // remove connection reference
    pConn->DelRef();
    return fHandled;
}
Ejemplo n.º 7
0
C4NetpuncherPacketID<TYPE>::C4NetpuncherPacketID(const C4NetIOPacket& rpack) {
	if (rpack.getPSize() < HeaderPSize + sizeof(id)) throw "invalid size";
	id = *getBufPtr<CID>(rpack, HeaderSize);
}
Ejemplo n.º 8
0
C4NetpuncherPacketCReq::C4NetpuncherPacketCReq(const C4NetIOPacket& rpack) {
	if (rpack.getPSize() < HeaderPSize + 2 + 16) throw "invalid size";
	uint16_t port = *getBufPtr<uint16_t>(rpack, HeaderSize);
	addr.SetAddress(C4NetIO::addr_t::Any, port);
	memcpy(&static_cast<sockaddr_in6*>(&addr)->sin6_addr, getBufPtr<char>(rpack, HeaderSize + sizeof(port)), 16);
}