Пример #1
0
void C4MainStat::ShowPart(int FrameCounter)
{
	C4Stat* pAkt;

	// insert tick nr
	LogSilentF("** PartStat begin %d", FrameCounter);

	// insert all stats
	for (pAkt = pFirst; pAkt; pAkt = pAkt->pNext)
		LogSilentF("%s: n=%u, t=%u", pAkt->strName, pAkt->iCountPart, pAkt->tTimeSumPart);

	// insert part stat end idtf
	LogSilentF("** PartStat end\n");
}
Пример #2
0
bool C4Network2Client::DoConnectAttempt(C4Network2IO *pIO)
{
	// local?
	if (isLocal()) { iNextConnAttempt = 0; return true; }
	// msg and data connected? Nothing to do
	if (getMsgConn() != getDataConn()) { iNextConnAttempt = time(NULL) + 10; return true; }
	// too early?
	if (iNextConnAttempt && iNextConnAttempt > time(NULL)) return true;
	// find address to try
	int32_t iBestAddress = -1;
	for (int32_t i = 0; i < iAddrCnt; i++)
		// no connection for this protocol?
		if ((!pDataConn || Addr[i].getProtocol() != pDataConn->getProtocol()) &&
		    (!pMsgConn  || Addr[i].getProtocol() != pMsgConn->getProtocol()))
			// protocol available?
			if (pIO->getNetIO(Addr[i].getProtocol()))
				// new best address?
				if (iBestAddress < 0 || AddrAttempts[i] < AddrAttempts[iBestAddress])
					iBestAddress = i;
	// too many attempts or nothing found?
	if (iBestAddress < 0 || AddrAttempts[iBestAddress] > C4NetClientConnectAttempts)
		{ iNextConnAttempt = time(NULL) + 10; return true; }
	// save attempt
	AddrAttempts[iBestAddress]++; iNextConnAttempt = time(NULL) + C4NetClientConnectInterval;
	// log
	LogSilentF("Network: connecting client %s on %s...", getName(), Addr[iBestAddress].toString().getData());
	// connect
	return pIO->Connect(Addr[iBestAddress].getAddr(), Addr[iBestAddress].getProtocol(), pClient->getCore());
}
Пример #3
0
bool C4Network2Res::SetByGroup(C4Group *pGrp, bool fTemp, C4Network2ResType eType, int32_t iResID, const char *szResName, bool fSilent) // by main thread
{
	Clear();
	CStdLock FileLock(&FileCSec);
	// default resource name: relative path
	StdStrBuf sResName;
	if (szResName)
		sResName = szResName;
	else
	{
		StdStrBuf sFullName = pGrp->GetFullName();
		sResName.Copy(Config.AtRelativePath(sFullName.getData()));
	}
	SCopy(pGrp->GetFullName().getData(), szFile, sizeof(szFile)-1);
	// set core
	Core.Set(eType, iResID, sResName.getData(), pGrp->EntryCRC32());
#ifdef C4NET2RES_DEBUG_LOG
	// log
	LogSilentF("Network: Resource: complete %d:%s is file %s (%s)", iResID, sResName.getData(), szFile, fTemp ? "temp" : "static");
#endif
	// set data
	fDirty = true;
	fTempFile = fTemp;
	fStandaloneFailed = false;
	fRemoved = false;
	iLastReqTime = time(NULL);
	fLoading = false;
	// ok
	return true;
}
Пример #4
0
bool C4Network2Res::SetByFile(const char *strFilePath, bool fTemp, C4Network2ResType eType, int32_t iResID, const char *szResName, bool fSilent)
{
	CStdLock FileLock(&FileCSec);
	// default resource name: relative path
	if (!szResName) szResName = Config.AtRelativePath(strFilePath);
	SCopy(strFilePath, szFile, sizeof(szFile)-1);
	// group?
	C4Group Grp;
	if (Reloc.Open(Grp, strFilePath))
		return SetByGroup(&Grp, fTemp, eType, iResID, szResName, fSilent);
	// so it needs to be a file
	StdStrBuf szFullFile;
	if (!Reloc.LocateItem(szFile, szFullFile))
		{ if (!fSilent) LogF("SetByFile: file %s not found!", strFilePath); return false; }
	// calc checksum
	uint32_t iCRC32;
	if (!GetFileCRC(szFullFile.getData(), &iCRC32)) return false;
#ifdef C4NET2RES_DEBUG_LOG
	// log
	LogSilentF("Network: Resource: complete %d:%s is file %s (%s)", iResID, szResName, szFile, fTemp ? "temp" : "static");
#endif
	// set core
	Core.Set(eType, iResID, Config.AtRelativePath(szFullFile.getData()), iCRC32);
	// set own data
	fDirty = true;
	fTempFile = fTemp;
	fStandaloneFailed = false;
	fRemoved = false;
	iLastReqTime = time(NULL);
	fLoading = false;
	// ok
	return true;
}
Пример #5
0
void C4Network2Res::Clear()
{
	CStdLock FileLock(&FileCSec);
	// delete files
	if (fTempFile)
		if (FileExists(szFile))
			if (!EraseFile(szFile))
				LogSilentF("Network: Could not delete temporary resource file (%s)", strerror(errno));
	if (szStandalone[0] && !SEqual(szFile, szStandalone))
		if (FileExists(szStandalone))
			if (!EraseFile(szStandalone))
				LogSilentF("Network: Could not delete temporary resource file (%s)", strerror(errno));
	szFile[0] = szStandalone[0] = '\0';
	fDirty = false;
	fTempFile = false;
	Core.Clear();
	Chunks.Clear();
	fRemoved = false;
	ClearLoad();
}
Пример #6
0
bool C4Network2Client::DoConnectAttempt(C4Network2IO *pIO)
{
	// local?
	if (isLocal()) { iNextConnAttempt = 0; return true; }
	// msg and data connected? Nothing to do
	if (getMsgConn() != getDataConn()) { iNextConnAttempt = time(nullptr) + 10; return true; }
	// too early?
	if (iNextConnAttempt && iNextConnAttempt > time(nullptr)) return true;
	// find address to try
	int32_t iBestAddress = -1;
	for (int32_t i = 0; i < iAddrCnt; i++)
		// no connection for this protocol?
		if ((!pDataConn || Addr[i].getProtocol() != pDataConn->getProtocol()) &&
		    (!pMsgConn  || Addr[i].getProtocol() != pMsgConn->getProtocol()))
			// protocol available?
			if (pIO->getNetIO(Addr[i].getProtocol()))
				// new best address?
				if (iBestAddress < 0 || AddrAttempts[i] < AddrAttempts[iBestAddress])
					iBestAddress = i;
	// too many attempts or nothing found?
	if (iBestAddress < 0 || AddrAttempts[iBestAddress] > C4NetClientConnectAttempts)
		{ iNextConnAttempt = time(nullptr) + 10; return true; }
	// save attempt
	AddrAttempts[iBestAddress]++; iNextConnAttempt = time(nullptr) + C4NetClientConnectInterval;
	auto addr = Addr[iBestAddress].getAddr();

	// try TCP simultaneous open if the stars align right
	if (addr.GetFamily() == C4NetIO::addr_t::IPv6 && // address needs to be IPv6...
	    !addr.IsLocal() && !addr.IsPrivate() &&      // ...global unicast...
	    Addr[iBestAddress].getProtocol() == P_TCP && // ...TCP,
	    !TcpSimOpenSocket &&                         // there is no previous request,
	    pParent->GetLocal()->getID() < getID())      // and make sure that only one client per pair initiates a request.
	{
		DoTCPSimultaneousOpen(pIO, C4Network2Address());
	}

	std::set<int> interfaceIDs;
	if (addr.IsLocal())
	    interfaceIDs = Network.Clients.GetLocal()->getInterfaceIDs();
	else
	    interfaceIDs = {0};
	for (auto id : interfaceIDs)
	{
	    addr.SetScopeId(id);
	    // log
	    LogSilentF("Network: connecting client %s on %s...", getName(), addr.ToString().getData());
	    // connect
	    if (pIO->Connect(addr, Addr[iBestAddress].getProtocol(), pClient->getCore()))
		return true;
	}
	return false;
}
Пример #7
0
bool C4Network2Client::DoTCPSimultaneousOpen(class C4Network2IO *pIO, const C4Network2Address &addr)
{
	if (!pIO->getNetIO(P_TCP)) return false;

	// Did we already bind a socket?
	if (TcpSimOpenSocket)
	{
		LogSilentF("Network: connecting client %s on %s with TCP simultaneous open...", getName(), addr.getAddr().ToString().getData());
		return pIO->ConnectWithSocket(addr.getAddr(), addr.getProtocol(), pClient->getCore(), std::move(TcpSimOpenSocket));
	}
	else
	{
		// No - bind one, inform peer, and schedule a connection attempt.
		auto NetIOTCP = dynamic_cast<C4NetIOTCP*>(pIO->getNetIO(P_TCP));
		auto bindAddr = pParent->GetLocal()->IPv6AddrFromPuncher;
		// We need to know an address that works.
		if (bindAddr.IsNull()) return false;
		bindAddr.SetPort(0);
		TcpSimOpenSocket = NetIOTCP->Bind(bindAddr);
		auto boundAddr = TcpSimOpenSocket->GetAddress();
		LogSilentF("Network: %s TCP simultaneous open request for client %s from %s...", addr.isIPNull() ? "initiating" : "responding to",
				getName(), boundAddr.ToString().getData());
		// Send address we bound to to the client.
		if (!SendMsg(MkC4NetIOPacket(PID_TCPSimOpen, C4PacketTCPSimOpen(pParent->GetLocal()->getID(), C4Network2Address(boundAddr, P_TCP)))))
			return false;
		if (!addr.isIPNull())
		{
			// We need to delay the connection attempt a bit. Unfortunately,
			// waiting for the next tick would usually take way too much time.
			// Instead, we block the main thread for a very short time and hope
			// that noone notices...
			int ping = getMsgConn()->getLag();
			std::this_thread::sleep_for(std::chrono::milliseconds(std::min(ping / 2, 10)));
			DoTCPSimultaneousOpen(pIO, addr);
		}
		return true;
	}
}
Пример #8
0
CStdGLCtx *CStdGL::CreateContext(C4Window * pWindow, C4AbstractApp *pApp)
{
	// safety
	if (!pWindow) return NULL;

	// create it
	CStdGLCtx *pCtx = new CStdGLCtx();
	bool first_ctx = !pMainCtx;
	if (first_ctx)
	{
		pMainCtx = pCtx;
		LogF("  gl: Create first %scontext...", Config.Graphics.DebugOpenGL ? "debug " : "");
	}
	bool success = pCtx->Init(pWindow, pApp);
	if (Config.Graphics.DebugOpenGL && glDebugMessageCallbackARB)
	{
		if (first_ctx) Log("  gl: Setting OpenGLDebugProc callback");
		glDebugMessageCallbackARB(&OpenGLDebugProc, nullptr);
		glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
#ifdef GL_KHR_debug
		if (GLEW_KHR_debug)
			glEnable(GL_DEBUG_OUTPUT);
#endif
	}
	// First context: Log some information about hardware/drivers
	// Must log after context creation to get valid results
	if (first_ctx)
	{
		const char *gl_vendor = reinterpret_cast<const char *>(glGetString(GL_VENDOR));
		const char *gl_renderer = reinterpret_cast<const char *>(glGetString(GL_RENDERER));
		const char *gl_version = reinterpret_cast<const char *>(glGetString(GL_VERSION));
		LogF("GL %s on %s (%s)", gl_version ? gl_version : "", gl_renderer ? gl_renderer : "", gl_vendor ? gl_vendor : "");
		
		if (Config.Graphics.DebugOpenGL)
		{
			// Dump extension list
			if (glGetStringi)
			{
				GLint gl_extension_count = 0;
				glGetIntegerv(GL_NUM_EXTENSIONS, &gl_extension_count);
				if (gl_extension_count == 0)
				{
					LogSilentF("No available extensions.");
				}
				else
				{
					LogSilentF("%d available extensions:", gl_extension_count);
					for (GLint i = 0; i < gl_extension_count; ++i)
					{
						const char *gl_extension = (const char*)glGetStringi(GL_EXTENSIONS, i);
						LogSilentF("  %4d: %s", i, gl_extension);
					}
				}
			}
			else
			{
				const char *gl_extensions = reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));
				LogSilentF("GLExt: %s", gl_extensions ? gl_extensions : "");
			}
		}
	}
	if (!success)
	{
		delete pCtx; Error("  gl: Error creating secondary context!"); return NULL;
	}
	// creation selected the new context - switch back to previous context
	RenderTarget = NULL;
	pCurrCtx = NULL;
	// done
	return pCtx;
}
Пример #9
0
bool C4Network2Res::GetStandalone(char *pTo, int32_t iMaxL, bool fSetOfficial, bool fAllowUnloadable, bool fSilent)
{
	// already set?
	if (szStandalone[0])
	{
		if (pTo) SCopy(szStandalone, pTo, iMaxL);
		return true;
	}
	// already tried and failed? No point in retrying
	if (fStandaloneFailed) return false;
	// not loadable? Wo won't be able to check the standalone as the core will lack the needed information.
	// the standalone won't be interesting in this case, anyway.
	if (!fSetOfficial && !Core.isLoadable()) return false;
	// set flag, so failure below will let future calls fail
	fStandaloneFailed = true;
	// lock file
	CStdLock FileLock(&FileCSec);

	// directory?
	SCopy(szFile, szStandalone, sizeof(szStandalone)-1);
	if (DirectoryExists(szFile))
	{
		// size check for the directory, if allowed
		if (fAllowUnloadable)
		{
			uint32_t iDirSize;
			if (!DirSizeHelper::GetDirSize(szFile, &iDirSize, Config.Network.MaxLoadFileSize))
				{ if (!fSilent) LogF("Network: could not get directory size of %s!", szFile); szStandalone[0] = '\0'; return false; }
			if (iDirSize > uint32_t(Config.Network.MaxLoadFileSize))
				{ if (!fSilent) LogSilentF("Network: %s over size limit, will be marked unloadable!", szFile); szStandalone[0] = '\0'; return false; }
		}
		// log - this may take a few seconds
		if (!fSilent) LogF(LoadResStr("IDS_PRC_NETPACKING"), GetFilename(szFile));
		// pack inplace?
		if (!fTempFile)
		{
			if (!pParent->FindTempResFileName(szFile, szStandalone))
				{ if (!fSilent) Log("GetStandalone: could not find free name for temporary file!"); szStandalone[0] = '\0'; return false; }
			if (!C4Group_PackDirectoryTo(szFile, szStandalone))
				{ if (!fSilent) Log("GetStandalone: could not pack directory!"); szStandalone[0] = '\0'; return false; }
		}
		else if (!C4Group_PackDirectory(szStandalone))
			{ if (!fSilent) Log("GetStandalone: could not pack directory!"); if (!SEqual(szFile, szStandalone)) EraseDirectory(szStandalone); szStandalone[0] = '\0'; return false; }
		// make sure directory is packed
		if (DirectoryExists(szStandalone))
			{ if (!fSilent) Log("GetStandalone: directory hasn't been packed!"); if (!SEqual(szFile, szStandalone)) EraseDirectory(szStandalone); szStandalone[0] = '\0'; return false; }
		// fallthru
	}

	// doesn't exist physically?
	if (!FileExists(szStandalone))
	{
		// try C4Group (might be packed)
		if (!pParent->FindTempResFileName(szFile, szStandalone))
			{ if (!fSilent) Log("GetStandalone: could not find free name for temporary file!"); szStandalone[0] = '\0'; return false; }
		if (!C4Group_CopyItem(szFile, szStandalone))
			{ if (!fSilent) Log("GetStandalone: could not copy to temporary file!"); szStandalone[0] = '\0'; return false; }
	}

	// remains missing? give up.
	if (!FileExists(szStandalone))
		{ if (!fSilent) Log("GetStandalone: file not found!"); szStandalone[0] = '\0'; return false; }

	// do optimizations (delete unneeded entries)
	if (!OptimizeStandalone(fSilent))
		{ if (!SEqual(szFile, szStandalone)) EraseItem(szStandalone); szStandalone[0] = '\0'; return false; }

	// get file size
	size_t iSize = FileSize(szStandalone);
	// size limit
	if (fAllowUnloadable)
		if (iSize > uint32_t(Config.Network.MaxLoadFileSize))
			{ if (!fSilent) LogSilentF("Network: %s over size limit, will be marked unloadable!", szFile); szStandalone[0] = '\0'; return false; }
	// check
	if (!fSetOfficial && iSize != Core.getFileSize())
	{
		// remove file
		if (!SEqual(szFile, szStandalone)) EraseItem(szStandalone); szStandalone[0] = '\0';
		// sorry, this version isn't good enough :(
		return false;
	}

	// calc checksum
	uint32_t iCRC32;
	if (!GetFileCRC(szStandalone, &iCRC32))
		{ if (!fSilent) Log("GetStandalone: could not calculate checksum!"); return false; }
	// set / check
	if (!fSetOfficial && iCRC32 != Core.getFileCRC())
	{
		// remove file, return
		if (!SEqual(szFile, szStandalone)) EraseItem(szStandalone); szStandalone[0] = '\0';
		return false;
	}

	// we didn't fail
	fStandaloneFailed = false;
	// mark resource as loadable and safe file information
	Core.SetLoadable(iSize, iCRC32);
	// set up chunk data
	Chunks.SetComplete(Core.getChunkCnt());
	// ok
	return true;
}
Пример #10
0
bool C4Network2IO::Init(int16_t iPortTCP, int16_t iPortUDP, int16_t iPortDiscover, int16_t iPortRefServer, bool fBroadcast) // by main thread
{
    // Already initialized? Clear first
    if (pNetIO_TCP || pNetIO_UDP) Clear();

    // init members
    tLastPing = tLastStatistic = C4TimeMilliseconds::Now();
    iTCPIRate = iTCPORate = iTCPBCRate = 0;
    iUDPIRate = iUDPORate = iUDPBCRate = 0;

    // init event callback
    C4InteractiveThread &Thread = Application.InteractiveThread;
    Thread.SetCallback(Ev_Net_Conn, this);
    Thread.SetCallback(Ev_Net_Disconn, this);
    Thread.SetCallback(Ev_Net_Packet, this);

    // initialize UPnP manager
    if (iPortTCP > 0 || iPortUDP > 0)
    {
        assert(!UPnPMgr);
        UPnPMgr = new C4Network2UPnP;
    }

    // initialize net i/o classes: TCP first
    if (iPortTCP > 0)
    {
        // create
        pNetIO_TCP = new C4NetIOTCP();
        // init
        if (!pNetIO_TCP->Init(iPortTCP))
        {
            LogF("Network: could not init TCP i/o (%s)", pNetIO_TCP->GetError() ? pNetIO_TCP->GetError() : "");
            delete pNetIO_TCP;
            pNetIO_TCP = NULL;
        }
        else
            LogSilentF("Network: TCP initialized on port %d", iPortTCP);

        // add to thread, set callback
        if (pNetIO_TCP)
        {
            Thread.AddProc(pNetIO_TCP);
            pNetIO_TCP->SetCallback(this);
            UPnPMgr->AddMapping(P_TCP, iPortTCP, iPortTCP);
        }

    }
    // then UDP
    if (iPortUDP > 0)
    {
        // create
        pNetIO_UDP = new C4NetIOUDP();
        // init
        if (!pNetIO_UDP->Init(iPortUDP))
        {
            LogF("Network: could not init UDP i/o (%s)", pNetIO_UDP->GetError() ? pNetIO_UDP->GetError() : "");
            delete pNetIO_UDP;
            pNetIO_UDP = NULL;
        }
        else
            LogSilentF("Network: UDP initialized on port %d", iPortUDP);

        // add to thread, set callback
        if (pNetIO_UDP)
        {
            Thread.AddProc(pNetIO_UDP);
            pNetIO_UDP->SetCallback(this);
            UPnPMgr->AddMapping(P_UDP, iPortUDP, iPortUDP);
        }
    }

    // no protocols?
    if (!pNetIO_TCP && !pNetIO_UDP)
    {
        LogFatal("Network: fatal - no protocols available!");
        Thread.ClearCallback(Ev_Net_Conn, this);
        Thread.ClearCallback(Ev_Net_Disconn, this);
        Thread.ClearCallback(Ev_Net_Packet, this);
        return false;
    }

    // discovery last
    if (iPortDiscover > 0)
    {
        // create
        pNetIODiscover = new C4Network2IODiscover(iPortRefServer);
        pNetIODiscover->SetDiscoverable(false);
        // init
        if (!pNetIODiscover->Init(iPortDiscover))
        {
            LogF("Network: could not init discovery (%s)", pNetIODiscover->GetError() ? pNetIODiscover->GetError() : "");
            delete pNetIODiscover;
            pNetIODiscover = NULL;
        }
        else
            LogSilentF("Network: discovery initialized on port %d", iPortDiscover);
        // add to thread
        if (pNetIODiscover)
            Thread.AddProc(pNetIODiscover);
    }

    // plus reference server
    if (iPortRefServer > 0)
    {
        // create
        pRefServer = new C4Network2RefServer();
        // init
        if (!pRefServer->Init(iPortRefServer))
        {
            LogF("Network: could not init reference server (%s)", pNetIO_UDP->GetError() ? pNetIO_UDP->GetError() : "");
            delete pRefServer;
            pRefServer = NULL;
        }
        else
            LogSilentF("Network: reference server initialized on port %d", iPortRefServer);
        // add to thread
        if (pRefServer)
            Thread.AddProc(pRefServer);
    }

    // own timer
    tLastExecute = C4TimeMilliseconds::Now();
    Thread.AddProc(this);

    // ok
    return true;
}
Пример #11
0
void C4MainStat::Show()
{

	// count stats
	unsigned int iCnt = 0;
	C4Stat* pAkt;
	for (pAkt = pFirst; pAkt; pAkt = pAkt->pNext)
		iCnt++;

	// create array
	C4Stat** StatArray = new C4Stat*[iCnt];
	bool* bHS = new bool[iCnt];

	// sort it
	unsigned int i,ii;
	for (ii=0; ii<iCnt; ii++) bHS[ii] = false;
	for (i=0; i<iCnt; i++)
	{
		C4Stat* pBestStat = NULL;
		unsigned int iBestNr = ~0;

		for (ii=0, pAkt = pFirst; ii<iCnt; ii++, pAkt = pAkt->pNext)
			if (!bHS[ii])
			{
				if (iBestNr == ~0u)
				{
					iBestNr = ii;
					pBestStat = pAkt;
				}
				else if (stricmp(pBestStat->strName, pAkt->strName) > 0)
				{
					iBestNr = ii;
					pBestStat = pAkt;
				}
			}

		if (iBestNr == (unsigned int) -1)
			break;
		bHS[iBestNr] = true;

		StatArray[i] = pBestStat;
	}

	delete bHS;

	LogSilent("** Stat");

	// output in order
	for (i=0; i<iCnt; i++)
	{
		pAkt = StatArray[i];

		// output it!
		if (pAkt->iCount)
			LogSilentF("%s: n = %u, t = %u, td = %.2f",
			           pAkt->strName, pAkt->iCount, pAkt->tTimeSum,
			           double(pAkt->tTimeSum) / pAkt->iCount * 1000);
	}

	// delete...
	delete[] StatArray;

	// ok. job done
	LogSilent("** Stat end");
}