win_net.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:49k
- /* ***** BEGIN LICENSE BLOCK *****
- * Source last modified: $Id: win_net.cpp,v 1.6.2.3 2004/07/09 01:46:44 hubbe Exp $
- *
- * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
- *
- * The contents of this file, and the files included with this file,
- * are subject to the current version of the RealNetworks Public
- * Source License (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the current version of the RealNetworks Community
- * Source License (the "RCSL") available at
- * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
- * will apply. You may also obtain the license terms directly from
- * RealNetworks. You may not use this file except in compliance with
- * the RPSL or, if you have a valid RCSL with RealNetworks applicable
- * to this file, the RCSL. Please see the applicable RPSL or RCSL for
- * the rights, obligations and limitations governing use of the
- * contents of the file.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL") in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your version of
- * this file only under the terms of the GPL, and not to allow others
- * to use your version of this file under the terms of either the RPSL
- * or RCSL, indicate your decision by deleting the provisions above
- * and replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient may
- * use your version of this file under the terms of any one of the
- * RPSL, the RCSL or the GPL.
- *
- * This file is part of the Helix DNA Technology. RealNetworks is the
- * developer of the Original Code and owns the copyrights in the
- * portions it created.
- *
- * This file, and the files included with this file, is distributed
- * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
- * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
- * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
- * ENJOYMENT OR NON-INFRINGEMENT.
- *
- * Technology Compatibility Kit Test Suite(s) Location:
- * http://www.helixcommunity.org/content/tck
- *
- * Contributor(s):
- *
- * ***** END LICENSE BLOCK ***** */
- #include "hxtypes.h"
- #ifdef _WIN16
- #include <stdlib.h>
- #endif _WIN16
- #include <stdio.h>
- #include <string.h>
- /* mcast_multiple_if test */
- #ifndef _WINCE
- #include <iostream.h>
- #include <winsock2.h>
- #include <ws2tcpip.h>
- #endif /* _WINCE */
- #include "hxslist.h"
- #include "platform/win/sock.h"
- #include "platform/win/hxsock.h" // Low level socket calls
- #include "hxthread.h"
- #include "hxcom.h"
- #include "hxengin.h"
- #include "threngin.h"
- #include "platform/win/win_net.h" // Our declaration
- #include "platform/win/casynnet.h" // Declaration of async socket notifier
- #include "netbyte.h"
- #include "hxbuffer.h"
- #include "timebuff.h"
- #include "hxtick.h"
- #include "debugout.h" // Debug macros
- #include "hxstrutl.h"
- #include "hxheap.h"
- #include "thrdconn.h"
- #ifdef _DEBUG
- #undef HX_THIS_FILE
- static const char HX_THIS_FILE[] = __FILE__;
- #endif
- static WinsockManager OnlyOneOfThisInTheWholeProgram;
- //#define _LOGSMIL 1
- win_net::win_net() // PostThreadMessage
- {
- set_sock( INVALID_SOCKET );
- mLastError = HXR_OK;
- callRaConnect = 1;
- bReadyToWrite = 0;
- m_SocketState = CONN_CLOSED;
- #ifndef WIN32_PLATFORM_PSPC
- m_hAsyncHandle = NULL;
- #endif
- m_AsyncAddress = NULL;
- CurrentAddr = 0;
- m_DNSOnly = FALSE;
- m_pAsyncHost = NULL;
- InBlockingMode = 0;
- m_lRefCount = 0;
- m_pInBuffer = new char[TCP_BUF_SIZE];
- m_bReuseAddr = FALSE;
- m_bReusePort = FALSE;
- m_bIgnoreWSAECONNRESET = FALSE;
- }
- win_net::~win_net()
- {
- #ifndef WIN32_PLATFORM_PSPC
- m_AsyncNotifier = CAsyncSockN::GetCAsyncSockNotifier( m_hInst , FALSE);
- if (m_AsyncNotifier)
- {
- m_AsyncNotifier->CancelSelect( this );
- }
- #endif
- m_SocketState = CONN_CLOSING;
- if ((get_sock() != INVALID_SOCKET) && sockObj)
- {
- if (sockObj->HXclosesocket(get_sock()))
- {
- int code = 0;
- code = sockObj->HXWSAGetLastError();
- }
- }
- set_sock( INVALID_SOCKET );
- m_SocketState = CONN_CLOSED;
- mConnectionOpen = 0;
- if (m_AsyncAddress)
- {
- delete [] m_AsyncAddress;
- m_AsyncAddress = NULL;
- }
- HX_VECTOR_DELETE(m_pAsyncHost);
- delete[] m_pInBuffer;
- }
- win_net * win_net::new_socket(UINT16 type)
- {
- win_net* c = NULL;
- if (sockObj)
- {
- switch(type)
- {
- case HX_TCP_SOCKET:
- c = new win_TCP;
- break;
-
- case HX_UDP_SOCKET:
- c = new win_UDP;
- break;
- }
- }
- return(c);
- }
- // init_drivers() should do any network driver initialization here
- // params is a pointer to a platform specfic defined struct that
- // contains an required initialization data
- HX_RESULT win_net::init_drivers(void *params)
- {
- if(!sockObj)
- sockObj = new CHXSock;
- if(!sockObj)
- return(HXR_OUTOFMEMORY);
- return(HXR_OK);
- }
- /* close_drivers() should close any network drivers used by the program
- NOTE: The program MUST not make any other calls to the network drivers
- until init_drivers() has been called */
- HX_RESULT win_net::close_drivers(void *params)
- {
- if(sockObj)
- {
- sockObj->HXWSACleanup();
- delete sockObj;
- sockObj = NULL;
- }
- return(HXR_OK);
- }
- HX_RESULT win_net::host_to_ip_str( char *host, char *ip, UINT32 ulIPBufLen)
- {
- ULONG32 dwAddress;
- IN_ADDR rInAddress;
- HX_RESULT theErr;
- PHOSTENT pHostEntry;
- theErr = HXR_OK;
- // Let's look for this in the cache first
- if (conn::is_cached( host, &dwAddress))
- {
- // Found it, copy the 32bit address into rInAddress w/o calling memcpy()
- rInAddress = *(IN_ADDR *)&dwAddress;
- }
- else
- {
- // Do DNS on the host name
- if (!(pHostEntry = sockObj->HXgethostbyname( host )))
- {
- // Error
- theErr = HXR_DNR;
- }
- // Return w/o attempting any copies if there's an error
- if (HXR_OK != theErr)
- {
- goto FuncExit;
- }
-
- // copy the ip address into rInAddress w/o calling memcpy()
- rInAddress = *(IN_ADDR *)(pHostEntry->h_addr);
- }
- // Convert the ULONG32 IP address into a string and copy it into ip
- SafeStrCpy( ip, sockObj->HXinet_ntoa( rInAddress ) , ulIPBufLen);
- // Single exit point
- FuncExit:
- return( theErr );
- }
- ULONG32 win_net::AddRef()
- {
- return InterlockedIncrement(&m_lRefCount);
- }
- ULONG32 win_net::Release()
- {
- if (InterlockedDecrement(&m_lRefCount) > 0)
- {
- return m_lRefCount;
- }
- delete this;
- return 0;
- }
- HX_RESULT win_net::init_win(UINT16 type, UINT32 local_addr,
- UINT16 port, UINT16 blocking)
- {
- int s;
- s = sockObj->HXsocket(PF_INET, type, 0);
- if (s == INVALID_SOCKET)
- {
- mLastError = HXR_NET_SOCKET_INVALID;
- return mLastError;
- }
- InBlockingMode = 1;
-
- {
- struct linger Ling;
- Ling.l_onoff = 0;
- Ling.l_linger = 0;
- if (callRaConnect && sockObj->HXsetsockopt(s, SOL_SOCKET, SO_LINGER,
- (char *)&Ling, sizeof(Ling)) != 0)
- {
- if(!InBlockingMode)
- return HXR_BLOCK_CANCELED;
- int code;
- code = sockObj->HXWSAGetLastError();
- mLastError = HXR_NET_SOCKET_INVALID;
- InBlockingMode = 0;
- return mLastError;
- }
- }
-
- if(!InBlockingMode)
- return HXR_BLOCK_CANCELED;
-
- InBlockingMode = 0;
-
- {
- if (sockObj->HXsetsockopt(s, SOL_SOCKET, SO_REUSEADDR,
- (const char *)&m_bReuseAddr, sizeof(m_bReuseAddr)) != 0)
- {
- int code;
- code = sockObj->HXWSAGetLastError();
- mLastError = HXR_NET_SOCKET_INVALID;
- return mLastError;
- }
- // Reuse port is not supported on win's right now...
- /*
- if (sockObj->HXsetsockopt(s, SOL_SOCKET, SO_REUSEPORT,
- (const char *)&m_bReusePort, sizeof(m_bReusePort)) != 0)
- {
- int code;
- code = sockObj->HXWSAGetLastError();
- mLastError = HXR_NET_SOCKET_INVALID;
- return mLastError;
- }
- */
- }
-
- struct sockaddr_in SockAddr;
- memset(&SockAddr, 0, sizeof(SockAddr));
- SockAddr.sin_family = AF_INET;
-
- SockAddr.sin_addr.s_addr = sockObj->HXhtonl(local_addr);
- SockAddr.sin_port = sockObj->HXhtons(port);
- if (sockObj->HXbind(s, (sockaddr*)&SockAddr, sizeof(SockAddr)) < 0)
- {
- //perror("bind");
- goto err;
- }
- {
- unsigned long lMode = 1;
- if (!blocking && sockObj->HXioctlsocket(s, FIONBIO, &lMode) < 0)
- {
- goto err;
- }
- }
- if (!callRaConnect)
- {
- m_SocketState = CONN_OPEN;
- }
- else
- {
- m_SocketState = CONN_NO_CONN;
- }
- set_sock( s );
- return HXR_OK;
- err:
- sockObj->HXclosesocket(s);
- mLastError = HXR_NET_CONNECT;
- return mLastError;
- }
- HX_RESULT win_net::connect(const char* host, UINT16 port, UINT16 blocking, ULONG32 ulPlatform)
- {
- DEBUGOUTSTR( "win_net::connect()rn" );
- m_hInst = (HINSTANCE)ulPlatform;
- if (!blocking)
- {
- #ifndef WIN32_PLATFORM_PSPC
- return( ConnectAsync( host, port ) );
- #else
- HX_ASSERT(0 && "No Async connect");
- #endif
- }
- else
- {
- bReadyToWrite = 0;
- if(!host)
- {
- mLastError = HXR_DNR;
- return mLastError;
- }
-
- if(get_sock() < 0)
- {
- mLastError = HXR_NET_SOCKET_INVALID;
- return mLastError;
- }
-
- struct in_addr addr;
- char* pTemp = strrchr(host, '.');
- if (pTemp && isdigit(*(pTemp + 1)))
- { /* IP address. */
- InBlockingMode = 1;
- addr.s_addr = sockObj->HXinet_addr(host);
-
- if(!InBlockingMode)
- return HXR_BLOCK_CANCELED;
-
- InBlockingMode = 0;
-
- if ((UINT)addr.s_addr == (UINT)-1)
- {
- mLastError = HXR_DNR;
- return mLastError;
- }
- m_SocketState = CONN_CONNECT_INPROG;
- }
- else
- { /* Host name. */
- InBlockingMode = 1;
- struct hostent *h = sockObj->HXgethostbyname(host);
-
- if(!InBlockingMode)
- return HXR_BLOCK_CANCELED;
-
- InBlockingMode = 0;
- if (!h || !h->h_addr )
- {
- mLastError = HXR_DNR;
- return mLastError;
- }
- memcpy(&addr, h->h_addr, sizeof(struct in_addr)); /* Flawfinder: ignore */
-
- // Rahul
- m_AsyncPort = port;
- if (m_pAsyncHost != host)
- {
- HX_VECTOR_DELETE(m_pAsyncHost);
- m_pAsyncHost = ::new_string(host);
- }
- }
-
- struct sockaddr_in SockAddr;
- memset(&SockAddr, 0, sizeof(SockAddr));
- SockAddr.sin_family = AF_INET;
- SockAddr.sin_addr.s_addr = *(long*)&addr;
- SockAddr.sin_port = sockObj->HXhtons(port);
- // this stores info about current addr
- CurrentAddr = *(ULONG32*)&addr;
-
- InBlockingMode = 1;
-
- if(callRaConnect && sockObj->HXconnect(get_sock(), (sockaddr*)&SockAddr, sizeof(SockAddr)))
- {
- if(!InBlockingMode)
- return HXR_BLOCK_CANCELED;
-
- InBlockingMode = 0;
- int code;
- code = sockObj->HXWSAGetLastError();
- if(!blocking && (code == WSAEWOULDBLOCK || code == WSAEINPROGRESS))
- {
- mConnectionOpen = 1;
- return HXR_OK;
- }
- mLastError = HXR_NET_CONNECT;
- return mLastError;
- }
-
- if(!InBlockingMode)
- return HXR_BLOCK_CANCELED;
-
- InBlockingMode = 0;
-
- mConnectionOpen = 1;
- m_SocketState = CONN_OPEN;
- bReadyToWrite = 1;
- #ifdef WIN32_PLATFORM_PSPC
- // Without asyncronous notification we cannot tolerate Asyncronous connect
- // so set non-blocking here rather than at connect
- ULONG lMode = 1;
- sockObj->HXioctlsocket(get_sock(), FIONBIO, &lMode);
- if (mCallBack)
- {
- mCallBack->Func(CONNECT_NOTIFICATION);
- }
- #endif
- return HXR_OK;
- }
- }
- //-------------------------------------------------
- #if defined(HELIX_FEATURE_NETWORK_USE_SELECT)
- HX_RESULT
- win_net::WaitforSelect(void *pE,void *pC)
- {
- ThreadEngine *pEngine = (ThreadEngine *)pE;
- ThreadedConn *pProcessConn = (ThreadedConn*) pC;
- if (!pEngine)
- return HXR_FAIL;
- CHXMapPtrToPtr::Iterator ndxConn;
- CHXMapPtrToPtr* pSockMap = pEngine->GetSockMap();
- fd_set readfds,exceptfds;
- BOOL bHaveSock = FALSE;
- HX_RESULT theErr = HXR_OK;
- FD_ZERO(&readfds);
- FD_ZERO(&exceptfds);
-
- for (ndxConn = pSockMap->Begin();
- ndxConn != pSockMap->End(); ++ndxConn)
- {
- ThreadedConn* pConn = (ThreadedConn*) (*ndxConn);
- if (pProcessConn &&
- pConn != pProcessConn)
- continue; // dont process other connections while closing
- if (!pConn->connection_really_open())
- continue;
- if (!pConn->GetActualConn())
- continue;
- unsigned int s = pConn->get_sock();
- if (s != INVALID_SOCKET)
- {
- FD_SET(s,&readfds);
- FD_SET(s,&exceptfds);
- bHaveSock = TRUE;
- }
- }
- if (!bHaveSock)
- return HXR_FAIL;
- theErr = sockObj->HXselect(NULL,&readfds,NULL,NULL/*&exceptfds*/,NULL);
- if (theErr == SOCKET_ERROR)
- {
- theErr = sockObj->HXWSAGetLastError();
- }
- else
- {
- theErr = HXR_OK;
- }
- // check for read ready
- for (ndxConn = pSockMap->Begin();
- ndxConn != pSockMap->End(); ++ndxConn)
- {
- ThreadedConn* pConn = (ThreadedConn*) (*ndxConn);
- if (pProcessConn &&
- pConn != pProcessConn)
- continue; // dont process other connections while closing
- if (!pConn->GetActualConn())
- continue;
- int s = pConn->get_sock();
- if (s != INVALID_SOCKET)
- {
- if (FD_ISSET(s,&readfds))
- pConn->DoRead(TRUE);
- }
- }
- return theErr;
- }
- HX_RESULT
- win_net::CheckForConnection()
- {
- HX_ASSERT(m_SocketState == CONN_LISTENNING);
- if (m_SocketState != CONN_LISTENNING)
- return HXR_FAIL;
- sockaddr_in addr;
- int len = sizeof(sockaddr_in);
- memset(&addr, 0, len);
-
- SOCKET sock = sockObj->HXaccept(get_sock(), (sockaddr*)&addr, &len);
- if ( sock == INVALID_SOCKET )
- {
- int code = sockObj->HXWSAGetLastError();
- // igno all errors... r
- return HXR_WOULD_BLOCK;
- }
- win_net* c = (win_net*)conn::actual_new_socket(HX_TCP_SOCKET);
- c->AddRef();
- conn::add_connection_to_list ( c );
- if ( c )
- {
- c->set_sock(sock);
- c->connect_accept((ULONG32)m_hInst, addr);
- if (mCallBack && (m_SocketState == CONN_LISTENNING))
- {
- mCallBack->Func(ACCEPT_NOTIFICATION, TRUE, (conn*)c);
- }
- }
- HX_RELEASE(c);
- return HXR_OK;
- }
- #endif //defined(HELIX_FEATURE_NETWORK_USE_SELECT)
- // This function actually starts an async DNS request
- // It does it on either the first read or first write after we
- #ifndef WIN32_PLATFORM_PSPC
- // call ConnectAsync();
- HX_RESULT win_net::DoStartAsyncConn()
- {
- DEBUGOUTSTR( "win_net::DoStartAsyncConn()rn" );
-
- if (!m_pAsyncHost)
- {
- return (mLastError = HXR_FAILED);
- }
- if (!m_AsyncAddress)
- {
- m_AsyncAddress = new char[MAXGETHOSTSTRUCT];
- }
- if (!m_AsyncAddress)
- {
- return (mLastError = HXR_OUTOFMEMORY);
- }
- m_AsyncNotifier = CAsyncSockN::GetCAsyncSockNotifier( m_hInst , TRUE);
- m_AsyncNotifier->DoAsyncDNS( this, m_pAsyncHost, m_AsyncAddress, MAXGETHOSTSTRUCT );
- m_SocketState = CONN_DNS_INPROG;
- return( mLastError = HXR_WOULD_BLOCK );
- }
- // This method get's called by connect() in the case of an async request
- // It doesn't however actually start the connection. It just registers
- // that we need to do the connection. DoStartAsyncConn() will really do it.
- HX_RESULT win_net::ConnectAsync( LPCSTR host, UINT16 port )
- {
- DEBUGOUTSTR( "win_net::ConnectAsync()rn" );
- bReadyToWrite = 0;
- if (!host)
- {
- mLastError = HXR_DNR;
- return mLastError;
- }
-
- if (get_sock() == INVALID_SOCKET)
- {
- mLastError = HXR_NET_SOCKET_INVALID;
- return mLastError;
- }
-
- struct in_addr addr;
- char* pTemp = strrchr(host, '.');
- if (pTemp && atoi(pTemp + 1))
- { /* IP address. */
- addr.s_addr = sockObj->HXinet_addr(host);
-
- if ((UINT)addr.s_addr == (UINT)-1)
- {
- mLastError = HXR_DNR;
- return mLastError;
- }
- else
- {
- LPSTR pTemp;
- hostent *pHost;
- if (!m_AsyncAddress)
- {
- m_AsyncAddress = new char[MAXGETHOSTSTRUCT];
- }
- if (!m_AsyncAddress)
- {
- mLastError = HXR_OUTOFMEMORY;
- return (mLastError);
- }
- pHost = (hostent *)m_AsyncAddress;
- // this stores info about current addr
- CurrentAddr = *(ULONG32 *)&addr;
- m_AsyncPort = port;
- pTemp = (LPSTR)&addr.s_addr;
- pHost->h_addr_list = &pTemp;
- CB_DNSComplete( TRUE );
- }
- }
- else if (conn::is_cached((char *)host,(ULONG32 *) &addr))
- {
- LPSTR pTemp;
- hostent *pHost;
- if (!m_AsyncAddress)
- {
- m_AsyncAddress = new char[MAXGETHOSTSTRUCT];
- }
- if (!m_AsyncAddress)
- {
- mLastError = HXR_OUTOFMEMORY;
- return (mLastError);
- }
- pHost = (hostent *)m_AsyncAddress;
- // this stores info about current addr
- CurrentAddr = *(ULONG32 *)&addr;
- m_AsyncPort = port;
- pTemp = (LPSTR)&addr.s_addr;
- pHost->h_addr_list = &pTemp;
- CB_DNSComplete( TRUE );
- }
- else
- {
- // Save the parameters, and tell ourselves we're starting up
- m_AsyncPort = port;
- if (m_pAsyncHost != host)
- {
- HX_VECTOR_DELETE(m_pAsyncHost);
- m_pAsyncHost = ::new_string(host);
- }
- m_SocketState = CONN_NO_CONN;
- return(DoStartAsyncConn());
- }
- return( HXR_OK );
- }
- // Once async DNS has commpleted then we'll call this guy to do the
- // connection (again asynchronously).
- void win_net::ContinueAsyncConnect()
- {
- hostent *pHost;
- struct in_addr addr;
- DEBUGOUTSTR( "win_net::ContinueAsyncConnect()rn" );
- pHost = (hostent *)m_AsyncAddress;
- if (!pHost)
- return;
- memcpy( &(addr.s_addr), pHost->h_addr, sizeof( addr.s_addr ) ); /* Flawfinder: ignore */
- m_AsyncNotifier = CAsyncSockN::GetCAsyncSockNotifier( m_hInst ,TRUE);
- m_AsyncNotifier->DoAsyncSelect( this );
-
- struct sockaddr_in SockAddr;
- memset( &SockAddr, 0, sizeof( SockAddr ) );
- SockAddr.sin_family = AF_INET;
- SockAddr.sin_addr.s_addr = *(long*)&(addr.s_addr);
- SockAddr.sin_port = sockObj->HXhtons( m_AsyncPort );
-
- if(callRaConnect && sockObj->HXconnect( get_sock(), (sockaddr*)&SockAddr, sizeof( SockAddr ) ))
- {
- int code;
- code = sockObj->HXWSAGetLastError();
- if (code == WSAEWOULDBLOCK || code == WSAEINPROGRESS)
- {
- m_SocketState = CONN_CONNECT_INPROG;
- mConnectionOpen = 1;
- return;
- }
- mLastError = HXR_NET_CONNECT;
- m_SocketState = CONN_CONNECT_FAILED;
- return;
- }
- m_SocketState = CONN_CONNECT_INPROG;
-
- mConnectionOpen = 1;
- return;
- }
- // Called by the notifier to tell us that the DNS request completed
- void win_net::CB_DNSComplete( int iSuccess )
- {
- DEBUGOUTSTR( "CB_DNSComplete()rn" );
- mDNSDone = TRUE;
- if (iSuccess && m_pAsyncHost)
- {
- conn::add_to_cache(m_pAsyncHost, get_addr());
- }
- if (m_DNSOnly)
- {
- if (iSuccess)
- {
- mHostIPValid = TRUE;
- mHostIPAddr = get_addr();
- }
- else
- {
- mHostIPValid = FALSE;
- }
- }
- else
- {
- if (iSuccess)
- {
- m_SocketState = CONN_CONNECT_INPROG;
- ContinueAsyncConnect();
- }
- else
- {
- m_SocketState = CONN_DNS_FAILED;
- }
- }
- if (mCallBack)
- {
- mCallBack->Func(DNS_NOTIFICATION, iSuccess);
- }
- }
- // Called by the notifier to tell us that the Connection completed
- void win_net::CB_ConnectionComplete( int iSuccess )
- {
- DEBUGOUTSTR( "CB_ConnectionComplete()rn" );
- if (iSuccess)
- {
- m_SocketState = CONN_OPEN;
- if (mCallBack)
- {
- mCallBack->Func(CONNECT_NOTIFICATION);
- }
- }
- else
- {
- m_SocketState = CONN_CONNECT_FAILED;
- if (mCallBack)
- {
- mCallBack->Func(CONNECT_NOTIFICATION, FALSE);
- }
- }
- }
- // Called by the notifier when data ready for read/write
- void win_net::CB_ReadWriteNotification( int iType )
- {
- #ifndef _DEMPSEY
- // noisy output
- DEBUGOUTSTR( "CB_ReadWriteNotification()....rn" );
- #endif // _DEMPSEY
- // Should do something here....
- if (mCallBack && (m_SocketState == CONN_OPEN))
- {
- if (iType == FD_WRITE)
- {
- mCallBack->Func(WRITE_NOTIFICATION);
- }
- else if (iType == FD_READ)
- {
- mCallBack->Func(READ_NOTIFICATION);
- }
-
- //mCallBack->callback_task( HX_UDP_CALLBACK, NULL );
- }
- }
- void win_net::CB_AcceptNotification()
- {
- DEBUGOUTSTR( "CB_AcceptNotification()....rn" );
- HX_ASSERT(m_SocketState == CONN_LISTENNING);
-
- win_net* c = (win_net*)conn::actual_new_socket(HX_TCP_SOCKET);
- c->AddRef();
- conn::add_connection_to_list ( c );
- if ( c )
- {
- sockaddr_in addr;
- int len = sizeof(addr);
- SOCKET sock = sockObj->HXaccept(get_sock(), (sockaddr*)&addr, &len);
- if ( sock != INVALID_SOCKET)
- {
- c->set_sock(sock);
- c->connect_accept((ULONG32)m_hInst, addr);
- if (mCallBack && (m_SocketState == CONN_LISTENNING))
- {
- mCallBack->Func(ACCEPT_NOTIFICATION, TRUE, (conn*)c);
- }
- }
- }
- HX_RELEASE(c);
- }
- void win_net::CB_CloseNotification()
- {
- DEBUGOUTSTR( "CB_CloseNotification()....rn" );
- m_SocketState = CONN_CLOSED;
- if (mCallBack)
- {
- mCallBack->Func(CLOSE_NOTIFICATION);
- }
- }
- #endif
- HX_RESULT win_net::connect( sockaddr_in *addr )
- {
- if(callRaConnect && sockObj->HXconnect( get_sock(), (sockaddr*)addr, sizeof( addr ) ))
- {
- mLastError = HXR_NET_CONNECT;
- return mLastError;
- }
-
- mConnectionOpen = 1;
- return HXR_OK;
- }
- HX_RESULT win_net::write(void * buf, UINT16 *len)
- {
- int got;
- DEBUGOUTSTR( "win_net::write()rn" );
- if (get_sock() == INVALID_SOCKET)
- {
- // Not connected
- return( mLastError = HXR_NET_SOCKET_INVALID );
- }
- if (m_SocketState != CONN_OPEN ) //&& m_SocketState != CONN_DNS_INPROG)
- {
- // We won't be able to write anything here, so clear this
- // we'll return why we didn't write anything.
- *len = 0;
- switch( m_SocketState )
- {
- case CONN_DNS_INPROG:
- case CONN_CONNECT_INPROG:
- case CONN_CLOSING:
- return( mLastError = HXR_WOULD_BLOCK );
- case CONN_CLOSED:
- return( mLastError = HXR_NET_SOCKET_INVALID );
- case CONN_NO_CONN:
- #ifndef WIN32_PLATFORM_PSPC
- return( DoStartAsyncConn() );
- #else
- HX_ASSERT(0 && "No Async net");
- return( HXR_NET_READ );
- #endif
- case CONN_DNS_FAILED:
- return( mLastError = HXR_DNR );
- case CONN_CONNECT_FAILED:
- return( mLastError = HXR_NET_CONNECT );
- default:
- // HUH???
- assert( 0 );
- return( mLastError = HXR_NET_READ );
- };
- }
- else
- {
- got = sockObj->HXsend( get_sock(), (char *)buf, *len, 0 );
- if (got == -1)
- {
- int code;
- *len = 0;
- code = sockObj->HXWSAGetLastError();
- // Mask the "so what?" errors
- if (code == WSAEWOULDBLOCK || code == WSAEINPROGRESS)
- {
- return HXR_WOULD_BLOCK;
- }
- else
- {
- mLastError = HXR_NET_WRITE;
- return mLastError;
- }
- }
- //#if defined(_DEBUG) && defined(_LOGSMIL)
- // if (::HXDebugOptionEnabled("zLogSMIL"))
- //{FILE* f1 = ::fopen("e:\temp\foo.txt", "a+"); ::fwrite(buf, got, 1, f1);::fclose(f1);}
- //#endif
- *len = got;
- return HXR_OK;
- }
- }
- HX_RESULT win_net::writeto(void * buf, UINT16 *len, ULONG32 addr, UINT16 port)
- {
- //sendto
- int got;
- sockaddr_in resend_addr;
-
- ::memset( &resend_addr, 0, sizeof( resend_addr ) );
- resend_addr.sin_family = AF_INET;
- resend_addr.sin_addr.s_addr = addr;
- resend_addr.sin_port = sockObj->HXhtons(port);
- got = sockObj->HXsendto(get_sock(), (char *) buf, *len, 0, (sockaddr *)&resend_addr, sizeof (resend_addr));
- if (got == -1)
- {
- int code;
- *len = 0;
- code = sockObj->HXWSAGetLastError();
- // Mask the "so what?" errors
- if (code == WSAEWOULDBLOCK || code == WSAEINPROGRESS)
- {
- return HXR_WOULD_BLOCK;
- }
- else
- {
- mLastError = HXR_NET_WRITE;
- return mLastError;
- }
- }
- *len = got;
- return HXR_OK;
- }
- HX_RESULT win_net::WriteComplete (char * Buffer, int length)
- {
- int sent = 0;
- unsigned short cur_sent=0;
- while(sent < length)
- {
- cur_sent = length - sent;
- HX_RESULT ret = write(Buffer + sent, &cur_sent);
- if(ret != HXR_OK && ret != HXR_WOULD_BLOCK)
- break;
- sent += cur_sent;
- }
- // m_SocketState = CONN_NO_CONN;
- if(sent < length)
- {
- mLastError = HXR_NET_WRITE;
- return mLastError;
- }
- return HXR_OK;
- }
- int win_net::ReadyToWrite()
- {
- if(get_sock() < 0)
- {
- bReadyToWrite = 0;
- return bReadyToWrite;
- }
- if(bReadyToWrite)
- return 1;
-
- fd_set writefds;
- FD_ZERO(&writefds);
- FD_SET((UINT32)get_sock(), &writefds);
-
- TIMEVAL timeout;
- timeout.tv_sec = 1;
- timeout.tv_usec = 0;
- if(sockObj->HXselect(0, NULL, &writefds,NULL, &timeout) == 1)
- bReadyToWrite = 1;
-
- return bReadyToWrite;
- }
- void win_net::done (void)
- {
- #ifndef WIN32_PLATFORM_PSPC
- m_AsyncNotifier = CAsyncSockN::GetCAsyncSockNotifier( m_hInst , FALSE);
- if (m_AsyncNotifier)
- {
- m_AsyncNotifier->CancelSelect( this );
- }
- #endif
- m_SocketState = CONN_CLOSING;
- if ((get_sock() != INVALID_SOCKET) && sockObj)
- {
- if (sockObj->HXclosesocket(get_sock()))
- {
- int code = 0;
- code = sockObj->HXWSAGetLastError();
- }
- }
- set_sock( INVALID_SOCKET );
- m_SocketState = CONN_CLOSED;
- mConnectionOpen = 0;
- }
- inline HX_RESULT win_net::listen(ULONG32 ulLocalAddr, UINT16 port,
- UINT16 backlog, UINT16 blocking,
- ULONG32 ulPlatform)
- {
- m_hInst = (HINSTANCE)ulPlatform;
- // accept is polled
- #ifndef WIN32_PLATFORM_PSPC
- m_AsyncNotifier = CAsyncSockN::GetCAsyncSockNotifier(m_hInst ,TRUE);
- m_AsyncNotifier->DoAsyncSelect((win_net*)this );
- #endif
- HX_RESULT ret = sockObj->HXlisten(get_sock(), backlog);
- if ( SUCCEEDED(ret) )
- {
- m_SocketState = CONN_LISTENNING;
- ret = HXR_OK;
- }
- else
- {
- ret = HXR_NET_SOCKET_INVALID;
- }
- return ret;
- }
- inline HX_RESULT win_net::blocking (void)
- {
- unsigned long nonblocking = 0;
- return sockObj->HXioctlsocket(get_sock(), FIONBIO, &nonblocking);
- }
-
- inline HX_RESULT win_net::nonblocking (void)
- {
- unsigned long nonblocking = 1;
- return sockObj->HXioctlsocket(get_sock(), FIONBIO, &nonblocking);
- }
- HX_RESULT win_net::connect_accept(ULONG32 ulPlatform, sockaddr_in addr)
- {
- m_hInst = (HINSTANCE)ulPlatform;
-
- CurrentAddr = addr.sin_addr.s_addr;
- // set up the new connection so it will use its own notifier.
- // now we want to add this so it will recieve messages.
- #ifndef WIN32_PLATFORM_PSPC
- m_AsyncNotifier = CAsyncSockN::GetCAsyncSockNotifier( m_hInst, TRUE);
- m_AsyncNotifier->DoAsyncSelect(this);
- #endif
- m_SocketState = CONN_OPEN;
- mConnectionOpen = 1;
- return HXR_OK;
- }
- CHXMapPtrToPtr win_net::zm_MapObjectsToWinsockTasks;
- CHXMapPtrToPtr win_net::zm_WinsockTasksRefCounts;
- int win_net::zm_LibRefCount = 0;
- BOOL win_net::IsWinsockAvailable(void* pObject)
- {
- BOOL bWinSockInitedForTask = FALSE;
- // First check to see that the drivers are loaded...
- //
- // NOTE: this doesn't include initializing Winsock for
- // the object's task...
- if(!OnlyOneOfThisInTheWholeProgram.IsInitialized())
- {
- OnlyOneOfThisInTheWholeProgram.Initialize();
- }
- if(OnlyOneOfThisInTheWholeProgram.IsInitialized())
- {
- zm_LibRefCount++;
-
- // Make sure Winsock is initialized for the object's task...
- // get current task.
- #if defined( WIN32 )
- void* ulTask = (void*)GetCurrentProcessId();
- #else
- void* ulTask = (void*)GetCurrentTask();
- #endif
- // add map of object (http or session) to task
- zm_MapObjectsToWinsockTasks[pObject] = ulTask;
- // bump up ref count for task
- void* pVoid;
- ULONG32 TaskRefCount = 0;
- if (zm_WinsockTasksRefCounts.Lookup(ulTask,pVoid))
- {
- TaskRefCount = (ULONG32)pVoid;
- }
- TaskRefCount++;
- bWinSockInitedForTask = TRUE;
- HX_ASSERT_VALID_PTR(sockObj);
- zm_WinsockTasksRefCounts[ulTask] = (void*)TaskRefCount;
- }
- return bWinSockInitedForTask;
- }
- BOOL win_net::ReleaseWinsockUsage(void* pObject)
- {
- // Only do any of this if we've first called IsWinsockAvailable()
- if (zm_LibRefCount > 0)
- {
- // get previous task from map of object (http or session) to task
- void* ulTask;
- if (zm_MapObjectsToWinsockTasks.Lookup(pObject,ulTask))
- {
- zm_MapObjectsToWinsockTasks.RemoveKey(pObject);
- // bump up ref count for task
- void* pVoid;
- ULONG32 TaskRefCount = 0;
- if (zm_WinsockTasksRefCounts.Lookup(ulTask,pVoid))
- {
- TaskRefCount = (ULONG32)pVoid;
- }
- TaskRefCount--;
- // if 0 then call WSACleanup
- if (TaskRefCount == 0)
- {
- zm_WinsockTasksRefCounts.RemoveKey(ulTask);
- }
- }
- // Decerement total ref count
- zm_LibRefCount--;
- }
- return TRUE;
- }
- HX_RESULT win_net::read(void * buf, UINT16 *len)
- {
- int got;
- static int breakpoint = 0;
- assert( buf );
- assert( len );
- // This DEBUGOUTSTR is noisy.
- #ifndef _DEMPSEY
- DEBUGOUTSTR( "win_net::read()rn" );
- #endif // !_DEMPSEY
- if (get_sock() == INVALID_SOCKET || !callRaConnect)
- {
- // Not connected
- return( mLastError = HXR_NET_SOCKET_INVALID );
- }
- // Is the TCP socket actually connected yet?
- /* We want to read data even if we have received CloseNotification.
- * This is because some unread data may be still be in the pipe
- * - RA 10/01/1997
- */
- if (m_SocketState != CONN_OPEN && m_SocketState != CONN_CLOSED)
- {
- // No
- // We won't be able to write anything here, so clear this
- // we'll return why we didn't write anything.
- *len = 0;
- switch( m_SocketState )
- {
- case CONN_DNS_INPROG:
- case CONN_CONNECT_INPROG:
- case CONN_CLOSING:
- return( mLastError = HXR_WOULD_BLOCK );
- case CONN_CLOSED:
- return( mLastError = HXR_NET_SOCKET_INVALID );
- case CONN_NO_CONN:
- #ifndef WIN32_PLATFORM_PSPC
- return( DoStartAsyncConn() );
- #else
- HX_ASSERT(0 && "No Async net");
- return( HXR_NET_READ );
- #endif
- case CONN_DNS_FAILED:
- return( mLastError = HXR_DNR );
- case CONN_CONNECT_FAILED:
- return( mLastError = HXR_NET_CONNECT );
- default:
- // HUH???
- HX_ASSERT (FALSE);
- return( mLastError = HXR_NET_READ );
- };
- }
- else
- {
- // Now we can actually do the read
- if (callRaConnect)
- {
- got = sockObj->HXrecv( get_sock(), (char *)buf, *len, 0 );
- }
- else
- {
- int fromlen;
- struct sockaddr from;
-
- fromlen = sizeof( from );
- got = sockObj->HXrecvfrom( get_sock(), (char *)buf, *len, 0, &from, &fromlen );
- if (got > 0) breakpoint++;
- }
- // Did we get an error?
- if (got == SOCKET_ERROR)
- {
- *len = 0;
- if (m_SocketState == CONN_CLOSED)
- {
- return( mLastError = HXR_NET_SOCKET_INVALID );
- }
- int code;
- code = sockObj->HXWSAGetLastError();
- // Translate the error
- switch (code)
- {
- case WSAEWOULDBLOCK:
- case WSAEINPROGRESS:
- return( mLastError = HXR_WOULD_BLOCK );
- case WSAEFAULT:
- case WSAENOTCONN:
- case WSAENOTSOCK:
- return( mLastError = HXR_NET_SOCKET_INVALID );
- case WSAENETDOWN:
- return( mLastError = HXR_GENERAL_NONET );
- case WSAEINTR:
- return( mLastError = HXR_BLOCK_CANCELED );
- case WSAEMSGSIZE:
- return( mLastError = HXR_MSG_TOOLARGE);
- case WSAETIMEDOUT:
- case WSAESHUTDOWN:
- case WSAECONNABORTED:
- return( mLastError = HXR_SERVER_DISCONNECTED );
- case WSAECONNRESET:
- /*
- * WinSock Recvfrom() Now Returns WSAECONNRESET Instead of Blocking or Timing Out (Q263823)
- * workaround
- */
- if (!m_bIgnoreWSAECONNRESET)
- {
- return( mLastError = HXR_SERVER_DISCONNECTED );
- }
- else
- {
- return( mLastError = HXR_WOULD_BLOCK );
- }
- default:
- return( mLastError = HXR_NET_READ ); // Error we don't know what to do about
- }
- // Shouldn't really get here
- return( mLastError );
- }
- else if (got == 0 && *len != 0)
- {
- *len = 0;
- if (m_SocketState == CONN_CLOSED)
- {
- return( mLastError = HXR_NET_SOCKET_INVALID );
- }
- else
- {
- return( mLastError = HXR_SERVER_DISCONNECTED );
- }
- }
- else
- {
- // This should be our exit point for successful read
- *len = got;
- return( HXR_OK );
- }
- }
- }
- HX_RESULT
- win_net::readfrom (REF(IHXBuffer*) pBuffer,
- REF(UINT32) ulAddress,
- REF(UINT16) ulPort)
- {
- int got = 0;
- UINT16 size = 0;
- #ifndef _DEMPSEY
- DEBUGOUTSTR( "win_net::readfrom()rn" );
- #endif // !_DEMPSEY
- pBuffer = NULL;
- ulAddress = 0;
- ulPort = 0;
- if (get_sock() == INVALID_SOCKET || callRaConnect)
- {
- // Not connected
- return( mLastError = HXR_NET_SOCKET_INVALID );
- }
- /* We want to read data even if we have received CloseNotification.
- * This is because some unread data may be still be in the pipe
- * - RA 10/01/1997
- */
- if (m_SocketState != CONN_OPEN && m_SocketState != CONN_CLOSED)
- {
- // No
- // We won't be able to write anything here, so clear this
- // we'll return why we didn't write anything.
- switch( m_SocketState )
- {
- case CONN_DNS_INPROG:
- case CONN_CONNECT_INPROG:
- case CONN_CLOSING:
- return( mLastError = HXR_WOULD_BLOCK );
- case CONN_CLOSED:
- return( mLastError = HXR_NET_SOCKET_INVALID );
- case CONN_NO_CONN:
- #ifndef WIN32_PLATFORM_PSPC
- return( DoStartAsyncConn() );
- #else
- HX_ASSERT(0 && "No Async net");
- return( HXR_NET_READ );
- #endif
- case CONN_DNS_FAILED:
- return( mLastError = HXR_DNR );
- case CONN_CONNECT_FAILED:
- return( mLastError = HXR_NET_CONNECT );
- default:
- // HUH???
- HX_ASSERT (FALSE);
- return( mLastError = HXR_NET_READ );
- };
- }
- else
- {
- int fromlen;
- struct sockaddr_in from;
-
- fromlen = sizeof( from );
- got = sockObj->HXrecvfrom( get_sock(), m_pInBuffer, TCP_BUF_SIZE, 0, (struct sockaddr*)&from, &fromlen );
- // Did we get an error?
- if (got == SOCKET_ERROR)
- {
- if (m_SocketState == CONN_CLOSED)
- {
- return( mLastError = HXR_NET_SOCKET_INVALID );
- }
- int code;
- code = sockObj->HXWSAGetLastError();
- // Translate the error
- switch (code)
- {
- case WSAEWOULDBLOCK:
- case WSAEINPROGRESS:
- return( mLastError = HXR_WOULD_BLOCK );
- case WSAEFAULT:
- case WSAENOTCONN:
- case WSAENOTSOCK:
- return( mLastError = HXR_NET_SOCKET_INVALID );
- case WSAENETDOWN:
- return( mLastError = HXR_GENERAL_NONET );
- case WSAEINTR:
- return( mLastError = HXR_BLOCK_CANCELED );
- case WSAEMSGSIZE:
- return( mLastError = HXR_MSG_TOOLARGE);
- case WSAETIMEDOUT:
- case WSAESHUTDOWN:
- case WSAECONNABORTED:
- return( mLastError = HXR_SERVER_DISCONNECTED );
- case WSAECONNRESET:
- /*
- * WinSock Recvfrom() Now Returns WSAECONNRESET Instead of Blocking or Timing Out (Q263823)
- * workaround
- */
- if (!m_bIgnoreWSAECONNRESET)
- {
- return( mLastError = HXR_SERVER_DISCONNECTED );
- }
- else
- {
- return( mLastError = HXR_WOULD_BLOCK );
- }
-
- default:
- return( mLastError = HXR_NET_READ ); // Error we don't know what to do about
- }
- // Shouldn't really get here
- return( mLastError );
- }
- else if (got == 0)
- {
- if (m_SocketState == CONN_CLOSED)
- {
- return( mLastError = HXR_NET_SOCKET_INVALID );
- }
- else
- {
- return( mLastError = HXR_SERVER_DISCONNECTED );
- }
- }
- else
- {
- // This should be our exit point for successful read
- CHXTimeStampedBuffer* pTimeBuffer = new CHXTimeStampedBuffer;
- pTimeBuffer->AddRef();
- pTimeBuffer->SetTimeStamp(HX_GET_TICKCOUNT());
- pTimeBuffer->Set((UCHAR*)m_pInBuffer, got);
- pBuffer = (IHXBuffer*) pTimeBuffer;
- ulAddress = DwToHost(from.sin_addr.s_addr);
- ulPort = WToHost(from.sin_port);
-
- return( HXR_OK );
- }
- }
- }
-
- ULONG32 win_net::get_addr()
- {
- hostent *pHost = (hostent *)m_AsyncAddress;
- ULONG32 addr = 0;
-
- // if CurrentAddr is set, we must have passed
- // a dotted IP address...
- if (CurrentAddr)
- {
- addr = CurrentAddr;
- }
- else if (pHost)
- {
- addr = (ULONG32) (*(ULONG32*)pHost->h_addr);
- }
- return addr;
- }
- UINT16 win_net::get_local_port()
- {
- sockaddr_in addr;
- int addr_len = sizeof addr;
- memset(&addr, 0, HX_SAFESIZE_T(addr_len));
- int ret = sockObj->HXgetsockname(get_sock(), (sockaddr*)&addr, &addr_len);
-
- return (ret < 0) ? -1: WToHost(addr.sin_port);
- }
- // we need it for dns_find_ip_addr since async stuff needs a window handle...
- HX_RESULT win_net::SetWindowHandle(ULONG32 handle)
- {
- m_hInst = (HINSTANCE)handle;
- return HXR_OK;
- }
- HX_RESULT win_net::dns_find_ip_addr(const char * host, UINT16 blocking)
- {
- if(!host)
- {
- mLastError = HXR_DNR;
- return mLastError;
- }
- if(get_sock() < 0)
- {
- mLastError = HXR_NET_SOCKET_INVALID;
- return mLastError;
- }
- if (conn::is_cached((char *) host, &mHostIPAddr))
- {
- mHostIPValid = TRUE;
- mDNSDone = TRUE;
- mLastError = HXR_OK;
- if (mCallBack)
- {
- mCallBack->Func(DNS_NOTIFICATION, TRUE);
- }
- return mLastError;
- }
- char* pTemp = strrchr(host, '.');
- if (pTemp && atoi(pTemp + 1))
- { /* IP address. */
- struct in_addr addr;
- mHostIPValid = FALSE;
- mHostIPAddr = 0;
- mDNSDone = TRUE;
- addr.s_addr = sockObj->HXinet_addr(host);
-
- if ((UINT)addr.s_addr == (UINT)-1)
- {
- mLastError = HXR_DNR;
- return mLastError;
- }
- mHostIPValid = TRUE;
- mHostIPAddr = *(ULONG32 *) &addr;
- conn::add_to_cache((char *) host, mHostIPAddr);
- if (mCallBack)
- {
- mCallBack->Func(DNS_NOTIFICATION, TRUE);
- }
- return HXR_OK;
- }
- if (blocking)
- {
- struct in_addr addr;
-
- mHostIPValid = FALSE;
- mHostIPAddr = 0;
- mDNSDone = TRUE;
- struct hostent *h = sockObj->HXgethostbyname(host);
-
- if (!h || !h->h_addr )
- {
- mLastError = HXR_DNR;
- return mLastError;
- }
- memcpy(&addr, h->h_addr, sizeof(struct in_addr)); /* Flawfinder: ignore */
- mHostIPValid = TRUE;
- mHostIPAddr = *(ULONG32 *) &addr;
- conn::add_to_cache((char *) host, mHostIPAddr);
- if (mCallBack)
- {
- mCallBack->Func(DNS_NOTIFICATION, TRUE);
- }
- return( mLastError = HXR_OK);
- }
- else
- {
- if (m_pAsyncHost != host)
- {
- // Save the parameters, and tell ourselves we're starting up
- HX_VECTOR_DELETE(m_pAsyncHost);
- m_pAsyncHost = ::new_string(host);
- }
- if (!m_AsyncAddress)
- {
- m_AsyncAddress = new char[MAXGETHOSTSTRUCT];
- }
- if (!m_AsyncAddress)
- {
- return (mLastError = HXR_OUTOFMEMORY);
- }
- // set the boolean variable that we are only doing async DNs and
- // do not intend to connect
- #ifndef WIN32_PLATFORM_PSPC
- m_DNSOnly = TRUE;
- m_AsyncNotifier = CAsyncSockN::GetCAsyncSockNotifier( m_hInst , TRUE);
- m_AsyncNotifier->DoAsyncDNS( this, m_pAsyncHost, m_AsyncAddress, MAXGETHOSTSTRUCT );
- m_SocketState = CONN_DNS_INPROG;
- #else
- m_DNSOnly = FALSE;
- #endif
- return( mLastError = HXR_WOULD_BLOCK );
- }
- }
- BOOL win_net::dns_ip_addr_found(BOOL * valid, ULONG32 *addr)
- {
- if (mDNSDone)
- {
- // reset DNS only flag...
- m_DNSOnly = FALSE;
- *valid = mHostIPValid;
- *addr = mHostIPAddr;
- return TRUE;
- }
- else
- return FALSE;
- }
- BOOL win_net::set_receive_buf_size(int DesiredSize)
- {
- int s = get_sock();
- if (s == INVALID_SOCKET)
- {
- mLastError = HXR_NET_SOCKET_INVALID;
- return FALSE;
- }
- int RcvBufSize = 0;
- int iSize = sizeof(RcvBufSize);
- if (sockObj->HXgetsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&RcvBufSize,
- &iSize))
- {
- RcvBufSize = 0;
- }
- if (RcvBufSize < DesiredSize)
- {
- RcvBufSize = DesiredSize;
- if(sockObj->HXsetsockopt(s, SOL_SOCKET, SO_RCVBUF,
- (char *)&RcvBufSize, sizeof(RcvBufSize)))
- {
- int code;
- code = sockObj->HXWSAGetLastError();
- return FALSE;
- }
- }
- return TRUE;
- }
- /*
- * reuse_addr/reuse_port has to be called before a sock binds. however,
- * socket is not available until it binds as it is implemented. So, set a
- * flag here and do the actual setsockopt right before a sock binds.
- * Look in init_win().
- */
- HX_RESULT
- win_net::reuse_addr(BOOL enable)
- {
- m_bReuseAddr = enable;
- return HXR_OK;
- }
- HX_RESULT
- win_net::reuse_port(BOOL enable)
- {
- m_bReusePort = enable;
- return HXR_OK;
- }
- HX_RESULT
- win_net::get_host_name(char* name, int namelen)
- {
- HX_ASSERT(sockObj);
-
- if (sockObj->HXgethostname(name, namelen) != 0)
- {
- return HXR_FAILED;
- }
- else
- {
- return HXR_OK;
- }
- }
- HX_RESULT
- win_net::get_host_by_name(char* name, REF(struct hostent*) h)
- {
- HX_ASSERT(sockObj);
-
- h = sockObj->HXgethostbyname(name);
- if (!h || !h->h_addr_list)
- {
- return HXR_DNR;
- }
- else
- {
- return HXR_OK;
- }
- }
- HX_RESULT win_UDP::set_broadcast(BOOL enable)
- {
- int ret;
- SOCKET s = get_sock();
- if(s == INVALID_SOCKET)
- {
- return( mLastError = HXR_NET_SOCKET_INVALID );
- }
- ret = sockObj->HXsetsockopt( s, SOL_SOCKET, SO_BROADCAST, (char*)&enable, sizeof(UINT32) );
- if(ret == -1)
- ret = HXR_BIND;
- return ret;
- }
- HX_RESULT
- win_UDP::set_send_size(UINT32 send_size)
- {
- int s = get_sock();
- int ret = 0;
- again:
- ret = sockObj->HXsetsockopt(s, SOL_SOCKET, SO_SNDBUF,
- (char*)&send_size, sizeof(INT32));
- if (ret < 0 && send_size > 8192)
- {
- send_size >>= 1;
- goto again;
- }
- return ret;
- }
- HX_RESULT win_UDP::connect(const char* host, UINT16 port, UINT16 blocking, ULONG32 ulPlatform )
- {
- HX_RESULT ret;
- if (get_sock() < 0 && (ret = init(INADDR_ANY, 0, blocking)) != HXR_OK)
- {
- if(ret == HXR_BLOCK_CANCELED)
- return ret;
-
- mLastError = HXR_NET_CONNECT;
- return mLastError;
- }
- return win_net::connect(host, port, blocking, ulPlatform );
- }
- HX_RESULT win_UDP::SetWindowHandle(ULONG32 handle)
- {
- m_hInst = (HINSTANCE)handle;
- #ifndef WIN32_PLATFORM_PSPC
- m_AsyncNotifier = CAsyncSockN::GetCAsyncSockNotifier( m_hInst ,TRUE);
- m_AsyncNotifier->DoAsyncSelect( this );
- #endif
- return HXR_OK;
- }
- HX_RESULT win_UDP::connect(sockaddr_in * addr, UINT16 blocking)
- {
- HX_RESULT ret;
- if (get_sock() < 0 && (ret = init(INADDR_ANY, 0, blocking)) != HXR_OK)
- {
- if(ret == HXR_BLOCK_CANCELED)
- return ret;
-
- mLastError = HXR_NET_CONNECT;
- return mLastError;
- }
- return win_net::connect(addr);
- }
- HX_RESULT win_TCP::connect(const char* host, UINT16 port, UINT16 blocking, ULONG32 ulPlatform )
- {
- HX_RESULT ret;
- if (get_sock() < 0 && (ret = init(INADDR_ANY, 0, blocking)) != HXR_OK)
- {
- if(ret == HXR_BLOCK_CANCELED)
- return ret;
-
- mLastError = HXR_NET_CONNECT;
- return mLastError;
- }
- return win_net::connect(host, port, blocking, ulPlatform );
- }
- HX_RESULT win_TCP::connect(sockaddr_in * addr, UINT16 blocking)
- {
- HX_RESULT ret;
- if (get_sock() < 0 && (ret = init(INADDR_ANY, 0, blocking)) != HXR_OK)
- {
- if(ret == HXR_BLOCK_CANCELED)
- return ret;
-
- mLastError = HXR_NET_CONNECT;
- return mLastError;
- }
- return win_net::connect(addr);
- }
- inline HX_RESULT win_UDP::listen(ULONG32 ulLocalAddr, UINT16 port,
- UINT16 backlog, UINT16 blocking,
- ULONG32 ulPlatform)
- {
- return HXR_INVALID_OPERATION;
- }
- inline HX_RESULT win_TCP::listen(ULONG32 ulLocalAddr, UINT16 port,
- UINT16 backlog, UINT16 blocking,
- ULONG32 ulPlatform)
- {
- HX_RESULT ret = HXR_NET_SOCKET_INVALID;
- if ( get_sock() < 0 )
- {
- if ( ulLocalAddr == HX_INADDR_ANY )
- ret = init(INADDR_ANY, port, blocking);
- else
- ret = init(ulLocalAddr, port, blocking);
- }
- if ( FAILED(ret) )
- {
- if(ret == HXR_BLOCK_CANCELED)
- return ret;
- mLastError = HXR_NET_SOCKET_INVALID;
- return mLastError;
- }
- return win_net::listen(ulLocalAddr, port, backlog, blocking, ulPlatform);
- }
- HX_RESULT
- win_UDP::set_multicast()
- {
- #ifdef NO_MULTICAST
- return HXR_MULTICAST_UDP;
- #else
- INT32 ret;
- sockaddr_in addr;
- int addr_len = sizeof addr;
- if (get_sock() == INVALID_SOCKET)
- {
- // Not connected
- return( mLastError = HXR_NET_SOCKET_INVALID );
- }
- memset(&addr, 0, HX_SAFESIZE_T(addr_len));
- ret = sockObj->HXgetsockname(get_sock(), (sockaddr*)&addr, &addr_len);
- if (ret < 0)
- {
- return HXR_MULTICAST_UDP;
- }
- ret = sockObj->HXsetsockopt(get_sock(), IPPROTO_IP, IP_MULTICAST_IF,
- (char*) &addr.sin_addr.s_addr,
- sizeof (addr.sin_addr.s_addr));
- if (ret < 0)
- {
- return HXR_MULTICAST_UDP;
- }
- return HXR_OK;
- #endif /* NO_MULTICAST */
- }
- HX_RESULT
- win_UDP::set_multicast_ttl(unsigned char ttl)
- {
- #ifdef NO_MULTICAST
- return HXR_MULTICAST_UDP;
- #else
- if (get_sock() == INVALID_SOCKET)
- {
- // Not connected
- return( mLastError = HXR_NET_SOCKET_INVALID );
- }
-
- INT32 ret;
- INT32 ttl_proxy = ttl;
- ret = sockObj->HXsetsockopt(get_sock(), IPPROTO_IP, IP_MULTICAST_TTL,
- (char*) &ttl_proxy, sizeof (ttl_proxy));
- if (ret < 0)
- {
- return HXR_MULTICAST_UDP;
- }
- return HXR_OK;
- #endif /* ! NO_MULTICAST */
- }
- HX_RESULT win_UDP::join_multicast_group(ULONG32 addr, ULONG32 if_addr)
- {
- int ret;
- ip_mreq multicast_group;
- if (get_sock() == INVALID_SOCKET)
- {
- // Not connected
- return( mLastError = HXR_NET_SOCKET_INVALID );
- }
-
- multicast_group.imr_multiaddr.s_addr = sockObj->HXhtonl(addr);
- multicast_group.imr_interface.s_addr = sockObj->HXhtonl(if_addr);
-
- ret = sockObj->HXsetsockopt(get_sock(), IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&multicast_group , sizeof (multicast_group) );
- if (ret == -1)
- {
- int err;
- err = sockObj->HXWSAGetLastError();
- return HXR_MULTICAST_JOIN;
- }
- return HXR_OK;
- }
- HX_RESULT win_UDP::leave_multicast_group(ULONG32 addr, ULONG32 if_addr)
- {
- int ret;
- ip_mreq multicast_group;
- if (get_sock() == INVALID_SOCKET)
- {
- // Not connected
- return( mLastError = HXR_NET_SOCKET_INVALID );
- }
- multicast_group.imr_multiaddr.s_addr = sockObj->HXhtonl(addr);
- // multicast_group.imr_multiaddr.s_addr = sockObj->HXinet_addr("226.0.0.8");
- multicast_group.imr_interface.s_addr = sockObj->HXhtonl(if_addr);
-
- ret = sockObj->HXsetsockopt(get_sock(), IPPROTO_IP, IP_DROP_MEMBERSHIP, (char*)&multicast_group , sizeof (multicast_group) );
- if (ret == -1)
- {
- return HXR_GENERAL_MULTICAST;
- }
- return HXR_OK;
- }
- HX_RESULT
- win_UDP::set_multicast_if(ULONG32 ulInterface)
- {
- int ret;
- int s = get_sock();
- if(s == INVALID_SOCKET)
- {
- return( mLastError = HXR_NET_SOCKET_INVALID );
- }
- unsigned long addr = sockObj->HXhtonl(ulInterface);
- ret = sockObj->HXsetsockopt(s, IPPROTO_IP, IP_MULTICAST_IF,
- (char*)&addr, sizeof(addr));
- if(ret == -1)
- ret = HXR_GENERAL_MULTICAST;
- return ret;
- }
- HX_RESULT
- win_UDP::GetFromInfo(ULONG32& ulAddr, UINT16& nPort)
- {
- return HXR_OK;
- }
- WinsockManager::WinsockManager()
- {
- bInitialized = FALSE;
- Initialize();
- }
- WinsockManager::~WinsockManager()
- {
- conn::close_drivers(NULL);
- bInitialized = FALSE;
- }
- void
- WinsockManager::Initialize()
- {
- bInitialized = FALSE;
- HX_ASSERT(!sockObj);
- if(!sockObj)
- sockObj = new CHXSock;
- if(conn::init_drivers(NULL) != HXR_OK)
- return;
- if(sockObj && sockObj->WinSockAvail() && sockObj->InitWinsock())
- {
- bInitialized = TRUE;
- }
- UINT8 nWinSockVersion = sockObj->HXGetVersion();
- /*
- * Check to see what platform we are on
- */
- OSVERSIONINFO winver;
- winver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- #ifndef WIN32_PLATFORM_PSPC
- if(GetVersionEx(&winver))
- {
- if(nWinSockVersion == 2 &&
- winver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS &&
- winver.dwMinorVersion == 0)
- {
- /*
- * Async lookup in Win 95 with WinSock2.0 installed returns the same handle for
- * multiple requests. If there are multiple outstanding requests, there is
- * no way to map the handle in the response to the outstansing request since
- * all replies get mapped to one request. NT 4.0 returns different handles so
- * name resolution works fine.
- *
- * We workaround this by queueing up the DNS requests.
- */
- sockGlobals.m_bWinSock2Suck = TRUE;
- }
- }
- #endif
- }
- BOOL
- WinsockManager::IsInitialized()
- {
- return bInitialized && sockObj;
- }