// DNS.cpp : Implementation of CDNS
#include "stdafx.h"
#include "DResolver.h"
#include "DNS.h"
#include "ClientSocket_i.c"
#include "ClientInfo.h"
#include <stdio.h>
//hard coded, see the defines in the file ..\extending\server\hostdnssvs.h
//#define HOST_DNS_SVS_SOCKET 0xA00100DD
/*typedef enum tagDResolverID
{
idGetDNSByName= 1,
idGetDNSByAddr= 2,
idGetCountClients = 3,
idGetClients = 4,
}DResolverID;*/
/////////////////////////////////////////////////////////////////////////////
// CDNS
HRESULT CDNS::RecvChunk(void *pBuffer, long *plRecv)
{
CComPtr<ISktClient> pISktClient;
HRESULT hr=S_OK;
VARIANT vtData;
VariantInit(&vtData);
do
{
void *pData;
hr=m_pIUnknown.QueryInterface(&pISktClient);
if(FAILED(hr))
break;
hr=pISktClient->RecvChunk(plRecv, 0, &vtData);
if(FAILED(hr))
break;
SAFEARRAY *psa=vtData.parray;
hr=SafeArrayAccessData(psa, &pData);
if(FAILED(hr))
break;
memcpy(pBuffer, pData, *plRecv);
SafeArrayUnaccessData(psa);
}while(false);
VariantClear(&vtData);
if(!FAILED(hr))
hr=S_OK;
return hr;
}
HRESULT CDNS::SendChunk(void *pBuffer, long nSize, long *plSent)
{
CComPtr<ISktClient> pISktClient;
HRESULT hr=S_OK;
VARIANT vtData;
VariantInit(&vtData);
do
{
void *pData;
hr=m_pIUnknown.QueryInterface(&pISktClient);
if(FAILED(hr))
break;
SAFEARRAYBOUND bound;
bound.cElements=nSize;
bound.lLbound=0;
vtData.vt=VT_ARRAY|VT_UI1;
SAFEARRAY *psa=SafeArrayCreate(VT_UI1, 1, &bound);
hr=SafeArrayAccessData(psa, &pData);
if(FAILED(hr))
break;
memcpy(pData, pBuffer, nSize);
SafeArrayUnaccessData(psa);
vtData.parray=psa;
hr=pISktClient->SendChunk(vtData, 0, plSent);
}while(false);
VariantClear(&vtData);
if(!FAILED(hr))
hr=S_OK;
return hr;
}
STDMETHODIMP CDNS::GetClients()
{
CStreamHeader StreamHeader;
BYTE *pBuffer=NULL;
StreamHeader.m_nValue=idGetClients;
CComPtr<ISktClient> pISktClient;
Lock();
do
{
long lSent=0;
long lEvents;
m_hrDNS=SendChunk(&StreamHeader, sizeof(StreamHeader), &lSent);
if(FAILED(m_hrDNS))
break;
m_hrDNS=m_pIUnknown.QueryInterface(&pISktClient);
if(FAILED(m_hrDNS))
break;
pISktClient->get_Events(&lEvents);
if((lEvents & FD_READ) != FD_READ) //if blocking mode used
{
UINT nCount;
long lRecv=sizeof(StreamHeader);
m_hrDNS=RecvChunk(&StreamHeader, &lRecv);
if(FAILED(m_hrDNS))
break;
if(FAILED(StreamHeader.m_nValue))
break;
pBuffer=new BYTE[StreamHeader.m_nLen];
lRecv=StreamHeader.m_nLen;
m_hrDNS=RecvChunk(pBuffer, &lRecv);
if(FAILED(m_hrDNS))
break;
if(m_bstrClients)
{
::SysFreeString(m_bstrClients);
m_bstrClients=NULL;
}
ATLASSERT((lRecv%sizeof(CClientInfo))==0);
nCount=lRecv/sizeof(CClientInfo);
if(nCount)
{
CComBSTR bstrClients;
for(UINT n=0; n<nCount; n++)
{
BYTE *p=pBuffer+n*sizeof(CClientInfo);
CClientInfo* pInfo=(CClientInfo*)p;
{
char strTemp[50]={0};
unsigned short nPort=pInfo->m_nPort;
if(n)
sprintf(strTemp, ",%s:%d", inet_ntoa(*((in_addr*)&(pInfo->m_nIPAddr))), nPort);
else
sprintf(strTemp, "%s:%d", inet_ntoa(*((in_addr*)&(pInfo->m_nIPAddr))), nPort);
bstrClients +=CComBSTR(strTemp);
}
}
m_bstrClients=bstrClients.m_str;
bstrClients.m_str=NULL;
}
}
}while(false);
if(pBuffer)
delete []pBuffer;
Unlock();
return m_hrDNS;
}
STDMETHODIMP CDNS::GetCountClients()
{
CStreamHeader StreamHeader;
StreamHeader.m_nValue=idGetCountClients;
CComPtr<ISktClient> pISktClient;
Lock();
do
{
long lSent=0;
long lEvents=0;
m_hrDNS=SendChunk(&StreamHeader, sizeof(StreamHeader), &lSent);
if(FAILED(m_hrDNS))
break;
m_hrDNS=m_pIUnknown.QueryInterface(&pISktClient);
if(FAILED(m_hrDNS))
break;
pISktClient->get_Events(&lEvents);
if((lEvents & FD_READ) != FD_READ) //if blocking mode used
{
USES_CONVERSION;
long lRecv=sizeof(StreamHeader);
m_hrDNS=RecvChunk(&StreamHeader, &lRecv);
if(FAILED(m_hrDNS))
break;
if(FAILED(StreamHeader.m_nValue))
break;
ATLASSERT(StreamHeader.m_nLen==sizeof(m_lCount));
lRecv=sizeof(m_lCount);
m_hrDNS=RecvChunk(&m_lCount, &lRecv);
if(FAILED(m_hrDNS))
break;
}
}while(false);
Unlock();
return m_hrDNS;
}
STDMETHODIMP CDNS::GetDnsByName(BSTR bstrName)
{
CStreamHeader StreamHeader;
StreamHeader.m_nValue=idGetDNSByName;
CComPtr<ISktClient> pISktClient;
Lock();
m_hrDNS=S_OK;
do
{
USES_CONVERSION;
long nLen=0;
long lEvents=0;
CPacking Packing;
if(!bstrName|| (nLen=::SysStringLen(bstrName))==0)
{
m_hrDNS=E_UNEXPECTED;
break;
}
StreamHeader.m_nLen=nLen;
Packing.Pack(&StreamHeader, sizeof(StreamHeader));
Packing.Pack(OLE2A(bstrName), nLen);
m_hrDNS=SendChunk(Packing.m_pBuffer, Packing.m_nLen, &nLen);
if(FAILED(m_hrDNS))
break;
m_hrDNS=m_pIUnknown.QueryInterface(&pISktClient);
if(FAILED(m_hrDNS))
break;
pISktClient->get_Events(&lEvents);
if((lEvents & FD_READ) != FD_READ) //if blocking mode used, we need to process it now
{
USES_CONVERSION;
long lRecv=sizeof(StreamHeader);
m_hrDNS=RecvChunk(&StreamHeader, &lRecv);
if(FAILED(m_hrDNS))
break;
if(FAILED(StreamHeader.m_nValue))
{
m_hrDNS=StreamHeader.m_nValue;
break;
}
if(m_bstrHostEnt)
{
::SysFreeString(m_bstrHostEnt);
m_bstrHostEnt=NULL;
}
lRecv=StreamHeader.m_nLen;
if(lRecv)
{
char *strBuffer=new char[lRecv+1];
m_hrDNS=RecvChunk(strBuffer, &lRecv);
if(FAILED(m_hrDNS))
{
delete []strBuffer;
break;
}
strBuffer[lRecv]=0;
m_bstrHostEnt=A2BSTR(strBuffer);
delete []strBuffer;
}
}
}while(false);
Unlock();
return m_hrDNS;
}
STDMETHODIMP CDNS::GetDnsByAddr(BSTR bstrAddr)
{
CStreamHeader StreamHeader;
StreamHeader.m_nValue=idGetDNSByAddr;
CComPtr<ISktClient> pISktClient;
Lock();
m_hrDNS=S_OK;
do
{
USES_CONVERSION;
long nLen=0;
long lEvents=0;
CPacking Packing;
if(!bstrAddr|| (nLen=::SysStringLen(bstrAddr))==0)
{
m_hrDNS=E_UNEXPECTED;
break;
}
StreamHeader.m_nLen=nLen;
Packing.Pack(&StreamHeader, sizeof(StreamHeader));
Packing.Pack(OLE2A(bstrAddr), nLen);
m_hrDNS=SendChunk(Packing.m_pBuffer, Packing.m_nLen, &nLen);
if(FAILED(m_hrDNS))
break;
m_hrDNS=m_pIUnknown.QueryInterface(&pISktClient);
if(FAILED(m_hrDNS))
break;
pISktClient->get_Events(&lEvents);
if((lEvents & FD_READ) != FD_READ) //if blocking mode used, we need to process it now
{
USES_CONVERSION;
long lRecv=sizeof(StreamHeader);
m_hrDNS=RecvChunk(&StreamHeader, &lRecv);
if(FAILED(m_hrDNS))
break;
if(FAILED(StreamHeader.m_nValue))
{
m_hrDNS=StreamHeader.m_nValue;
break;
}
if(m_bstrHostEnt)
{
::SysFreeString(m_bstrHostEnt);
m_bstrHostEnt=NULL;
}
lRecv=StreamHeader.m_nLen;
if(lRecv)
{
char *strBuffer=new char[lRecv+1];
m_hrDNS=RecvChunk(strBuffer, &lRecv);
if(FAILED(m_hrDNS))
{
delete []strBuffer;
break;
}
strBuffer[lRecv]=0;
m_bstrHostEnt=A2BSTR(strBuffer);
delete []strBuffer;
}
}
}while(false);
Unlock();
return m_hrDNS;
}
STDMETHODIMP CDNS::GetHostEnt(BSTR *pbstrHostEnt)
{
Lock();
if(!pbstrHostEnt)
{
m_hrDNS=E_UNEXPECTED;
Unlock();
return m_hrDNS;
}
m_hrDNS=S_OK;
if(m_bstrHostEnt)
*pbstrHostEnt=::SysAllocString(m_bstrHostEnt);
Unlock();
return S_OK;
}
STDMETHODIMP CDNS::Clients(BSTR *pbstrClients)
{
Lock();
if(!pbstrClients)
{
m_hrDNS=E_UNEXPECTED;
Unlock();
return m_hrDNS;
}
m_hrDNS=S_OK;
if(m_bstrClients)
*pbstrClients=::SysAllocString(m_bstrClients);
Unlock();
return S_OK;
}
STDMETHODIMP CDNS::Count(long *plCount)
{
Lock();
if(!plCount)
{
m_hrDNS=E_UNEXPECTED;
Unlock();
return m_hrDNS;
}
m_hrDNS=S_OK;
*plCount=m_lCount;
Unlock();
return S_OK;
}
STDMETHODIMP CDNS::AttachSocket(IUnknown *pIUnknown)
{
CComPtr<ISktClient> pISktClient;
CComPtr<IDResolver> pIDResolver;
VARIANT_BOOL bIsConnected;
VARIANT_BOOL bDNSClient;
long hSocket=INVALID_SOCKET;
long hWnd=NULL;
Lock();
if(!pIUnknown)
{
m_hrDNS=E_UNEXPECTED;
Unlock();
return E_UNEXPECTED;
}
pIUnknown->QueryInterface(__uuidof(ISktClient), (void**)&pISktClient);
if(!pISktClient.p)
{
m_hrDNS=E_UNEXPECTED;
Unlock();
return E_UNEXPECTED;
}
m_hrDNS=pIUnknown->QueryInterface(&pIDResolver);
if(!FAILED(m_hrDNS))
{
bDNSClient=VARIANT_TRUE;
CComPtr<IUnknown> pIUnknown;
QueryInterface(__uuidof(IUnknown), (void**)&pIUnknown);
if(pIUnknown.p && pIUnknown.IsEqualObject(pIUnknown))
{
m_hrDNS=E_UNEXPECTED;
Unlock();
return E_UNEXPECTED;
}
}
else
bDNSClient=VARIANT_FALSE;
m_hrDNS=m_ClientSocketEvent.DispEventUnadvise(m_pIUnknown.p);
if(m_pIUnknown.p)
m_pIUnknown.Release();
m_pIUnknown.p=pIUnknown;
pIUnknown->AddRef();
m_pIUnknownClientSocket=m_pIUnknown.p;
m_pIUnknownForPointContainer=m_pIUnknown.p;
m_hrDNS=m_ClientSocketEvent.DispEventAdvise(m_pIUnknown.p);
if(FAILED(m_hrDNS))
{
Unlock();
return m_hrDNS;
}
pISktClient->get_WinHandle(&hWnd);
m_hWnd=hWnd;
pISktClient->get_SocketHandle(&m_hSocket);
if(bDNSClient==VARIANT_FALSE)
{
if(pISktClient->get_IsConnected(&bIsConnected)==S_OK && bIsConnected)
{
//SwitchTo call is blocking one
m_hrDNS=pISktClient->SwitchTo(CREATE_START_SOCK_CLIENT);
m_hrDNS=pISktClient->SwitchTo(0xA00100DDL);
}
}
Unlock();
return m_hrDNS;
}
HRESULT __stdcall CDNS::OnGetHostByAddr(LONG nHandle, BSTR bstrHostName, BSTR bstrHostAlias, LONG lError)
{
return Fire_OnGetHostByAddr(nHandle, bstrHostName, bstrHostAlias, lError);
}
HRESULT __stdcall CDNS::OnGetHostByName(LONG hHandle, BSTR bstrHostName, BSTR bstrAlias, BSTR bstrIPAddr, LONG lError)
{
return Fire_OnGetHostByName(hHandle, bstrHostName, bstrAlias, bstrIPAddr, lError);
}
HRESULT __stdcall CDNS::OnDataAvailable(long hSocket, long lBytes, long lError)
{
CStreamHeader StreamHeader;
aa: if(lBytes>=sizeof(StreamHeader))
{
Lock();
do
{
long lRecv=sizeof(StreamHeader);
m_hrDNS=RecvChunk(&StreamHeader, &lRecv);
lBytes -=lRecv;
m_hrDNS=lError=StreamHeader.m_nValue;
if(FAILED(m_hrDNS))
break;
if(StreamHeader.m_nLen)
{
USES_CONVERSION;
lRecv=StreamHeader.m_nLen;
switch (lError)
{
case idGetDNSByAddr:
case idGetDNSByName:
{
char *str=new char [lRecv+1];
m_hrDNS=RecvChunk(str, &lRecv);
ATLASSERT(lRecv);
str[lRecv]=0;
if(m_bstrHostEnt)
::SysFreeString(m_bstrHostEnt);
m_bstrHostEnt=A2BSTR(str);
delete []str;
}
break;
case idGetCountClients:
ATLASSERT(StreamHeader.m_nLen=sizeof(m_lCount));
m_hrDNS=RecvChunk(&m_lCount, &lRecv);
break;
case idGetClients:
{
UINT nCount;
BYTE *pBuffer=new BYTE[lRecv];
m_hrDNS=RecvChunk(pBuffer, &lRecv);
if(FAILED(m_hrDNS))
break;
ATLASSERT((lRecv%sizeof(CClientInfo))==0);
nCount=lRecv/sizeof(CClientInfo);
if(nCount)
{
CComBSTR bstrClients;
for(UINT n=0; n<nCount; n++)
{
BYTE *p=pBuffer+n*sizeof(CClientInfo);
CClientInfo* pInfo=(CClientInfo*)p;
{
char strTemp[50]={0};
unsigned short nPort=pInfo->m_nPort;
if(n)
sprintf(strTemp, ",%s:%d", inet_ntoa(*((in_addr*)&(pInfo->m_nIPAddr))), nPort);
else
sprintf(strTemp, "%s:%d", inet_ntoa(*((in_addr*)&(pInfo->m_nIPAddr))), nPort);
bstrClients +=CComBSTR(strTemp);
}
}
m_bstrClients=bstrClients.m_str;
bstrClients.m_str=NULL;
}
}
break;
default:
Unlock();
return S_OK;
break;
}
lBytes -=StreamHeader.m_nLen;
}
}while(false);
Unlock();
Fire_OnDataAvailable(hSocket, lBytes, lError);
}
if(lBytes>0 && lBytes>sizeof(StreamHeader))
{
goto aa;
// ::PostMessage((HWND)m_hWnd, WM_SOCKET_CLIENT_NOTIFY, m_hSocket, FD_READ); //smoother but slight slower
}
return S_OK;
}
HRESULT __stdcall CDNS::OnSendingData(long hSocket, long lError)
{
return Fire_OnSendingData(hSocket, lError);
}
HRESULT __stdcall CDNS::OnSocketConnected(long hSocket, long lError)
{
if(lError==S_OK)
{
CComPtr<ISktClient> pISktClient;
Lock();
m_hrDNS=m_pIUnknown.QueryInterface(&pISktClient);
if(!FAILED(m_hrDNS))
m_hrDNS=pISktClient->SwitchTo(g_nDResolverClassID);
Unlock();
ATLTRACE(_T("The client socket %d is connected with a host\n"), hSocket);
}
return Fire_OnSocketConnected(hSocket, lError);
}
HRESULT __stdcall CDNS::OnConnecting(long hSocket, long hWnd)
{
ATLTRACE(_T("The client socket %d is connecting to a host......\n"), hSocket);
m_hWnd=hWnd;
m_hSocket=hSocket;
return Fire_OnConnecting(hSocket, hWnd);
}
HRESULT __stdcall CDNS::OnSocketClosed(long hSocket, long lError)
{
ATLTRACE(_T("The connected host is shut down\n"));
return Fire_OnSocketClosed(hSocket, lError);
}
HRESULT __stdcall CDNS::OnOtherMessages(long nMsg, long wParam, long lParam)
{
return Fire_OnOtherMessages(nMsg, wParam, lParam);
}
STDMETHODIMP CDNS::GetRtn(long *plResult)
{
Lock();
if(plResult)
{
if(m_hrDNS!=S_OK)
*plResult=m_hrDNS;
else
{
CComPtr<ISktClient> pISktClient;
m_pIUnknown.QueryInterface(&pISktClient);
pISktClient->GetRtn(plResult);
}
}
Unlock();
return S_OK;
}