// HostDnsSvs.cpp: implementation of the CHostDnsSvs class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "HostDnsSvs.h"
#include "ClientInfo.h"
#include <stdio.h>
#include <atlbase.h>
#include "SockUtil.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CHostDnsSvs::CHostDnsSvs()
{
//The class used by the main thread/message queue to dynamically create the class objects
//once required from a client
m_nClassID=HOST_DNS_SVS_SOCKET;
//3 lengthy requests will be processed using worker thread/message queues
m_pMethodIDs[0]=HOST_DNS_SVS_METHOD_ID_GETDNSNAME_BYNAME;
m_pMethodIDs[1]=HOST_DNS_SVS_METHOD_ID_GET_CLIENTS;
m_pMethodIDs[2]=HOST_DNS_SVS_METHOD_ID_GETDNSNAME_BYADDR;
//The first thread/queue uses the function, GetHostByNameProc,
//to process two requests, HOST_DNS_SVS_METHOD_ID_GETDNSNAME_BYNAME
//and HOST_DNS_SVS_METHOD_ID_GET_CLIENTS
m_pHostThreadInfo[0].m_pSlowProcess=GetHostByNameProc;
m_pHostThreadInfo[0].m_pMethodIDs=m_pMethodIDs;
m_pHostThreadInfo[0].m_nCountOfMethods=2;
//The 2nd thread/message queue uses the function GetHostByIPAddrProc,
//to process one request, HOST_DNS_SVS_METHOD_ID_GETDNSNAME_BYADDR only
m_pHostThreadInfo[1].m_pSlowProcess=GetHostByIPAddrProc;
m_pHostThreadInfo[1].m_nCountOfMethods=1;
m_pHostThreadInfo[1].m_pMethodIDs=(m_pMethodIDs+2);
//set the pointer m_pSockThreadInfo to the 2 thread info structues
m_pSockThreadInfo=m_pHostThreadInfo;
//2 worker thread/message queues will be involved totally
m_nCountOfThreadInfos=2;
}
bool CHostDnsSvs::QuickProcess(SockMethodID nMethodID)
{
switch (nMethodID)
{
case HOST_DNS_SVS_METHOD_ID_GET_COUNT_CLIENTS:
return GetCountClients(); //always true
break;
case HOST_DNS_SVS_METHOD_ID_GET_CLIENTS:
//true or fase
//if true, the request is processed using main thread/queue
//if not, it is processed using worker thread/message queue
return GetClients();
break;
default:
break;
}
return false;
}
HRESULT CHostDnsSvs::GetHostByNameProc(SOCKET hSocket, SockMethodID nMethodID, void *pBuffer, DWORD nBufferLen, void* pSockWithThread)
{
const hostent* pHost;
CStreamHeader StreamHeader;
CPacking Packing;
HWND hWnd=g_pSocketSvr->GetWnd();
CHostDnsSvs DnsSvs;
DnsSvs.m_hSocket=hSocket;
char *strName=NULL;
if(nBufferLen)
{
strName = new char [nBufferLen+1];
memcpy(strName, pBuffer, nBufferLen);
strName[nBufferLen]=0;
// ATLTRACE("IP Name = %s\n", strName);
}
Packing.Empty();
switch (nMethodID)
{
case HOST_DNS_SVS_METHOD_ID_GETDNSNAME_BYNAME:
pHost=DnsSvs.GetHostByName(strName, true);
if(strName)
{
delete []strName;
strName=NULL;
}
if(pHost)
{
char *strIP;
UINT nIndex=0;
Packing.Pack(pHost->h_name, strlen(pHost->h_name));
Packing.Pack(";", 1);
if(pHost->h_aliases[0] && strlen(pHost->h_aliases[0]))
Packing.Pack(pHost->h_name, strlen(pHost->h_name));
do
{
strIP=pHost->h_addr_list[nIndex];
if(strIP)
{
strIP=inet_ntoa(*((in_addr*)(pHost->h_addr_list[nIndex])));
if(strlen(strIP))
{
Packing.Pack(";", 1);
Packing.Pack(strIP, strlen(strIP));
}
else
break;
nIndex++;
}
else
break;
}while(true);
StreamHeader.m_nLen=Packing.m_nLen;
StreamHeader.m_nValue=HOST_DNS_SVS_METHOD_ID_GETDNSNAME_BYNAME;
//ALWAYS ALWAYS ALWAYS put the header info at the very beginning
//client will use the header info for determining method id, error info and data size in bytes
Packing.Insert(0, &StreamHeader, sizeof(StreamHeader));
}
else
{
StreamHeader.m_nLen=0;
StreamHeader.m_nValue=CAsySocket::GetLastError()+Sock_ErrorOffsetSvr;
Packing.Pack(&StreamHeader, sizeof(StreamHeader));
}
break;
case HOST_DNS_SVS_METHOD_ID_GET_CLIENTS:
{
SOCKADDR_IN sockAddr;
int nLen;
UINT nIndex;
CAsySocketClient *pClient;
CClientInfo ClientInfo;
UINT nCount=g_pSocketSvr->GetClientCount();
for(nIndex=0; nIndex<nCount; nIndex++)
{
nLen=sizeof(sockAddr);
pClient=g_pSocketSvr->GetClient(nIndex);
pClient->GetPeerName((SOCKADDR*)(&sockAddr), &nLen);
ClientInfo.m_nPort=ntohs(sockAddr.sin_port);
ClientInfo.m_nIPAddr=*((unsigned long*)&(sockAddr.sin_addr));
Packing.Pack(&ClientInfo, sizeof(ClientInfo));
}
StreamHeader.m_nLen=nCount*sizeof(CClientInfo);
StreamHeader.m_nValue=HOST_DNS_SVS_METHOD_ID_GET_CLIENTS;
Packing.Insert(0, &StreamHeader, sizeof(StreamHeader));
}
break;
default:
ATLASSERT(FALSE); //should n't come to here
}
DnsSvs.SendBigChunk(Packing.m_pBuffer, Packing.m_nLen);
return StreamHeader.m_nValue;
}
HRESULT CHostDnsSvs::GetHostByIPAddrProc(SOCKET hSocket, SockMethodID nMethodID, void *pBuffer, DWORD nBufferLen, void* pSockWithThread)
{
char strAddr[2048]={0};
char strBuffer[2048]={0};
ATLASSERT(nMethodID==HOST_DNS_SVS_METHOD_ID_GETDNSNAME_BYADDR);
ATLASSERT(nBufferLen);
CPacking Packing;
CStreamHeader StreamHeader;
HWND hWnd=g_pSocketSvr->GetWnd();
CHostDnsSvs DnsSvs;
DnsSvs.m_hSocket=hSocket;
memcpy(strAddr, pBuffer, nBufferLen);
// ATLTRACE("IP Addr = %s\n", strAddr);
const hostent* pHost=DnsSvs.GetHostByAddr(strAddr, PF_INET, true);
Packing.Empty();
if(!pHost)
{
StreamHeader.m_nLen=0;
StreamHeader.m_nValue=CAsySocket::GetLastError()+Sock_ErrorOffsetSvr;
}
else
{
sprintf(strBuffer, "%s;%s;%s", pHost->h_name, pHost->h_aliases[0], inet_ntoa(*((in_addr*)(pHost->h_addr_list[0]))));
Packing.Pack(strBuffer, strlen(strBuffer));
StreamHeader.m_nLen=strlen(strBuffer);
StreamHeader.m_nValue=HOST_DNS_SVS_METHOD_ID_GETDNSNAME_BYADDR;
}
Packing.Insert(0, &StreamHeader, sizeof(StreamHeader));
DnsSvs.SendBigChunk(Packing.m_pBuffer, Packing.m_nLen);
return StreamHeader.m_nValue;
}
bool CHostDnsSvs::GetCountClients()
{
//Use CPacking
CPacking Packing;
DWORD dwCount=g_pSocketSvr->GetClientCount();
m_StreamHeader.m_nLen=sizeof(DWORD);
m_StreamHeader.m_nValue=HOST_DNS_SVS_METHOD_ID_GET_COUNT_CLIENTS;
Packing.Pack(&m_StreamHeader, sizeof(m_StreamHeader));
Packing.Pack(&dwCount, sizeof(dwCount));
SendBigChunk(Packing.m_pBuffer, Packing.m_nLen);
return true;
}
bool CHostDnsSvs::GetClients()
{
SOCKADDR_IN sockAddr;
int nLen;
UINT nIndex;
CAsySocketClient *pClient;
BYTE *pByte;
CClientInfo *pClientInfo;
UINT nCount=g_pSocketSvr->GetClientCount();
if(nCount>(8*1024/sizeof(CClientInfo)))
//tells the main thread/queue that it is better to user a worker
//thread/message queue to process if too many clients at run time
return false;
pByte=new BYTE[sizeof(m_StreamHeader)+sizeof(CClientInfo)*nCount];
pClientInfo = (CClientInfo*)(pByte+sizeof(m_StreamHeader));
for(nIndex=0; nIndex<nCount; nIndex++)
{
nLen=sizeof(sockAddr);
pClient=g_pSocketSvr->GetClient(nIndex);
pClient->GetPeerName((SOCKADDR*)(&sockAddr), &nLen);
pClientInfo[nIndex].m_nPort=ntohs(sockAddr.sin_port);
pClientInfo[nIndex].m_nIPAddr=*((unsigned long*)&(sockAddr.sin_addr));
}
m_StreamHeader.m_nLen=nCount*sizeof(CClientInfo);
m_StreamHeader.m_nValue=HOST_DNS_SVS_METHOD_ID_GET_CLIENTS;
memcpy(pByte, &m_StreamHeader, sizeof(m_StreamHeader));
SendBigChunk(pByte, m_StreamHeader.m_nLen+sizeof(m_StreamHeader));
delete []pByte;
return true;
}