352 lines
9.2 KiB
C++
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;
|
|
}
|
|
}
|