JD2022-TU1/main/extern/Camcam/LIBS/Net/NET_io.cpp

352 lines
9.2 KiB
C++

#include <windows.h>
#include <stdio.h>
#include "NET.h"
#define RATE_UP_MIN (30*1024) // 10ko/s
#define RATE_UP_MAX (200*1024) // 10ko/s
/*
===================================================================================================
===================================================================================================
RATE CONTROL
===================================================================================================
===================================================================================================
*/
__declspec(naked)
unsigned __int64 __cdecl read_time(void)
{
__asm
{
rdtsc
ret ; return value at EDX:EAX
}
}
u64 NET_IO::ACCURATE_GetTime()
{
if (ACCURATE_OneMLS == 0)
{
u64 RdtscTimeBase,RdtscTimeEnd;
u32 TimeBase,DT,RdtscDT;
TimeBase = timeGetTime();
RdtscTimeBase = read_time();
DT = 0;
while (DT < 200) {DT = timeGetTime() - TimeBase;};
RdtscTimeEnd = read_time();
RdtscDT = (u32)((RdtscTimeEnd - RdtscTimeBase)>>16);
ACCURATE_OneMLS = RdtscDT / DT;
}
return read_time() >> 16;
}; // 1/1000 s
u32 NET_IO::CanSend(u32 Size)
{
u64 T;
u32 DT;
u32 SendedSinceLastCall;
T = ACCURATE_GetTime();
DT = (u32)(T - ACCURATE_LastTimeSend);
SendedSinceLastCall = (RATE_UP * DT) / (1000 * ACCURATE_OneMLS);
if (SendedSinceLastCall > DataToFlush)
DataToFlush = 0;
else
DataToFlush -= SendedSinceLastCall;
ACCURATE_LastTimeSend = T;
if (Size + DataToFlush <= RATE_UP_BUFFERRIZEMAX)
{
return 1;// OK I Can Send
}
else
{
NeedMoreUpD = 1;
return 0;
}
}
void NET_IO::RateControl()
{
/* Upload rate control */
if (RatingDT > 4000) RatingDT = 4000;
if (RatingDT < 500) RatingDT = 500;
if (timeGetTime() - LastTimeSendToWorld > 1000)
{
/* Send the LINK Message */
OneBuf ToSend;
*((u32 *)ToSend.BufDATA) = 'LINK';
ToSend.SetIP(NET_IO_IP_WORLD,MyPort);
memcpy(&ToSend.BufDATA[4],MyComputerName,256);
ToSend.Size = 4 + 256;
NET_DataSend(&ToSend);//*/
}
if ((timeGetTime() - LastTimCheck)>RatingDT)
{
static u32 TESTKKJ = 0;
u32 Counter;
Counter = 32;
while (Counter--)
if (ValidMask & (1<<Counter))
{
/* if (timeGetTime() - LinkedIP[Counter].LastConnectionTime > 3000)
{
UnLinkToIP(LinkedIP[Counter].ulIP,LinkedIP[Counter].Port);
} else*/
if (timeGetTime() - LinkedIP[Counter].LastConnectionTime > 3000)
{
UnLinkToIP(LinkedIP[Counter].ulIP,LinkedIP[Counter].Port);
} else
if (LinkedIP[Counter].LostPackets * 100 / (LinkedIP[Counter].LostPackets + LinkedIP[Counter].GoodPackets) > 2)
{
/* Send the cool Message */
OneBuf ToSend;
((u32 *)ToSend.BufDATA)[0] = htonl ( 'COOL' );
((u32 *)ToSend.BufDATA)[1] = htonl ( LinkedIP[Counter].ulIP );
ToSend.SetIP(NET_IO_IP_WORLD,MyPort);
ToSend.Size = 8;
NET_DataSend(&ToSend);
CoolNotifycation++;
}
}
if ((TESTKKJ & 0x3f) == 0)
{
/* Send the LINK Message */
OneBuf ToSend;
*((u32 *)ToSend.BufDATA) = 'LINK';
ToSend.SetIP(NET_IO_IP_WORLD,MyPort);
memcpy(&ToSend.BufDATA[4],MyComputerName,256);
ToSend.Size = 4 + 256;
NET_DataSend(&ToSend);//*/
}
TESTKKJ++;
LastTimCheck = timeGetTime() - LastTimCheck;
ACTUAL_RATE_UP = ((UploadCheck * 1000) / LastTimCheck);
ACTUAL_RATE_DOWN = ((DownLoadCheck * 1000) / LastTimCheck);
if (CoolNotifycation)
{
RATE_UP -= 20 * 1024;
RatingDT += RatingDT;
}
else
{
if (NeedMoreUpD)
{
NeedMoreUpD = 0;
RatingDT -= 10;
RATE_UP += 5 * 1024;
}
}//*/
if (RATE_UP > ACTUAL_RATE_DOWN + (ACTUAL_RATE_DOWN >> 1)) RATE_UP = ACTUAL_RATE_DOWN + (ACTUAL_RATE_DOWN >> 1);
if (RATE_UP < RATE_UP_MIN) RATE_UP = RATE_UP_MIN;
//if (RATE_UP > RATE_UP_MAX) RATE_UP = RATE_UP_MAX;
CoolNotifycation = 0;
UploadCheck = 0;
DownLoadCheck = 0;
LastTimCheck = timeGetTime();
}
}
/*
===================================================================================================
===================================================================================================
RECEIVE - SEND
===================================================================================================
===================================================================================================
*/
/*
s32 MY_SENDTO(SOCKET s,const char FAR * buf,int len,int flags,const struct sockaddr FAR *to,int tolen)
{return sendto(s,buf,len,flags,to,tolen);};
s32 MY_RECEIVE(SOCKET s,char FAR * buf,int len,int flags,struct sockaddr FAR *from,int FAR * fromlen)
{return recvfrom(s,buf,len,flags,from,fromlen);};
*/
void NET_IO::ReadLoadData()
{
if (WAIT_OBJECT_0 == WaitForSingleObject(InputData.AccesMutex, INFINITE))
{
int c;
int fromlen;
do {
static u32 PacketNumber1 = 0;
OneBuf *ToSet;
ToSet = InputData.THREAD_STACK.Get();
if (!ToSet)
{
OneBuf ToSend;
*((u32 *)ToSend.BufDATA) = 0;
// Here mean I can't handle all the receipted message
// " My PC is too slow "
// Should notify here "slower" message to others.
// Proportionnaly to stack percentage IP
// My THREAD STACK is Empty
// So I fill the oldest buffer stored in APPI_STACK
// to keep API more "fresh" data.
/* Parse IP to find the older */
u32 Counter = 32;
u32 MaxNumber;
MaxNumber = 0;
while (Counter --)
{
if (LinkedIP[Counter].Number > LinkedIP[MaxNumber].Number)
{
MaxNumber = Counter;
}
}
LinkedIP[MaxNumber].GetNextPacket(NULL,this);
ToSet = InputData.THREAD_STACK.Get();
if (!ToSet)
{
/* BUG !! */
*(u32 *)0 = *(u32 *)4; // <- please crash
}
}
if (ToSet)
{
u32 Size;
c = 0;
fromlen = sizeof(sockaddr_in );
Size = c = recvfrom(NET_i_InSocket,(char far *) (ToSet->BufDATA),MTU_USED+5,0,(struct sockaddr *) &ToSet->Sender,&fromlen);
if ( (c != SOCKET_ERROR) && (NET_IsMyIp(ToSet->GetIP())))
InTheNet--;
if ((c >= 0) && (c < 5))
c = SOCKET_ERROR;
if (c == SOCKET_ERROR)
{
InputData.THREAD_STACK.Add(ToSet);
c = 0;
}
else
{
u32 PacketNumber;
c -= 4;
if ((ntohl(((u32 *)ToSet->BufDATA)[0]) == 'COOL') &&
(NET_IsMyIp(ntohl(((u32 *)ToSet->BufDATA)[1]))))
CoolNotifycation++;
PacketNumber = ((u32)(ToSet->BufDATA[c++])) << 0;
PacketNumber += ((u32)(ToSet->BufDATA[c++])) << 8;
PacketNumber += ((u32)(ToSet->BufDATA[c++])) << 16;
PacketNumber += ((u32)(ToSet->BufDATA[c++])) << 24;
ToSet->PacketNumber = PacketNumber;
ToSet->ReceivedTimeMS = timeGetTime();
ToSet->Size = c - 4;
if ((NET_SendToMe) && (NET_IsMyIp(ToSet->GetIP())))
ToSet->Sender.sin_addr.s_addr ^= 0x101010;
if (!NET_IsMyIp(ToSet->GetIP()))
{
DownLoadCheck += c;
AddToStat(ToSet);
}
else
/* thrash it */
InputData.THREAD_STACK.Add(ToSet);
}
}
} while (c);
ReleaseMutex(InputData.AccesMutex);
}
/* Try to flush output buffer */
if (WAIT_OBJECT_0 == WaitForSingleObject(OutputData.AccesMutex, INFINITE))
{
if (OutputData.THREAD_STACK.Number)
{
u32 OK_Continue;
do
{
u32 Err;
OneBuf *ToSend;
ToSend = OutputData.THREAD_STACK.FIFO[OutputData.THREAD_STACK.End];
if (CanSend(ToSend->Size) &&
(NET_PacketSend(&ToSend->Sender,ToSend->BufDATA, ToSend->Size)==0))
{
OutputData.APPI_STACK.Add(OutputData.THREAD_STACK.Get());
OK_Continue = OutputData.THREAD_STACK.Number;
UploadCheck += ToSend->Size;
} else
OK_Continue = 0;
}
while (OK_Continue);
}
ReleaseMutex(OutputData.AccesMutex);
}
}
/*
===================================================================================================
SEND
===================================================================================================
*/
int NET_IO::NET_PacketSend(struct sockaddr_in *_pst_Adr, void *_p_Data, int _i_Num)
{
int err;
err = sendto
(
NET_i_InSocket,
(const char far *) _p_Data,
_i_Num,
0,
(const sockaddr *) _pst_Adr,
sizeof(struct sockaddr_in)
);
/*if (err == _i_Num) */
if (err < 0) return err;
if (err == _i_Num)
{
DataToFlush += _i_Num;
}
InTheNet++;
return 0;
}
u32 NET_IO::NET_DataSend(OneBuf *pBuf)
{
u32 Ret = 0;
if ((NET_SendToMe) && (NET_IsMyIp(pBuf->GetIP() ^ 0x101010)))
pBuf->Sender.sin_addr.s_addr ^= 0x101010;
if (pBuf->GetIP() == NET_IO_IP_WORLD)
{
pBuf->SetIP(INADDR_BROADCAST);
pBuf->SetBufPort(MyPort);
LastTimeSendToWorld = timeGetTime();
};
if (WAIT_OBJECT_0 == WaitForSingleObject(OutputData.AccesMutex, INFINITE))
{
if (OutputData.APPI_STACK.Number)
{
((unsigned char *)pBuf->BufDATA)[pBuf->Size++] = (ActualPacketNumber >> 0 ) & 0xff;
((unsigned char *)pBuf->BufDATA)[pBuf->Size++] = (ActualPacketNumber >> 8 ) & 0xff;
((unsigned char *)pBuf->BufDATA)[pBuf->Size++] = (ActualPacketNumber >>16 ) & 0xff;
((unsigned char *)pBuf->BufDATA)[pBuf->Size++] = (ActualPacketNumber >>24 ) & 0xff;
OneBuf *pBufOut;
pBufOut = OutputData.APPI_STACK.Get();
memcpy(pBufOut,pBuf,sizeof(OneBuf) - (MTU_USED + 5 - pBuf->Size));
OutputData.THREAD_STACK.Add(pBufOut);
ActualPacketNumber++;
ReleaseMutex(OutputData.AccesMutex);
return 0;
}
NeedMoreUpD = 1;
ReleaseMutex(OutputData.AccesMutex);
return -1;
}
else
{
return -1;
}
}