eMule 49b. TK4 Mod 2.2b




A code optimize in the TK4 MOD from version 2.0c, (based on eMule 47c), this page contains information originally posted to the eMule forum at that time.


eMule Version: 0.47c, 0.48a
Files changed: ClientUDPSocket.cpp and UDPSocket.cpp

eMule Forum Discussion thread entry point      account required,(free)
eMule Forum Discussion thread entry point      account required,(free)


I was doing some profiling... cool.gif When I noted that in CClientUDPSocket::SendTo() ipstr() took, what I believed to be, an excessive execution time for what it did. So, I looked at the code,(see the current code below). ipstr() returns a CString object and for eMule that's a CStringT object. Now CString objects seem expensive to me anyway, but when I looked at int CAsyncSocket::SendTo(const void* lpBuf, int nBufLen, UINT nHostPort, LPCTSTR lpszHostAddress, int nFlags) I found the first thing it does to our newly created TChar CString is convert it to an ASCII string, it then takes that ASCII string and with inet_addr(lpszAscii); turns it back to the uint32 value we started with in dwIP!!
Finally it makes a call to SendTo(lpBuf, nBufLen, (SOCKADDR*)&sockAddr, sizeof(sockAddr), nFlags);

Note: The INADDR_NONE error returned by inet_addr() has the value 0xffffffff which equals 255.255.255.255, the limited broadcast address,(INADDR_BROADCAST). Therefore passing 255.255.255.255/INADDR_BROADCAST would result in an error being returned by int CAsyncSocket::SendTo(const void* lpBuf, int nBufLen, UINT nHostPort, LPCTSTR lpszHostAddress, int nFlags).


The code as is (47c/48a):
CODE:  Original CClientUDPSocket::SendTo()
int CClientUDPSocket::SendTo(char* lpBuf,int nBufLen,uint32 dwIP, uint16 nPort){
// NOTE: *** This function is invoked from a *different* thread!
uint32 result = CAsyncSocket::SendTo(lpBuf,nBufLen,nPort,ipstr(dwIP));
if (result == (uint32)SOCKET_ERROR){
uint32 error = GetLastError();
if (error == WSAEWOULDBLOCK){
m_bWouldBlock = true;
return -1;
}
if (thePrefs.GetVerbose())
DebugLogError(_T("Error: Client UDP socket, failed to send data to %s:%u: %s"), ipstr(dwIP), nPort, GetErrorMessage(error, 1));
}
return 0;

}



Where the waste is...
CODE: MFC CAsyncSocket::CAsyncSocket::SendTo(const void* lpBuf, int nBufLen, UINT nHostPort, LPCTSTR lpszHostAddress, int nFlags)

// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.

