📄 hxnetapi.cpp
字号:
if (!m_pData)
{
return HXR_OUTOFMEMORY;
}
#ifdef _UNIX
m_pData->SetAsyncDNSPref( ReadAsyncDNSPref((IUnknown*)m_pContext) );
#endif
// XXXAAK -- local addr binding stuff
theErr = m_pData->init(INADDR_ANY, 0);
m_pData->nonblocking();
m_pData->set_callback(m_pCallback);
#ifdef _WINDOWS
#if defined (_WIN32)
ULONG32 ulPlatformData = (ULONG32)GetModuleHandle(NULL);
#elif defined (_WIN16)
ULONG32 ulPlatformData = (ULONG32)(int)g_hInstance;
#endif
m_pData->SetWindowHandle(ulPlatformData);
#endif /* defined (_WINDOWS) */
m_bResolverPending = TRUE;
#ifndef _WINCE
m_pData->dns_find_ip_addr(pHostName);
#else
// Only blocking DNS
m_pData->dns_find_ip_addr(pHostName, 1);
#endif
return HXR_OK;
}
void
HXResolver::DNSDone(BOOL bSuccess)
{
ULONG32 ulAddr = 0;
BOOL bIsValid = TRUE;
char* pDottedIP = 0;
m_bResolverPending = FALSE;
AddRef();
if (bSuccess)
{
m_pData->dns_ip_addr_found(&bIsValid, &ulAddr);
UINT32 ulHostAddr = DwToHost(ulAddr);
m_pResp->GetHostByNameDone(HXR_OK, ulHostAddr);
}
else
{
m_pResp->GetHostByNameDone(HXR_DNR, 0);
}
Release();
}
HX_RESULT
HXResolver::HXResolverCallback::Func(NotificationType Type,
BOOL bSuccess, conn* pConn)
{
if(m_pContext)
{
switch (Type)
{
case DNS_NOTIFICATION:
m_pContext->DNSDone(bSuccess);
break;
case READ_NOTIFICATION:
case WRITE_NOTIFICATION:
case CONNECT_NOTIFICATION:
default:
break;
}
}
return HXR_OK;
}
/* HXTCPSocket */
HXTCPSocket::HXTCPSocket(IUnknown* pContext, HXNetworkServices* pNetworkServices):
m_lRefCount(0)
,m_pTCPResponse(0)
,m_pCtrl(0)
,m_lForeignAddress(0)
,m_nForeignPort(0)
,m_bReadPending(FALSE)
,m_nRequired(0)
,mSendTCP(0)
,mReceiveTCP(0)
,m_pBuffer(0)
,m_pCallback(0)
,m_bConnected(FALSE)
,m_bWantWritePending(FALSE)
,m_bInitComplete(FALSE)
,m_bWriteFlushPending(FALSE)
,m_pScheduler(0)
,m_pSchedulerReadCallback(0)
,m_pSchedulerWriteCallback(0)
,m_bInRead(FALSE)
,m_bInWrite(FALSE)
,m_bInDoRead(FALSE)
,m_pInterruptState(NULL)
,m_pResponseInterruptSafe(NULL)
,m_pMutex(NULL)
,m_bInDestructor(FALSE)
,m_pNonInterruptReadCallback(NULL)
,m_pNetworkServices(NULL)
,m_pPreferences(NULL)
,m_bReuseAddr(FALSE)
,m_bReusePort(FALSE)
,m_pContext(pContext)
,m_bSecureSocket(FALSE)
{
m_pNetworkServices = pNetworkServices;
m_pNetworkServices->AddRef();
#ifdef _MACINTOSH
m_pInterruptSafeMacWriteQueue = new InterruptSafeMacQueue();
HX_ASSERT(m_pInterruptSafeMacWriteQueue != NULL);
#endif
if (pContext)
{
pContext->QueryInterface(IID_IHXScheduler, (void**) &m_pScheduler);
pContext->QueryInterface(IID_IHXInterruptState, (void**) &m_pInterruptState);
pContext->QueryInterface(IID_IHXPreferences, (void**) &m_pPreferences);
}
if (m_pScheduler)
{
m_pSchedulerReadCallback = new ScheduledSocketCallback(this, TRUE);
m_pSchedulerReadCallback->AddRef();
m_pSchedulerWriteCallback = new ScheduledSocketCallback(this, TRUE);
m_pSchedulerWriteCallback->AddRef();
m_pNonInterruptReadCallback = new ScheduledSocketCallback(this, FALSE);
m_pNonInterruptReadCallback->AddRef();
#ifdef _MACINTOSH
m_pMacCommandCallback = new ScheduledSocketCallback(this, FALSE);
m_pMacCommandCallback->AddRef();
#endif
}
#if defined(_UNIX) && defined(HELIX_FEATURE_IGNORE_SIGPIPE)
// When the connection is closed by the server, SIGPIPE will be thrown
// in next write() and terminates the program abruptly.
//
// In order to gracefully exists the program, it's recommended to:
// - ignore the SIGPIPE and
// - checks the return code(errno) from write()
//
// for read(), it simply returns 0 when the connection is closed.
SIGNAL(SIGPIPE, SIG_IGN);
#endif /* _UNIX && HELIX_FEATURE_IGNORE_SIGPIPE */
#if defined(THREADS_SUPPORTED)
HXMutex::MakeMutex(m_pMutex);
#elif defined(_UNIX_THREADED_NETWORK_IO)
if( ReadNetworkThreadingPref((IUnknown*)m_pContext) )
HXMutex::MakeMutex(m_pMutex);
else
HXMutex::MakeStubMutex(m_pMutex);
#else
HXMutex::MakeStubMutex(m_pMutex);
#endif
}
HXTCPSocket::~HXTCPSocket()
{
m_bInDestructor = TRUE; // set it early
m_pMutex->Lock();
#ifdef _MACINTOSH
HX_DELETE(m_pInterruptSafeMacWriteQueue); // will release any objects in its nodes
#endif
if (m_pSchedulerReadCallback)
m_pSchedulerReadCallback->Unschedule(m_pScheduler);
if (m_pSchedulerWriteCallback)
m_pSchedulerWriteCallback->Unschedule(m_pScheduler);
if (m_pNonInterruptReadCallback)
m_pNonInterruptReadCallback->Unschedule(m_pScheduler);
#ifdef _MACINTOSH
if (m_pMacCommandCallback)
m_pMacCommandCallback->Unschedule(m_pScheduler);
#endif
/*
* XXX...While handling the m_pCtrl->done it's possible for the
* DispatchMessage call in CancelSelect to cause an
* asynchronous DoRead to occur. The resulting AddRef/Release
* would cause this object to be deleted again, so to prevent
* this we set the m_pCallback->m_pContext = 0
*/
if (m_pCallback)
{
m_pCallback->m_pContext = 0;
}
//#ifndef _UNIX
/* XXXJR I feel certain this is related to the above comment somehow.
* Deleting the ctrl here wreaks havoc on the encoder.
* This is a bad solution, but I don't really know
* what the right one is. This at least prevents random crashes
* in the encoder.
*
* XXXGH commented out the #ifndef because it was breaking my
* connectionless control stuff
*
*/
if (m_pCtrl)
{
m_pCtrl->done();
m_pCtrl->Release(); // A deleted (0xdddddddd) pointer was used here.
m_pCtrl = 0;
}
//#endif
HX_RELEASE(m_pTCPResponse);
HX_DELETE(m_pCallback);
HX_DELETE(mSendTCP);
HX_DELETE(mReceiveTCP);
HX_VECTOR_DELETE(m_pBuffer);
while (m_PendingWriteBuffers.GetCount() > 0)
{
IHXBuffer* pBuffer =
(IHXBuffer*) m_PendingWriteBuffers.RemoveHead();
pBuffer->Release();
}
if (m_pSchedulerReadCallback)
{
m_pSchedulerReadCallback->m_pSocket = NULL;
m_pSchedulerReadCallback->Release();
m_pSchedulerReadCallback = NULL;
}
if (m_pSchedulerWriteCallback)
{
m_pSchedulerWriteCallback->m_pSocket = NULL;
m_pSchedulerWriteCallback->Release();
m_pSchedulerWriteCallback = NULL;
}
if (m_pNonInterruptReadCallback)
{
m_pNonInterruptReadCallback->m_pSocket = NULL;
m_pNonInterruptReadCallback->Release();
m_pNonInterruptReadCallback = NULL;
}
#ifdef _MACINTOSH
if (m_pMacCommandCallback)
{
m_pMacCommandCallback->m_pSocket = NULL;
m_pMacCommandCallback->Release();
m_pMacCommandCallback = NULL;
}
#endif
HX_RELEASE(m_pInterruptState);
HX_RELEASE(m_pResponseInterruptSafe);
HX_RELEASE(m_pScheduler);
m_pMutex->Unlock();
HX_DELETE(m_pMutex);
#if defined( _WIN32 ) || defined( _WINDOWS )
win_net::ReleaseWinsockUsage(this);
#endif
HX_RELEASE(m_pNetworkServices);
HX_RELEASE(m_pPreferences);
}
STDMETHODIMP HXTCPSocket::QueryInterface(REFIID riid, void** ppvObj)
{
QInterfaceList qiList[] =
{
{ GET_IIDHANDLE(IID_IHXTCPSocket), (IHXTCPSocket*)this },
{ GET_IIDHANDLE(IID_IHXSetSocketOption), (IHXSetSocketOption*)this },
{ GET_IIDHANDLE(IID_IHXTCPSecureSocket), (IHXTCPSecureSocket*)this },
{ GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXTCPSocket*)this },
};
return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
}
STDMETHODIMP_(ULONG32) HXTCPSocket::AddRef()
{
return InterlockedIncrement(&m_lRefCount);
}
STDMETHODIMP_(ULONG32) HXTCPSocket::Release()
{
if (InterlockedDecrement(&m_lRefCount) > 0)
{
return m_lRefCount;
}
else if (m_lRefCount < 0)
{
// double delete
return 0;
}
delete this;
return 0;
}
STDMETHODIMP HXTCPSocket::Init(IHXTCPResponse* pTCPResponse)
{
if (!pTCPResponse)
{
return HXR_UNEXPECTED;
}
m_pTCPResponse = pTCPResponse;
m_pTCPResponse->AddRef();
m_pTCPResponse->QueryInterface(IID_IHXInterruptSafe,
(void**) &m_pResponseInterruptSafe);
// allocate TCP send and receive queue
mSendTCP = new CByteGrowingQueue(QUEUE_START_SIZE,1);
if (!mSendTCP || !mSendTCP->IsQueueValid())
{
return HXR_OUTOFMEMORY;
}
mSendTCP->SetMaxSize(TCP_BUF_SIZE);
mReceiveTCP = new CByteGrowingQueue(QUEUE_START_SIZE,1);
if (!mReceiveTCP || !mReceiveTCP->IsQueueValid())
{
return HXR_OUTOFMEMORY;
}
mReceiveTCP->SetMaxSize(TCP_BUF_SIZE);
m_pBuffer = new char[TCP_BUF_SIZE];
if (!m_pBuffer)
{
return HXR_OUTOFMEMORY;
}
return HXR_OK;
}
STDMETHODIMP HXTCPSocket::SetResponse(IHXTCPResponse* pTCPResponse)
{
m_pMutex->Lock();
HX_RELEASE(m_pTCPResponse);
m_pTCPResponse = pTCPResponse;
m_pTCPResponse->AddRef();
HX_RELEASE(m_pResponseInterruptSafe);
m_pTCPResponse->QueryInterface(IID_IHXInterruptSafe,
(void**) &m_pResponseInterruptSafe);
m_pMutex->Unlock();
return HXR_OK;
}
STDMETHODIMP HXTCPSocket::Bind(UINT32 ulLocalAddr, UINT16 nPort)
{
UINT32 ulMaxBandwidth = 0;
BOOL bEnforceMaxBandwidth = TRUE;
BOOL bLoadTest = FALSE;
IHXBuffer* pBuffer = NULL;
if (m_bInitComplete)
return HXR_UNEXPECTED;
m_nLocalPort = nPort;
#if defined( _WIN32 ) || defined( _WINDOWS )
// Have we been able to load and initialize the winsock stuff yet?
if (!win_net::IsWinsockAvailable(this))
{
return HXR_FAIL; // HXR_GENERAL_NONET;
}
#endif
m_pNetworkServices->UseDrivers();
HX_RESULT theErr = conn::init_drivers(NULL);
#ifdef _UNIX
//This one has to be set before we create a new socket.
conn::SetNetworkThreadingPref( ReadNetworkThreadingPref((IUnknown*)m_pContext) );
conn::SetThreadedDNSPref( ReadThreadedDNSPref((IUnknown*)m_pContext) );
#endif
m_pCtrl = NULL;
#if defined(HELIX_FEATURE_SECURECONN)
if (m_bSecureSocket)
{
IHXSSL* pHXSSL = NULL;
IHXCommonClassFactory* pCCF = NULL;
if (m_pContext)
{
m_pContext->AddRef();
// get the CCF
m_pContext->QueryInterface(IID_IHXCommonClassFactory, (void**)&pCCF);
HX_RELEASE(m_pContext);
}
if (pCCF)
{
pCCF->CreateInstance(IID_IHXSSL, (void**) &pHXSSL);
HX_RELEASE(pCCF);
}
if (pHXSSL)
{
m_pCtrl = new secureconn(pHXSSL);
pHXSSL->Release();
}
}
else
#endif /* HELIX_FEATURE_SECURECONN */
{
m_pCtrl = conn::new_socket(HX_TCP_SOCKET);
}
if (!m_pCtrl)
{
return HXR_OUTOFMEMORY;
}
// XXXGo - As it is implemented, this is the only way...
if (m_bReuseAddr)
{
if (m_pCtrl->reuse_addr(m_bReuseAddr) != HXR_OK)
{
// err...what do we need to do?
HX_ASSERT(!"reuse_addr() failed");
}
}
if (m_bReusePort)
{
if (m_pCtrl->reuse_port(m_bReusePort) != HXR_OK)
{
// err...what do we need to do?
HX_ASSERT(!"reuse_port() failed");
}
}
#ifdef _UNIX
m_pCtrl->SetAsyncDNSPref( ReadAsyncDNSPref((IUnknown*)m_pContext) );
#endif
m_pCtrl->nonblocking();
m_pCallback = new TCPSocketCallback;
if (!m_pCallback)
{
return HXR_OUTOFMEMORY;
}
m_pCallback->m_pContext = this;
m_pCtrl->set_callback(m_pCallback);
m_bInitComplete = TRUE;
if (m_pPreferences)
{
/* Get MaxBandwidth from Prefs */
ReadPrefINT32(m_pPreferences, "MaxBandwidth", ulMaxBandwidth);
ReadPrefBOOL(m_pPreferences, "LoadTest", bLoadTest);
ReadPrefBOOL(m_pPreferences, "EnforceMaxBandwidth", bEnforceMaxBandwidth);
//If we are in load test mode, never enforce the MaxBandwidth.
bEnforceMaxBandwidth = bEnforceMaxBandwidth&&!bLoadTest;
if (ulMaxBandwidth && bEnforceMaxBandwidth)
{
conn::m_ulMaxBandwidth = ulMaxBandwidth / 8;
}
else if (!bEnforceMaxBandwidth)
{
conn::m_ulMaxBandwidth = MAX_UINT32;
}
}
return HXR_OK;
}
STDMETHODIMP HXTCPSocket::Connect(const char* pDestination,
UINT16 nPort)
{
if (!m_bInitComplete)
{
HX_RESULT ret = Bind(HXR_INADDR_ANY, 0);
if (HXR_OK != ret)
return ret;
}
HX_RESULT theErr = HXR_OK;
UINT32 ulPlatformData = 0;
#if defined (_WIN32)
ulPlatformData = (UINT32)GetModuleHandle(NULL);
#elif defined (_WIN16)
ulPlatformData = (UINT32)(int)g_hInstance;
#endif
m_nForeignPort = nPort;
#ifndef _WINCE
theErr = m_pCtrl->connect(pDestination,nPort,0,ulPlatformData);
#else
theErr = m_pCtrl->connect(pDestination,nPort,1,ulPlatformData);
#endif
theErr = ConvertNetworkError(theErr);
return theErr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -