📄 hxnetapi.cpp
字号:
HX_RELEASE( pEngine ); } Release(); } return theErr;}HX_RESULT HXTCPSocket::TCPSocketCallback::Func(NotificationType Type, BOOL bSuccess, conn* pConn){ if(m_pContext) { switch (Type) { case READ_NOTIFICATION://// This clears up a problem on the Macintosh where we were getting// interrupt callbacks from the Network device, and could possibly// collide when adding/removing data the same time from the same// socket, at interrupt time, and at system level time.//#if defined(_UNIX_THREADED_NETWORK_IO) if( !ReadNetworkThreadingPref((IUnknown*)(m_pContext->m_pContext) )) { m_pContext->AddRef(); m_pContext->m_pMutex->Lock(); m_pContext->DoRead(); m_pContext->m_pMutex->Unlock(); m_pContext->Release(); }#elif !defined (THREADS_SUPPORTED) && !defined(_MACINTOSH) m_pContext->AddRef(); m_pContext->m_pMutex->Lock(); m_pContext->DoRead(); m_pContext->m_pMutex->Unlock(); m_pContext->Release();#endif break; case WRITE_NOTIFICATION:#if defined(_UNIX_THREADED_NETWORK_IO) if( !ReadNetworkThreadingPref((IUnknown*)(m_pContext->m_pContext)) ) { m_pContext->AddRef(); m_pContext->m_pMutex->Lock(); m_pContext->DoWrite(); m_pContext->m_pMutex->Unlock(); m_pContext->Release(); }#elif !defined (THREADS_SUPPORTED) && !defined(_MACINTOSH) m_pContext->AddRef(); m_pContext->m_pMutex->Lock(); m_pContext->DoWrite(); m_pContext->m_pMutex->Unlock(); m_pContext->Release();#endif break; case CONNECT_NOTIFICATION: m_pContext->ConnectDone(bSuccess); break; case CLOSE_NOTIFICATION: m_pContext->CloseDone(); break; case DNS_NOTIFICATION: m_pContext->DNSDone(bSuccess); break; default: break; } } return HXR_OK;}HXListenSocket::HXListenSocket(IUnknown* pContext, HXNetworkServices* pNetworkServices): m_pListenConn(NULL), m_pCallback(NULL), m_pContext(NULL) , m_bReuseAddr(FALSE) , m_bReusePort(FALSE){ m_pContext = pContext; m_pContext->AddRef(); m_pNetworkServices = pNetworkServices; m_pNetworkServices->AddRef(); m_lRefCount = 0; m_pListenResponse = 0;}HXListenSocket::~HXListenSocket(){ if (m_pCallback) { m_pCallback->m_pContext = 0; } if (m_pListenConn) { m_pListenConn->done(); m_pListenConn->Release(); m_pListenConn = NULL; } HX_RELEASE(m_pContext); HX_DELETE(m_pCallback); HX_RELEASE(m_pListenResponse); HX_RELEASE(m_pNetworkServices);}STDMETHODIMP HXListenSocket::QueryInterface(REFIID riid, void** ppvObj){ QInterfaceList qiList[] = { { GET_IIDHANDLE(IID_IHXListenSocket), (IHXListenSocket*)this }, { GET_IIDHANDLE(IID_IHXSetSocketOption), (IHXSetSocketOption*)this }, { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXListenSocket*)this }, }; return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);}STDMETHODIMP_(ULONG32) HXListenSocket::AddRef(){ return InterlockedIncrement(&m_lRefCount);}STDMETHODIMP_(ULONG32) HXListenSocket::Release(){ if (InterlockedDecrement(&m_lRefCount) > 0) { return m_lRefCount; } delete this; return HXR_OK;}STDMETHODIMP HXListenSocket::SetOption(HX_SOCKET_OPTION option, UINT32 ulValue){ HX_RESULT ret = HXR_OK; switch (option) { case HX_SOCKOPT_REUSE_ADDR: m_bReuseAddr = ulValue; break; case HX_SOCKOPT_REUSE_PORT: m_bReusePort = ulValue; break; default: ret = HXR_NOTIMPL; } return ret;}STDMETHODIMP HXListenSocket::Init(UINT32 ulLocalAddr, UINT16 port, IHXListenResponse* pListenResponse){ if (!pListenResponse) { return HXR_UNEXPECTED; } HX_RELEASE(m_pListenResponse); m_pListenResponse = pListenResponse; m_pListenResponse->AddRef();#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();#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 HX_RESULT ret = conn::init_drivers(NULL); m_pListenConn = conn::new_socket(HX_TCP_SOCKET); if ( m_pListenConn == NULL ) { return HXR_OUTOFMEMORY; }#ifdef _UNIX m_pListenConn->SetAsyncDNSPref( ReadAsyncDNSPref((IUnknown*)m_pContext) );#endif m_pListenConn->nonblocking(); m_pListenConn->reuse_addr(m_bReuseAddr); m_pListenConn->reuse_port(m_bReusePort); if ( m_pCallback == NULL) { m_pCallback = new ListenSocketCallback(); m_pCallback->m_pContext = this; } m_pListenConn->set_callback(m_pCallback); UINT32 ulPlatformData = 0;#if defined (_WIN32) ulPlatformData = (UINT32)GetModuleHandle(NULL);#elif defined (_WIN16) ulPlatformData = (UINT32)(int)g_hInstance;#endif return m_pListenConn->listen(ulLocalAddr, port, 2, 0, ulPlatformData);}HX_RESULT HXListenSocket::ListenSocketCallback::Func(NotificationType Type, BOOL bSuccess, conn* pConn){ if(m_pContext) { switch (Type) { case ACCEPT_NOTIFICATION: if ( bSuccess ) { HXTCPSocket* pSock = new HXTCPSocket(m_pContext->m_pContext, m_pContext->m_pNetworkServices); if ( pSock ) { pSock->AddRef(); if ( SUCCEEDED(pSock->AcceptConnection(pConn)) ) { m_pContext->m_pListenResponse->NewConnection(HXR_OK, (IHXTCPSocket*)pSock); } HX_RELEASE(pSock); } } break; case CONNECT_NOTIFICATION: break; case READ_NOTIFICATION: break; case CLOSE_NOTIFICATION: break; case DNS_NOTIFICATION: default: break; } } return HXR_OK;}HXUDPSocket::HXUDPSocket(IUnknown* pContext, HXNetworkServices* pNetworkServices): m_lRefCount(0), m_pCallback(0), m_pUDPResponse(0), m_pData(0), m_bReadPending(FALSE), m_bInRead(FALSE), m_bInDoRead(FALSE), m_bInWrite(FALSE), m_nRequired(0), m_pSchedulerReadCallback(NULL), m_pSchedulerWriteCallback(NULL), m_pNonInterruptReadCallback(NULL), m_pScheduler(0), m_nDestPort(0), m_bInitComplete(FALSE), m_pInterruptState(NULL), m_pResponseInterruptSafe(NULL), m_pMutex(NULL), m_bReuseAddr(FALSE), m_bReusePort(FALSE), m_bInDestructor(FALSE), m_pContext(pContext){#ifdef _MACINTOSH m_pInterruptSafeMacWriteQueue = new InterruptSafeMacQueue(); HX_ASSERT(m_pInterruptSafeMacWriteQueue != NULL);#endif m_pNetworkServices = pNetworkServices; m_pNetworkServices->AddRef(); if (pContext) { pContext->QueryInterface(IID_IHXScheduler, (void**) &m_pScheduler); pContext->QueryInterface(IID_IHXInterruptState, (void**) &m_pInterruptState); } 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(); }#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}HXUDPSocket::~HXUDPSocket(){ m_bInDestructor = TRUE; 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); /* * XXX...While handling the m_pData->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; } if (m_pData) { m_pData->done(); m_pData->Release(); m_pData = 0; } if(m_pUDPResponse) { m_pUDPResponse->Release(); m_pUDPResponse = 0; } if (m_pCallback) { delete m_pCallback; m_pCallback = 0; } if (m_pScheduler) { m_pScheduler->Release(); m_pScheduler = 0; } while (!m_ReadBuffers.IsEmpty()) { UDP_PACKET* pPacket = (UDP_PACKET*)m_ReadBuffers.RemoveHead(); HX_RELEASE(pPacket->pBuffer); HX_DELETE(pPacket); } HX_RELEASE(m_pInterruptState); HX_RELEASE(m_pResponseInterruptSafe); 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; } m_pMutex->Unlock(); HX_DELETE(m_pMutex);#if defined( _WIN32 ) || defined( _WINDOWS ) win_net::ReleaseWinsockUsage(this);#endif HX_RELEASE(m_pNetworkServices);}STDMETHODIMP HXUDPSocket::QueryInterface(REFIID riid, void** ppvObj){ QInterfaceList qiList[] = { { GET_IIDHANDLE(IID_IHXUDPSocket), (IHXUDPSocket*)this }, { GET_IIDHANDLE(IID_IHXSetSocketOption), (IHXSetSocketOption*)this }, { GET_IIDHANDLE(IID_IHXUDPMulticastInit), (IHXUDPMulticastInit*)this }, { GET_IIDHANDLE(IID_IHXSetPrivateSocketOption), (IHXSetPrivateSocketOption*)this }, { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXUDPSocket*)this }, }; return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);}STDMETHODIMP_(ULONG32) HXUDPSocket::AddRef(){ return InterlockedIncrement(&m_lRefCount);}STDMETHODIMP_(ULONG32) HXUDPSocket::Release(){ if (InterlockedDecrement(&m_lRefCount) > 0) { return m_lRefCount; } delete this; return 0;}STDMETHODIMPHXUDPSocket::InitMulticast(UINT8 uTTL){ if (HXR_OK != m_pData->set_multicast()) { return HXR_FAIL; } if (HXR_OK != m_pData->set_multicast_ttl(uTTL)) { return HXR_FAIL; } return HXR_OK;}STDMETHODIMP HXUDPSocket::Init(ULONG32 ulAddr, UINT16 nPort, IHXUDPResponse* pUDPResponse){ if (!pUDPResponse && !m_pUDPResponse) { /* * if the response object hasn't been set up yet, then * require a response object (i.e. the first call to Init * must always specify a response object */ return HXR_UNEXPECTED; } HX_RESULT theErr = HXR_OK; UINT32 ulPlatformData = 0; if (pUDPResponse != NULL) { HX_RELEASE(m_pUDPResponse); m_pUDPResponse = pUDPResponse; m_pUDPResponse->AddRef(); } HX_RELEASE(m_pResponseInterruptSafe); m_pUDPResponse->QueryInterface(IID_IHXInterruptSafe, (void**) &m_pResponseInterruptSafe); m_sockAddr.sin_family = AF_INET; m_sockAddr.sin_addr.s_addr = DwToNet(ulAddr); //*(long*)&ulAddr; m_sockAddr.sin_port = WToNet(nPort); m_nDestPort = nPort; return HXR_OK;}STDMETHODIMP HXUDPSocket::Bind(UINT32 ulLocalAddr, UINT16 nPort){ if (m_bInitComplete) return HXR_UNEXPECTED;#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); if (theErr) { return (theErr); } theErr = HXR_OK; UINT32 ulPlatformData = 0;#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_pData = conn::new_socket(HX_UDP_SOCKET); if (!m_pData) { return HXR_OUTOFMEMORY; } // XXXGo - As it is implemented, this is the only way... if (m_bReuseAddr) { if (m_pData->reuse_addr(m_bReuseAddr) != HXR_OK) { // err...what do we need to do? HX_ASSERT(!"reuse_addr() failed");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -