433 lines
11 KiB
C++
433 lines
11 KiB
C++
//-----------------------------------------------------------------------------
|
|
// File: XbSocket.cpp
|
|
//
|
|
// Desc: Wraps SOCKET object
|
|
//
|
|
// Hist: 05.17.01 - New for June XDK release
|
|
// 08.08.01 - Moved to common framework
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//-----------------------------------------------------------------------------
|
|
#include "XbSocket.h"
|
|
#include <cassert>
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: CXBSocket()
|
|
// Desc: Associate existing socket with object. Object will close the socket
|
|
// when it is destroyed.
|
|
//-----------------------------------------------------------------------------
|
|
CXBSocket::CXBSocket( SOCKET sock )
|
|
:
|
|
m_Socket( sock )
|
|
{
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: CXBSocket()
|
|
// Desc: Create a socket of the given type
|
|
//-----------------------------------------------------------------------------
|
|
CXBSocket::CXBSocket( SocketType type )
|
|
:
|
|
m_Socket( INVALID_SOCKET )
|
|
{
|
|
BOOL bSuccess = Open( type );
|
|
assert( bSuccess );
|
|
(VOID)bSuccess;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: CXBSocket()
|
|
// Desc: Create a socket of the given type/protocol
|
|
//-----------------------------------------------------------------------------
|
|
CXBSocket::CXBSocket( INT iType, INT iProtocol )
|
|
:
|
|
m_Socket( INVALID_SOCKET )
|
|
{
|
|
BOOL bSuccess = Open( iType, iProtocol );
|
|
assert( bSuccess );
|
|
(VOID)bSuccess;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: ~CXBSocket()
|
|
// Desc: Close and release socket
|
|
//-----------------------------------------------------------------------------
|
|
CXBSocket::~CXBSocket()
|
|
{
|
|
Close();
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Open()
|
|
// Desc: Open a socket of the given type
|
|
//-----------------------------------------------------------------------------
|
|
BOOL CXBSocket::Open( SocketType type )
|
|
{
|
|
switch( type )
|
|
{
|
|
case Type_UDP:
|
|
return Open( SOCK_DGRAM, IPPROTO_UDP );
|
|
|
|
case Type_TCP:
|
|
return Open( SOCK_STREAM, IPPROTO_TCP );
|
|
|
|
default:
|
|
assert( type == Type_VDP );
|
|
return Open( SOCK_DGRAM, IPPROTO_VDP );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Open()
|
|
// Desc: Open a socket of the given type/protocol
|
|
//-----------------------------------------------------------------------------
|
|
BOOL CXBSocket::Open( INT iType, INT iProtocol )
|
|
{
|
|
Close();
|
|
m_Socket = socket( AF_INET, iType, iProtocol );
|
|
return( m_Socket != INVALID_SOCKET );
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: IsOpen()
|
|
// Desc: TRUE if socket is open
|
|
//-----------------------------------------------------------------------------
|
|
BOOL CXBSocket::IsOpen() const
|
|
{
|
|
return( m_Socket != INVALID_SOCKET );
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Close()
|
|
// Desc: Close socket
|
|
//-----------------------------------------------------------------------------
|
|
INT CXBSocket::Close()
|
|
{
|
|
INT iResult = 0;
|
|
if( m_Socket != INVALID_SOCKET )
|
|
{
|
|
iResult = closesocket( m_Socket );
|
|
m_Socket = INVALID_SOCKET;
|
|
}
|
|
return iResult;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Accept()
|
|
// Desc: Permit incoming connection attempt
|
|
//-----------------------------------------------------------------------------
|
|
SOCKET CXBSocket::Accept( SOCKADDR_IN* pSockAddr )
|
|
{
|
|
assert( m_Socket != INVALID_SOCKET );
|
|
INT iSize = sizeof( SOCKADDR_IN );
|
|
|
|
SOCKET sockResult = accept( m_Socket, (sockaddr*)(pSockAddr), &iSize );
|
|
|
|
if( sockResult != INVALID_SOCKET && pSockAddr != NULL )
|
|
assert( iSize == sizeof( SOCKADDR_IN ) );
|
|
return sockResult;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Bind()
|
|
// Desc: Associate local address with socket
|
|
//-----------------------------------------------------------------------------
|
|
INT CXBSocket::Bind( const SOCKADDR_IN* pSockAddr )
|
|
{
|
|
assert( m_Socket != INVALID_SOCKET );
|
|
assert( pSockAddr != NULL );
|
|
assert( pSockAddr->sin_family == AF_INET );
|
|
|
|
INT iResult = bind( m_Socket, (const sockaddr*)(pSockAddr),
|
|
sizeof( SOCKADDR_IN ) );
|
|
return iResult;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Connect()
|
|
// Desc: Connect socket
|
|
//-----------------------------------------------------------------------------
|
|
INT CXBSocket::Connect( const SOCKADDR_IN* pSockAddr )
|
|
{
|
|
assert( m_Socket != INVALID_SOCKET );
|
|
assert( pSockAddr != NULL );
|
|
assert( pSockAddr->sin_family == AF_INET );
|
|
|
|
INT iResult = connect( m_Socket, (const sockaddr*)(pSockAddr),
|
|
sizeof( SOCKADDR_IN ) );
|
|
return iResult;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: GetSocket()
|
|
// Desc: Returns the socket handle
|
|
//-----------------------------------------------------------------------------
|
|
SOCKET CXBSocket::GetSocket() const
|
|
{
|
|
return m_Socket;
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: GetSockName()
|
|
// Desc: Get socket "name"
|
|
//-----------------------------------------------------------------------------
|
|
INT CXBSocket::GetSockName( SOCKADDR_IN* pSockAddr ) const
|
|
{
|
|
assert( m_Socket != INVALID_SOCKET );
|
|
assert( pSockAddr != NULL );
|
|
INT iSize = sizeof( SOCKADDR_IN );
|
|
|
|
INT iResult = getsockname( m_Socket, (sockaddr*)(pSockAddr), &iSize );
|
|
|
|
if( iResult != SOCKET_ERROR )
|
|
assert( iSize == sizeof( SOCKADDR_IN ) );
|
|
return iResult;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: GetSockOpt()
|
|
// Desc: Get socket option
|
|
//-----------------------------------------------------------------------------
|
|
INT CXBSocket::GetSockOpt( INT iLevel, INT iName, VOID* pValue, INT* piSize ) const
|
|
{
|
|
assert( m_Socket != INVALID_SOCKET );
|
|
assert( pValue != NULL );
|
|
assert( piSize != NULL );
|
|
|
|
INT iResult = getsockopt( m_Socket, iLevel, iName, (CHAR*)(pValue), piSize );
|
|
return iResult;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: IoCtlSocket()
|
|
// Desc: Configure socket I/O mode
|
|
//-----------------------------------------------------------------------------
|
|
INT CXBSocket::IoCtlSocket( LONG nCmd, DWORD* pArg )
|
|
{
|
|
assert( m_Socket != INVALID_SOCKET );
|
|
assert( pArg != NULL );
|
|
|
|
INT iResult = ioctlsocket( m_Socket, nCmd, pArg );
|
|
return iResult;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Listen()
|
|
// Desc: Listen for incoming connection
|
|
//-----------------------------------------------------------------------------
|
|
INT CXBSocket::Listen( INT iBacklog )
|
|
{
|
|
assert( m_Socket != INVALID_SOCKET );
|
|
|
|
INT iResult = listen( m_Socket, iBacklog );
|
|
return iResult;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Recv()
|
|
// Desc: Receive data on socket
|
|
//-----------------------------------------------------------------------------
|
|
INT CXBSocket::Recv( VOID* pBuffer, INT iBytes )
|
|
{
|
|
assert( m_Socket != INVALID_SOCKET );
|
|
assert( pBuffer != NULL );
|
|
assert( iBytes >= 0 );
|
|
|
|
INT iResult = recv( m_Socket, (CHAR*)(pBuffer), iBytes, 0 );
|
|
return iResult;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: RecvFrom()
|
|
// Desc: Receive data on socket and report source address
|
|
//-----------------------------------------------------------------------------
|
|
INT CXBSocket::RecvFrom( VOID* pBuffer, INT iBytes, SOCKADDR_IN* pSockAddr )
|
|
{
|
|
assert( m_Socket != INVALID_SOCKET );
|
|
assert( pBuffer != NULL );
|
|
assert( iBytes >= 0 );
|
|
INT iSize = sizeof( SOCKADDR_IN );
|
|
|
|
INT iResult = recvfrom( m_Socket, (CHAR*)(pBuffer), iBytes, 0,
|
|
(sockaddr*)(pSockAddr), &iSize );
|
|
if( iResult != SOCKET_ERROR && pSockAddr != NULL )
|
|
assert( iSize == sizeof( SOCKADDR_IN ) );
|
|
|
|
return iResult;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Select()
|
|
// Desc: Does a select call to check status of socket - returns separate
|
|
// BOOLs for read, write, and error
|
|
//-----------------------------------------------------------------------------
|
|
INT CXBSocket::Select( BOOL* pbRead, BOOL* pbWrite, BOOL* pbError )
|
|
{
|
|
assert( m_Socket != INVALID_SOCKET );
|
|
|
|
INT iResultTotal = 0;
|
|
|
|
timeval tv = {0};
|
|
if( pbRead )
|
|
{
|
|
fd_set fdsRead = {0};
|
|
FD_SET( m_Socket, &fdsRead );
|
|
|
|
INT iResult = select( 0, &fdsRead, NULL, NULL, &tv );
|
|
assert( iResult != SOCKET_ERROR );
|
|
|
|
*pbRead = ( iResult == 1 );
|
|
iResultTotal += iResult;
|
|
}
|
|
|
|
if( pbWrite )
|
|
{
|
|
fd_set fdsWrite = {0};
|
|
FD_SET( m_Socket, &fdsWrite );
|
|
|
|
INT iResult = select( 0, NULL, &fdsWrite, NULL, &tv );
|
|
assert( iResult != SOCKET_ERROR );
|
|
|
|
*pbWrite = ( iResult == 1 );
|
|
iResultTotal += iResult;
|
|
}
|
|
|
|
if( pbError )
|
|
{
|
|
fd_set fdsError = {0};
|
|
FD_SET( m_Socket, &fdsError );
|
|
|
|
INT iResult = select( 0, NULL, NULL, &fdsError, &tv );
|
|
assert( iResult != SOCKET_ERROR );
|
|
|
|
*pbError = ( iResult == 1 );
|
|
iResultTotal += iResult;
|
|
}
|
|
|
|
return iResultTotal;
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Send()
|
|
// Desc: Send data on socket
|
|
//-----------------------------------------------------------------------------
|
|
INT CXBSocket::Send( const VOID* pBuffer, INT iBytes )
|
|
{
|
|
assert( m_Socket != INVALID_SOCKET );
|
|
assert( pBuffer != NULL );
|
|
assert( iBytes >= 0 );
|
|
|
|
INT iResult = send( m_Socket, (const CHAR*)(pBuffer), iBytes, 0 );
|
|
return iResult;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: SendTo()
|
|
// Desc: Send data on socket to specific destination
|
|
//-----------------------------------------------------------------------------
|
|
INT CXBSocket::SendTo( const VOID* pBuffer, INT iBytes, const SOCKADDR_IN* pSockAddr )
|
|
{
|
|
assert( m_Socket != INVALID_SOCKET );
|
|
assert( pBuffer != NULL );
|
|
assert( iBytes >= 0 );
|
|
|
|
INT iResult = sendto( m_Socket, (const CHAR*)(pBuffer), iBytes, 0,
|
|
(const sockaddr*)(pSockAddr), sizeof( SOCKADDR_IN ) );
|
|
return iResult;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: SetSockOpt()
|
|
// Desc: Set socket option
|
|
//-----------------------------------------------------------------------------
|
|
INT CXBSocket::SetSockOpt( INT iLevel, INT iName, const VOID* pValue, INT iBytes )
|
|
{
|
|
assert( m_Socket != INVALID_SOCKET );
|
|
assert( pValue != NULL );
|
|
|
|
INT iResult = setsockopt( m_Socket, iLevel, iName, (const CHAR*)(pValue),
|
|
iBytes );
|
|
return iResult;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Shutdown()
|
|
// Desc: Disabled sending and/or receiving on socket
|
|
//-----------------------------------------------------------------------------
|
|
INT CXBSocket::Shutdown( INT iHow )
|
|
{
|
|
assert( m_Socket != INVALID_SOCKET );
|
|
|
|
INT iResult = shutdown( m_Socket, iHow );
|
|
return iResult;
|
|
}
|