#include "StdAfx.h"
#include ".\socketutil.h"

#define  SOCK_TIMEOUT 5

CSocketUtil::CSocketUtil(void)
{
}

CSocketUtil::~CSocketUtil(void)
{
}

unsigned long CSocketUtil::conv_addr(const char *name)
{
	struct hostent *he;
	int max;
	unsigned long retval;

	if ((retval = inet_addr(name)) != INADDR_NONE)
		return retval;

	he = gethostbyname(name);
	if (he == NULL)
		return INADDR_NONE;

	for (max = 0; he->h_addr_list[max]; max++) ;
	if (max == 1) 
		return *((unsigned long *)(he->h_addr_list[0]));
	else 
		return *((unsigned long *)(he->h_addr_list[rand() % max]));

}


CString CSocketUtil::get_first_rcts(const char *name)
{
	struct hostent *he;
	int max;
	unsigned long retval;
	CString str_ip;
	CString sHeadOfAddress;

	if ((retval = inet_addr(name)) != INADDR_NONE)
	{
		str_ip = name;
		return str_ip;
	}

	he = gethostbyname(name);
	if (he == NULL)
		return NULL;

	for (max = 0; he->h_addr_list[max]; max++) ;

	int* end_ips = new int[max];

	for (int i=0; i<max; i++)
	{

		sockaddr_in sa; 
		sa.sin_family      = AF_INET;
		sa.sin_addr.s_addr = *((unsigned long *)(he->h_addr_list[i]));

		str_ip = inet_ntoa(sa.sin_addr);

		int lastDot = str_ip.ReverseFind('.');
		sHeadOfAddress = str_ip.Left(lastDot);
		CString sEndOfAddress = str_ip.Right(str_ip.GetLength() - lastDot -1);
		end_ips[i] = atoi(sEndOfAddress.GetString());

	}

	for (int i=0; i<max; i++)
		for (int j=0; j<max-1; j++)
			if (end_ips[j] > end_ips[j+1])
				swap(end_ips[j] , end_ips[j+1]);

	char end_ip[5];
	sprintf(end_ip , "%d" , end_ips[0]);

	CString result_ip;
	result_ip = sHeadOfAddress + "." + end_ip;

	delete end_ips;
	return result_ip;
}



int CSocketUtil::_sh_send(SOCKET s, char *pszBuf, int nLen)
{
	int iSent = 0, nSentLen;
	fd_set wset;
	struct timeval tv;

	FD_ZERO(&wset);
	FD_SET(s, &wset);
	tv.tv_sec = SOCK_TIMEOUT;
	tv.tv_usec = 0;
	do {
		if (select(static_cast<int>(s + 1), NULL, &wset, NULL, &tv) < 0) break;
		if (!FD_ISSET(s, &wset)) break;

		nSentLen = send(s, pszBuf + iSent, nLen, 0);

		iSent += nSentLen;
		nLen  -= nSentLen;
	} while (nLen > 0 && nSentLen > 0);

	return nLen > 0 ? SOCKET_ERROR : iSent;
}

int CSocketUtil::_sh_recv(SOCKET s, char *pszBuf, int nLen)
{	
	return recv(s , pszBuf , nLen , NULL);
}


int CSocketUtil::_rtxTimer(int sec , SOCKET descriptor)
{
	fd_set fdsetRead;
	fd_set fdsetWrite;
	struct timeval tv;

	FD_ZERO(&fdsetRead);
	FD_ZERO(&fdsetWrite);
	FD_SET(descriptor, &fdsetRead);
	FD_SET(descriptor, &fdsetWrite);

	tv.tv_sec = sec;
	tv.tv_usec = 0;

	return (::select(descriptor + 1, &fdsetRead, &fdsetWrite, NULL, &tv));
}

BOOL CSocketUtil::MessagePump(int nSleepDuration)
{
	MSG msg;

	if(nSleepDuration > 0)
		Sleep(nSleepDuration);

	try
	{
		while(::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
		{
			if(AfxGetApp()->PumpMessage())
				return TRUE;
		}
	}
	catch(...)
	{
	}

	return FALSE;
}