#include #include #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< 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; } }