int CAsyncSocket::SendTo(const void* lpBuf, int nBufLen, UINT nHostPort, LPCTSTR lpszHostAddress, int nFlags)
{
USES_CONVERSION_EX;

SOCKADDR_IN sockAddr;

memset(&sockAddr,0,sizeof(sockAddr));

LPSTR lpszAscii;
if (lpszHostAddress != NULL)
{
lpszAscii = T2A_EX((LPTSTR)lpszHostAddress, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
if (lpszAscii == NULL)
{
// OUT OF MEMORY
WSASetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
}
else
{
lpszAscii = NULL;
}

sockAddr.sin_family = AF_INET;

if (lpszAscii == NULL)
sockAddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
else
{
sockAddr.sin_addr.s_addr = inet_addr(lpszAscii);
if (sockAddr.sin_addr.s_addr == INADDR_NONE)
{
LPHOSTENT lphost;
lphost = gethostbyname(lpszAscii);
if (lphost != NULL)
sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
else
{
WSASetLastError(WSAEINVAL);
return SOCKET_ERROR;
}
}
}

sockAddr.sin_port = htons((u_short)nHostPort);

return SendTo(lpBuf, nBufLen, (SOCKADDR*)&sockAddr, sizeof(sockAddr), nFlags);
}




What the waste is...      Note: bold purple indicates the code retained to form the optimizated replacement for this function.
CODE: MFC CAsyncSocket::CAsyncSocket::SendTo(const void* lpBuf, int nBufLen, UINT nHostPort, LPCTSTR lpszHostAddress, int nFlags)Annotated version

// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.

int CAsyncSocket::SendTo(const void* lpBuf, int nBufLen, UINT nHostPort, LPCTSTR lpszHostAddress, int nFlags)
{
USES_CONVERSION_EX;

SOCKADDR_IN sockAddr; <- Retained

memset(&sockAddr,0,sizeof(sockAddr)); <- Retained


LPSTR lpszAscii;
if (lpszHostAddress != NULL)
{
lpszAscii = T2A_EX((LPTSTR)lpszHostAddress, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
if (lpszAscii == NULL)
{
// OUT OF MEMORY
WSASetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
}
else
{
lpszAscii = NULL;
}


^^^^^ Above String conversion only

sockAddr.sin_family = AF_INET; <- Retained

if (lpszAscii == NULL) <- To deal with and empty string being passed, can never happen with the original code
sockAddr.sin_addr.s_addr = htonl(INADDR_BROADCAST); <--- Why htonl?? #define INADDR_BROADCAST (u_long)0xffffffff confused.gif
else
{
sockAddr.sin_addr.s_addr = inet_addr(lpszAscii); <--- ***THIS LINE Returns the value dwIP !!!
if (sockAddr.sin_addr.s_addr == INADDR_NONE) <--- Deals with an error returned by inet_addr() BUT also could occur if INADDR_BROADCAST address is passed!!
{
LPHOSTENT lphost;
lphost = gethostbyname(lpszAscii);
<-- A check to see if a host name had been passed in the original string, not applicable to our code
if (lphost != NULL)
sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
else
{
WSASetLastError(WSAEINVAL); <-- Just added to the optimize for 255.255.255.255
return SOCKET_ERROR;
}
}
}

sockAddr.sin_port = htons((u_short)nHostPort); <--- Retained

return SendTo(lpBuf, nBufLen, (SOCKADDR*)&sockAddr, sizeof(sockAddr), nFlags); <--- Call Retained
}




Optimized code
CODE: My optimized version of CClientUDPSocket::SendTo()
int CClientUDPSocket::SendTo(char* lpBuf,int nBufLen,uint32 dwIP, uint16 nPort){
// NOTE: *** This function is invoked from a *different* thread!
//TK4 MOD 2.0c - Save converting dwIP from uint32 to a CStringT to ASCII then back to uint32

if(dwIP == INADDR_BROADCAST)
{
WSASetLastError(WSAEINVAL);
if (thePrefs.GetVerbose())
DebugLogError(_T("Error: Client UDP socket, failed to send data to %s:%u: %s"), ipstr(dwIP), nPort, GetErrorMessage(WSAEINVAL, 1));
return 0;
}

SOCKADDR_IN sockAddr;
memset(&sockAddr, 0,sizeof(sockAddr));
sockAddr.sin_family = AF_INET;
sockAddr.sin_addr.s_addr = dwIP;
sockAddr.sin_port = htons((u_short)nPort);

uint32 result = CAsyncSocket::SendTo(lpBuf, nBufLen, (SOCKADDR*)&sockAddr, sizeof(sockAddr), 0);


// uint32 result = CAsyncSocket::SendTo(lpBuf,nBufLen,nPort,ipstr(dwIP));

if (result == (uint32)SOCKET_ERROR){
uint32 error = GetLastError();
if (error == WSAEWOULDBLOCK){
m_bWouldBlock = true;
return -1;
}
if (thePrefs.GetVerbose())
DebugLogError(_T("Error: Client UDP socket, failed to send data to %s:%u: %s"), ipstr(dwIP), nPort, GetErrorMessage(error, 1));
}
return 0;
}



Optimized code
CODE: The same optimize can be applied to CUDPSocket::SendTo()
int CUDPSocket::SendTo(BYTE* lpBuf, int nBufLen, uint32 dwIP, uint16 nPort)
{
// NOTE: *** This function is invoked from a *different* thread!
//TK4 MOD 2.0c - Save converting dwIP from uint32 to a CStringT to ASCII then back to uint32

if(dwIP == INADDR_BROADCAST)
{
WSASetLastError(WSAEINVAL);
if (thePrefs.GetVerbose())
DebugLogError(_T("Error: Client UDP socket, failed to send data to %s:%u: %s"), ipstr(dwIP), nPort, GetErrorMessage(WSAEINVAL, 1));
return 0;
}

SOCKADDR_IN sockAddr;
memset(&sockAddr, 0,sizeof(sockAddr));
sockAddr.sin_family = AF_INET;
sockAddr.sin_addr.s_addr = dwIP;
sockAddr.sin_port = htons((u_short)nPort);

int iResult = CAsyncSocket::SendTo(lpBuf, nBufLen, (SOCKADDR*)&sockAddr, sizeof(sockAddr), 0);


//int iResult = CAsyncSocket::SendTo(lpBuf, nBufLen, nPort, ipstr(dwIP));
if (iResult == SOCKET_ERROR) {
DWORD dwError = GetLastError();
if (dwError == WSAEWOULDBLOCK) {
m_bWouldBlock = true;
return -1; // blocked
}
else{
if (thePrefs.GetVerbose())
theApp.QueueDebugLogLine(false, _T("Error: Server UDP socket: Failed to send packet to %s:%u - %s"), ipstr(dwIP), nPort, GetErrorMessage(dwError, 1));
return 0; // error
}
}
return 1; // success
}