📄 hxnetapi.cpp
字号:
#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;}voidHXResolver::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_RESULTHXResolver::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;}STDMETHODIMP HXTCPSocket::Read(UINT16 uSize){ HX_RESULT theErr = HXR_OK; HX_RESULT lResult = HXR_OK; if (m_bReadPending) { return HXR_UNEXPECTED; } m_bReadPending = TRUE; m_nRequired = uSize; m_pMutex->Lock(); theErr = DoRead(); m_pMutex->Unlock(); lResult = ConvertNetworkError(theErr); return lResult;}STDMETHODIMP HXTCPSocket::Write(IHXBuffer* pBuffer){ HX_RESULT theErr = HXR_OK; HX_RESULT lResult = HXR_OK;#ifdef _MACINTOSH if (m_pInterruptSafeMacWriteQueue)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -