⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hxnetapi.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
				m_pTCPResponse->ConnectDone(theError);
				break;

			case TCP_BIND_COMMAND:
			default:
			    theErr = DoRead();
			    DoWrite();
			    break;
	   	}
	}
	m_pMutex->Unlock();

        // we want out of memory errors to be reported immediately
        // because fiddling around waiting for the error to propagate
        // normally will just make the situation worse; mask out all
        // other errors, as they will eventually get dealt with in
        // ReadDone() or similar functions.
        
        if (theErr != HXR_OUTOFMEMORY)
        {
            theErr = HXR_OK;
        }
        
	if( theErr )
	{
	    IHXErrorMessages * pErrorNotifier = NULL;
	    IUnknown * pPlayer = NULL;
	    IHXClientEngine* pEngine = NULL;
	    UINT32 nNumPlayers = 0;

	    m_pContext->QueryInterface(IID_IHXClientEngine, (void**)&pEngine);
	    if( pEngine )
	    {
		nNumPlayers = pEngine->GetPlayerCount();
		for( int ii=0; ii<nNumPlayers; ii++ )
		{
		    pEngine->GetPlayer(ii,pPlayer);
		    if( pPlayer )
		    {
			pPlayer->QueryInterface( IID_IHXErrorMessages, (void**)&pErrorNotifier );
		    }
		    if( pErrorNotifier )
		    {
			pErrorNotifier->Report( HXLOG_ERR, theErr, 0, NULL, NULL );
			pErrorNotifier->Release();
		    }
		    HX_RELEASE( pPlayer );
		}
	    }
	    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;
}

STDMETHODIMP
HXUDPSocket::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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -