.H
/*
******************************************
* winSocket.h - Header file for winSocket *
* Winsock API wrapper class *
* Ryan Lederman ryan@winprog.org *
* January 2002 *
* THIS CODE IS FREE *
* *
****************************************** */
#ifndef _WINSOCKET_H
#define _WINSOCKET_H
#include " winsock.h "
#include " winbase.h "
#define ERR_SUCCESS 0x00000000 // Successful
#define ERR_BADPARAM 0x80000001 // Bad argument passed
#define ERR_WSAERROR 0x80000002 // Need to get_LastError()
#define ERR_MAXLENGTH 512
class winSocket // Definition of winSocket
{
public : // Public Methods
winSocket::winSocket(); // Constructor
winSocket:: ~ winSocket(); // Destructor
int Create( void ); // Creates the socket
int Close( void ); // Closes the socket
int Connect( char * strRemote, unsigned int iPort ); // Connects the socket to a remote site
int Send( SOCKET s, char * strData, int iLen ); // Sends data
int Send( char * strData, int iLen );
int Receive( SOCKET s, char * strData, int iLen ); // Receives data
int Receive( char * strData, int iLen );
int Listen( int iQueuedConnections ); // Listen for connections
int Bind( char * strIP, unsigned int iPort ); // Binds to a port
int Accept( SOCKET s ); // Accepts a connection
int asyncSelect( HWND hWnd, // Allows calling window to receive
unsigned int wMsg, long lEvent ); // notifications (non-blocking sockets)
int get_LocalIP( char * strIP ); // Returns local IP address
int get_LocalPort( int * iPort ); // Returns local Port number
int get_RemoteIP( char * strIP ); // Returns remote side IP
int get_RemotePort( int * iPort ); // Returns remote side Port number
int get_LocalHost( char * strBuffer, int iBufLen ); // Returns local host name
int get_RemoteHost( char * strBuffer, int iBufLen ); // Returns remote host name
void get_LastError( char * strBuffer, int * iErrNum ); // Returns error information
int set_SendTimeout( int ms ); // Sets send timeout, in milliseconds
int set_RecvTimeout( int ms ); // Sets recv timeout, in milliseconds
void longToDottedQuad( unsigned long ulLong, char * cBuffer ); // 32-bit long -> dotted quad
private : // Private Methods
void winSocket::set_LastError( char * newError, int errNum ); // Sets last error information
private : // Private Members
struct sockaddr_in m_sockaddr; // Holds all data associated with socket
struct sockaddr_in m_rsockaddr; // Holds data associated with remote side
WORD m_wVersion; // Version to use when calling WSAStartup
char m_LastError[ERR_MAXLENGTH + 1 ]; // Buffer that holds last error
int m_ErrorNumber; // Last error number
public : // Public Members
SOCKET m_hSocket; // Underlying SOCKET object
};
#endif /* _WINSOCKET_H */
* winSocket.h - Header file for winSocket *
* Winsock API wrapper class *
* Ryan Lederman ryan@winprog.org *
* January 2002 *
* THIS CODE IS FREE *
* *
****************************************** */
#ifndef _WINSOCKET_H
#define _WINSOCKET_H
#include " winsock.h "
#include " winbase.h "
#define ERR_SUCCESS 0x00000000 // Successful
#define ERR_BADPARAM 0x80000001 // Bad argument passed
#define ERR_WSAERROR 0x80000002 // Need to get_LastError()
#define ERR_MAXLENGTH 512
class winSocket // Definition of winSocket
{
public : // Public Methods
winSocket::winSocket(); // Constructor
winSocket:: ~ winSocket(); // Destructor
int Create( void ); // Creates the socket
int Close( void ); // Closes the socket
int Connect( char * strRemote, unsigned int iPort ); // Connects the socket to a remote site
int Send( SOCKET s, char * strData, int iLen ); // Sends data
int Send( char * strData, int iLen );
int Receive( SOCKET s, char * strData, int iLen ); // Receives data
int Receive( char * strData, int iLen );
int Listen( int iQueuedConnections ); // Listen for connections
int Bind( char * strIP, unsigned int iPort ); // Binds to a port
int Accept( SOCKET s ); // Accepts a connection
int asyncSelect( HWND hWnd, // Allows calling window to receive
unsigned int wMsg, long lEvent ); // notifications (non-blocking sockets)
int get_LocalIP( char * strIP ); // Returns local IP address
int get_LocalPort( int * iPort ); // Returns local Port number
int get_RemoteIP( char * strIP ); // Returns remote side IP
int get_RemotePort( int * iPort ); // Returns remote side Port number
int get_LocalHost( char * strBuffer, int iBufLen ); // Returns local host name
int get_RemoteHost( char * strBuffer, int iBufLen ); // Returns remote host name
void get_LastError( char * strBuffer, int * iErrNum ); // Returns error information
int set_SendTimeout( int ms ); // Sets send timeout, in milliseconds
int set_RecvTimeout( int ms ); // Sets recv timeout, in milliseconds
void longToDottedQuad( unsigned long ulLong, char * cBuffer ); // 32-bit long -> dotted quad
private : // Private Methods
void winSocket::set_LastError( char * newError, int errNum ); // Sets last error information
private : // Private Members
struct sockaddr_in m_sockaddr; // Holds all data associated with socket
struct sockaddr_in m_rsockaddr; // Holds data associated with remote side
WORD m_wVersion; // Version to use when calling WSAStartup
char m_LastError[ERR_MAXLENGTH + 1 ]; // Buffer that holds last error
int m_ErrorNumber; // Last error number
public : // Public Members
SOCKET m_hSocket; // Underlying SOCKET object
};
#endif /* _WINSOCKET_H */
.CPP
/*
******************************************
* winSocket.cpp - Implementation of *
* winSocket Winsock API wrapper class *
* Ryan Lederman ryan@winprog.org *
* January 2002 *
* THIS CODE IS FREE *
* *
****************************************** */
#include " winSocket.h "
winSocket::winSocket() : m_hSocket( 0 ),
m_wVersion( 0 ),
m_ErrorNumber( 0 )
{
WSADATA wsaD; // Structure initialsed by WSAStartup
m_wVersion = MAKEWORD( 2 , 2 ); // Version number requested
memset( m_LastError, 0 , ERR_MAXLENGTH ); // Nullify last error
memset( & m_sockaddr, 0 , sizeof ( m_sockaddr ) ); // Nullify structures
memset( & m_rsockaddr, 0 , sizeof ( m_rsockaddr ) );
int result = WSAStartup( m_wVersion, & wsaD ); // Initialize Winsock
if ( result != 0 ) // WSAStartup failed
{
set_LastError( " WSAStartup failed! " , WSAGetLastError() );
return ;
}
}
winSocket:: ~ winSocket() { WSACleanup(); /* Un-initialise Winsock */ }
int winSocket::Create( void )
{
/* *************************************
* FUNCTION: Create *
* *
* PURPOSE: Initializes the underlying *
* SOCKET object for the class. *
* *
* RETURNS: ERR_WSAERROR upon error, *
* otherwise ERR_SUCCESS *
* *
************************************** */
if ( (m_hSocket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP )) == INVALID_SOCKET )
{
set_LastError( " socket() failed " , WSAGetLastError() );
return ERR_WSAERROR;
}
return ERR_SUCCESS;
}
int winSocket::Close( void )
{
/* ***************************************
* FUNCTION: Close *
* *
* PURPOSE: Closes the underlying *
* SOCKET object. Does not destroy class *
* *
* RETURNS: ERR_WSAERROR upon error, *
* otherwise ERR_SUCCESS *
* *
**************************************** */
if ( closesocket( m_hSocket ) == SOCKET_ERROR )
{
set_LastError( " closesocket() failed " , WSAGetLastError() );
return ERR_WSAERROR;
}
memset( & m_sockaddr, 0 , sizeof ( sockaddr_in ) );
memset( & m_rsockaddr, 0 , sizeof ( sockaddr_in ) );
return ERR_SUCCESS;
}
int winSocket::Connect( char * strRemote, unsigned int iPort )
{
/* ****************************************
* FUNCTION: Connect *
* *
* PURPOSE: Establishes TCP/IP connection *
* with remote host (strRemote) on port *
* # (iPort) *
* *
* RETURNS: ERR_BADPARAM for invalid *
* parameters, ERR_WSAERROR upon error, *
* otherwise ERR_SUCCESS *
* *
***************************************** */
if ( strlen( strRemote ) == 0 || iPort == 0 )
return ERR_BADPARAM;
hostent * hostEnt = NULL;
long lIPAddress = 0 ;
hostEnt = gethostbyname( strRemote );
if ( hostEnt != NULL )
{
lIPAddress = ((in_addr * )hostEnt -> h_addr) -> s_addr;
m_sockaddr.sin_addr.s_addr = lIPAddress;
}
else
{
m_sockaddr.sin_addr.s_addr = inet_addr( strRemote );
}
m_sockaddr.sin_family = AF_INET;
m_sockaddr.sin_port = htons( iPort );
if ( connect( m_hSocket, (SOCKADDR * ) & m_sockaddr, sizeof ( m_sockaddr ) ) == SOCKET_ERROR )
{
set_LastError( " connect() failed " , WSAGetLastError() );
return ERR_WSAERROR;
}
return ERR_SUCCESS;
}
int winSocket::Listen( int iQueuedConnections )
{
/* ****************************************
* FUNCTION: Listen *
* *
* PURPOSE: Places the SOCKET in the *
* listening state. Requires that Bind() *
* be called previously. *
* *
* RETURNS: ERR_BADPARAM for invalid *
* parameters, ERR_WSAERROR upon error, *
* otherwise ERR_SUCCESS *
* *
***************************************** */
if ( iQueuedConnections == 0 )
return ERR_BADPARAM;
if ( listen( m_hSocket, iQueuedConnections ) == SOCKET_ERROR )
{
set_LastError( " listen() failed " , WSAGetLastError() );
return ERR_WSAERROR;
}
return ERR_SUCCESS;
}
int winSocket::Send( SOCKET s, char * strData, int iLen )
{
/* *********************************************
* FUNCTION: Send *
* *
* PURPOSE: Sends data (strData) to remote *
* side on socket s. *
* *
* RETURNS: ERR_BADPARAM for invalid *
* parameters, ERR_WSAERROR upon error, *
* otherwise ERR_SUCCESS *
* *
********************************************** */
if ( strData == NULL || iLen == 0 )
return ERR_BADPARAM;
if ( send( s, strData, iLen, 0 ) == SOCKET_ERROR )
{
set_LastError( " send() failed " , WSAGetLastError() );
return ERR_WSAERROR;
}
return ERR_SUCCESS;
}
int winSocket::Send( char * strData, int iLen )
{
/* *********************************************
* FUNCTION: Send *
* *
* PURPOSE: Sends data (strData) to remote *
* side on an established TCP/IP connection. *
* Requires that Connect be called previously. *
* *
* RETURNS: ERR_BADPARAM for invalid *
* parameters, ERR_WSAERROR upon error, *
* otherwise ERR_SUCCESS *
* *
********************************************** */
if ( strData == NULL || iLen == 0 )
return ERR_BADPARAM;
if ( send( m_hSocket, strData, iLen, 0 ) == SOCKET_ERROR )
{
set_LastError( " send() failed " , WSAGetLastError() );
return ERR_WSAERROR;
}
return ERR_SUCCESS;
}
int winSocket::Receive( SOCKET s, char * strData, int iLen )
{
/* **********************************************
* FUNCTION: Receive *
* *
* PURPOSE: Retreives data from incoming queue *
* and copies to (strData). (iLen) will contain *
* the length of data read in bytes *
* *
* RETURNS: ERR_BADPARAM for invalid *
* parameters, ERR_WSAERROR upon error, *
* otherwise passes what recv() returns. *
* *
********************************************** */
if ( strData == NULL )
return ERR_BADPARAM;
int len = 0 ;
int ret = 0 ;
ret = recv( s, strData, iLen, 0 );
if ( ret == SOCKET_ERROR )
{
set_LastError( " recv() failed " , WSAGetLastError() );
return ERR_WSAERROR;
}
return ret;
}
int winSocket::Receive( char * strData, int iLen )
{
/* **********************************************
* FUNCTION: Receive *
* *
* PURPOSE: Retreives data from incoming queue *
* and copies to (strData). (iLen) will contain *
* the length of data read in bytes *
* *
* RETURNS: ERR_BADPARAM for invalid *
* parameters, ERR_WSAERROR upon error, *
* otherwise passes what recv() returns. *
* *
********************************************** */
if ( strData == NULL )
return ERR_BADPARAM;
int len = 0 ;
int ret = 0 ;
ret = recv( m_hSocket, strData, iLen, 0 );
if ( ret == SOCKET_ERROR )
{
set_LastError( " recv() failed " , WSAGetLastError() );
return ERR_WSAERROR;
}
return ret;
}
int winSocket::Bind( char * strIP, unsigned int iPort )
{
/* ***********************************************
* FUNCTION: Bind *
* *
* PURPOSE: Associates the SOCKET object with an *
* IP address (strIP) and port number (iPort) *
* *
* RETURNS: ERR_BADPARAM for invalid *
* parameters, ERR_WSAERROR upon error, *
* otherwise ERR_SUCCESS *
* *
*********************************************** */
if ( strlen( strIP ) == 0 || iPort == 0 )
return ERR_BADPARAM;
memset( & m_sockaddr, 0 , sizeof ( m_sockaddr ) );
m_sockaddr.sin_family = AF_INET;
m_sockaddr.sin_addr.s_addr = inet_addr( strIP );
m_sockaddr.sin_port = htons( iPort );
if ( bind( m_hSocket, (SOCKADDR * ) & m_sockaddr, sizeof ( m_sockaddr ) ) == SOCKET_ERROR )
{
set_LastError( " bind() failed " , WSAGetLastError() );
return ERR_WSAERROR;
}
return ERR_SUCCESS;
}
int winSocket::Accept( SOCKET s )
{
/* **************************************************
* FUNCTION: Accept *
* *
* PURPOSE: Initializes the SOCKET object (if not *
* previously initialized), associates the SOCKET *
* object with the IP address and port of the *
* remote side, and accepts an incoming connection. *
* Usually called from a Window Procedure using *
* wParam as the argument. *
* *
* RETURNS: ERR_WSAERROR upon error, *
* otherwise ERR_SUCCESS *
* *
*************************************************** */
int Len = sizeof ( m_rsockaddr );
memset( & m_rsockaddr, 0 , sizeof ( m_rsockaddr ) );
if ( ( m_hSocket = accept( s, (SOCKADDR * ) & m_rsockaddr, & Len ) ) == INVALID_SOCKET )
{
set_LastError( " accept() failed " , WSAGetLastError() );
return ERR_WSAERROR;
}
return ERR_SUCCESS;
}
int winSocket::asyncSelect( HWND hWnd, unsigned int wMsg, long lEvent )
{
/* *************************************************
* FUNCTION: asyncSelect *
* *
* PURPOSE: Enables Windows Messaging notification *
* for the object. (wMsg) will be sent to the *
* Window Procedure of (hWnd) whenever one of the *
* events in (lEvent) has occurred. See MSDN docs *
* for WSAAsyncSelect() for more information. *
* *
* RETURNS: ERR_BADPARAM for invalid *
* parameters, ERR_WSAERROR upon error, *
* otherwise ERR_SUCCESS *
* *
************************************************** */
if ( ! IsWindow( hWnd ) || wMsg == 0 || lEvent == 0 )
return ERR_BADPARAM;
if ( WSAAsyncSelect( m_hSocket, hWnd, wMsg, lEvent ) == SOCKET_ERROR )
{
set_LastError( " WSAAsyncSelect() failed " , WSAGetLastError() );
return ERR_WSAERROR;
}
return ERR_SUCCESS;
}
int winSocket::get_RemoteIP( char * strIP )
{
/* ************************************************
* FUNCTION: get_RemoteIP *
* *
* PURPOSE: Copies the IP address for the remote *
* side on an established TCP/IP connection into *
* (strIP). *
* *
* RETURNS: ERR_BADPARAM for invalid parameters, *
* ERR_WSAERROR upon error, otherwise ERR_SUCCESS *
* *
************************************************* */
if ( strIP == NULL )
return ERR_BADPARAM;
int namelen = sizeof ( m_rsockaddr );
if ( getpeername( m_hSocket, (SOCKADDR * ) & m_rsockaddr, & namelen ) == SOCKET_ERROR )
{
set_LastError( " getpeername() failed " , WSAGetLastError() );
return ERR_WSAERROR;
}
longToDottedQuad( m_rsockaddr.sin_addr.s_addr, strIP );
return ERR_SUCCESS;
}
int winSocket::get_RemotePort( int * iPort )
{
/* ************************************************
* FUNCTION: get_RemotePort *
* *
* PURPOSE: Copies the port number for the remote *
* side on an established TCP/IP connection into *
* (iPort). *
* *
* RETURNS: ERR_BADPARAM for invalid parameters, *
* ERR_WSAERROR upon error, otherwise ERR_SUCCESS *
* *
************************************************* */
if ( iPort == NULL )
return ERR_BADPARAM;
int namelen = sizeof ( m_rsockaddr );
if ( getpeername( m_hSocket, (SOCKADDR * ) & m_rsockaddr, & namelen ) == SOCKET_ERROR )
{
set_LastError( " getpeername() failed " , WSAGetLastError() );
return ERR_WSAERROR;
}
* iPort = ntohs( m_rsockaddr.sin_port );
return ERR_SUCCESS;
}
int winSocket::get_LocalHost( char * strBuffer, int iBufLen )
{
/* ************************************************
* FUNCTION: get_LocalHost *
* *
* PURPOSE: Copies the fully qualified host name *
* for the local machine into (strBuffer). Will *
* fail if returned data is longer than (iBufLen).*
* *
* RETURNS: ERR_BADPARAM for invalid parameters, *
* ERR_WSAERROR upon error, otherwise ERR_SUCCESS *
* *
************************************************* */
if ( strBuffer == NULL )
return ERR_BADPARAM;
char strHost[ 512 ] = { 0 };
hostent * hostEnt = NULL;
int iLen = 0 ;
gethostname( strHost, 512 );
hostEnt = gethostbyname( strHost );
if ( hostEnt == NULL )
return ERR_WSAERROR;
iLen = strlen( hostEnt -> h_name );
if ( iLen > iBufLen )
return ERR_BADPARAM;
memset( strBuffer, 0 , iBufLen );
memcpy( strBuffer, hostEnt -> h_name, iLen );
return ERR_SUCCESS;
}
int winSocket::get_RemoteHost( char * strBuffer, int iBufLen )
{
/* ************************************************
* FUNCTION: get_RemoteHost *
* *
* PURPOSE: Copies the fully qualified host name *
* of the remote side (on a connected socket) *
* into (strBuffer). Will fail if data returned *
* is longer than iBufLen. *
* *
* RETURNS: ERR_BADPARAM for invalid parameters, *
* ERR_WSAERROR upon error, otherwise ERR_SUCCESS *
* *
************************************************* */
if ( strBuffer == NULL )
return ERR_BADPARAM;
hostent * hostEnt = NULL;
int iLen = 0 ;
int namelen = sizeof ( m_rsockaddr );
if ( getpeername( m_hSocket, (SOCKADDR * ) & m_rsockaddr, & namelen ) == SOCKET_ERROR )
return ERR_WSAERROR;
hostEnt = gethostbyaddr( ( char * ) & m_rsockaddr.sin_addr.s_addr, 4 ,PF_INET );
if ( hostEnt != NULL )
{
iLen = strlen( hostEnt -> h_name );
if ( iLen > iBufLen )
return ERR_BADPARAM;
memcpy( strBuffer, hostEnt -> h_name, iLen );
return ERR_SUCCESS;
}
return ERR_WSAERROR;
}
int winSocket::get_LocalIP( char * strIP )
{
/* ************************************************
* FUNCTION: get_LocalIP *
* *
* PURPOSE: Copies the IP address for the local *
* machine into (strIP). Requires that Connect or *
* Bind be called previously *
* *
* RETURNS: ERR_BADPARAM for invalid parameters, *
* otherwise ERR_SUCCESS *
* *
************************************************* */
if ( strIP == NULL )
return ERR_BADPARAM;
int namelen = sizeof ( m_sockaddr );
HOSTENT * hEnt = NULL;
char szHostName[ 512 ] = { 0 };
char szIP[ 16 ] = { 0 };
char szAddrField[ 4 ] = { 0 };
unsigned int ufield = 0 ;
if ( getsockname( m_hSocket, (SOCKADDR * ) & m_sockaddr, & namelen ) == SOCKET_ERROR )
return ERR_WSAERROR;
longToDottedQuad( m_sockaddr.sin_addr.s_addr, strIP );
return ERR_SUCCESS;
}
int winSocket::get_LocalPort( int * iPort )
{
/* ****************************************************
* FUNCTION: get_LocalPort *
* *
* PURPOSE: Copies the local port number associated *
* with the SOCKET object into (iPort). *
* Requires that Connect or Bind be called previously *
* *
* RETURNS: ERR_BADPARAM for invalid parameters, *
* otherwise ERR_SUCCESS *
* *
***************************************************** */
if ( iPort == NULL )
return ERR_BADPARAM;
* iPort = ntohs(m_sockaddr.sin_port);
return ERR_SUCCESS;
}
int winSocket::set_SendTimeout( int ms )
{
/* ****************************************************
* FUNCTION: set_SendTimeout *
* *
* PURPOSE: Sets the amount of time the socket will *
* wait before returning WSAETIMEDOUT when calling *
* Send(). Set to 0 for infinite (default) *
* *
* RETURNS: ERR_BADPARAM for invalid parameters, *
* ERR_WSAERROR for a winsock error, *
* otherwise ERR_SUCCESS *
* *
***************************************************** */
if ( ms < 0 )
return ERR_BADPARAM;
if ( setsockopt( m_hSocket, SOL_SOCKET, SO_SNDTIMEO, ( char * ) & ms, sizeof ( ms ) ) == SOCKET_ERROR )
{
set_LastError( " setsockopt() failed. " , WSAGetLastError() );
return ERR_WSAERROR;
}
return ERR_SUCCESS;
}
int winSocket::set_RecvTimeout( int ms )
{
/* ****************************************************
* FUNCTION: set_RecvTimeout *
* *
* PURPOSE: Sets the amount of time the socket will *
* wait before returning WSAETIMEDOUT when calling *
* Receive(). Set to 0 for infinite (default) *
* *
* RETURNS: ERR_BADPARAM for invalid parameters, *
* ERR_WSAERROR for a winsock error, *
* otherwise ERR_SUCCESS *
* *
***************************************************** */
if ( ms < 0 )
return ERR_BADPARAM;
if ( setsockopt( m_hSocket, SOL_SOCKET, SO_RCVTIMEO, ( char * ) & ms, sizeof ( ms ) ) == SOCKET_ERROR )
{
set_LastError( " setsockopt() failed. " , WSAGetLastError() );
return ERR_WSAERROR;
}
return ERR_SUCCESS;
}
void winSocket::set_LastError( char * newError, int errNum )
{
/* *************************************************
* FUNCTION: set_LastError *
* *
* PURPOSE: Sets error information for the object. *
* *
* RETURNS: None. *
* *
************************************************** */
memset( m_LastError, 0 , ERR_MAXLENGTH );
memcpy( m_LastError, newError, strlen( newError ) );
m_LastError[strlen(newError) + 1 ] = ' \0 ' ;
m_ErrorNumber = errNum;
}
void winSocket::get_LastError( char * strBuffer, int * iErrNum )
{
/* **************************************************
* FUNCTION: get_LastError *
* *
* PURPOSE: Retreives description and number of the *
* last error that occurred. Copies into (strBuffer)*
* and (iErrNum), repsectively. *
* *
* RETURNS: None. *
* *
*************************************************** */
int len = strlen( m_LastError );
if ( len > 0 )
{
memset( strBuffer, 0 , len );
memcpy( strBuffer, m_LastError, len );
strBuffer[len + 1 ] = ' \0 ' ;
* iErrNum = m_ErrorNumber;
}
}
void winSocket::longToDottedQuad( unsigned long ulLong, char * cBuffer )
{
/* ****************************************************
* FUNCTION: longToDottedQuad *
* *
* PURPOSE: Translates an IP address from 32-bit long *
* to dotted quad form (255.255.255.255). Translates *
* (ulLong) and copies results to (cBuffer). *
* *
* RETURNS: None. *
* *
***************************************************** */
wsprintf( cBuffer, " %d.%d.%d.%d " ,( int )((BYTE * ) & ulLong)[ 0 ],
( int )((BYTE * ) & ulLong)[ 1 ],( int )((BYTE * ) & ulLong)[ 2 ],( int )((BYTE * ) & ulLong)[ 3 ] );
}
* winSocket.cpp - Implementation of *
* winSocket Winsock API wrapper class *
* Ryan Lederman ryan@winprog.org *
* January 2002 *
* THIS CODE IS FREE *
* *
****************************************** */
#include " winSocket.h "
winSocket::winSocket() : m_hSocket( 0 ),
m_wVersion( 0 ),
m_ErrorNumber( 0 )
{
WSADATA wsaD; // Structure initialsed by WSAStartup
m_wVersion = MAKEWORD( 2 , 2 ); // Version number requested
memset( m_LastError, 0 , ERR_MAXLENGTH ); // Nullify last error
memset( & m_sockaddr, 0 , sizeof ( m_sockaddr ) ); // Nullify structures
memset( & m_rsockaddr, 0 , sizeof ( m_rsockaddr ) );
int result = WSAStartup( m_wVersion, & wsaD ); // Initialize Winsock
if ( result != 0 ) // WSAStartup failed
{
set_LastError( " WSAStartup failed! " , WSAGetLastError() );
return ;
}
}
winSocket:: ~ winSocket() { WSACleanup(); /* Un-initialise Winsock */ }
int winSocket::Create( void )
{
/* *************************************
* FUNCTION: Create *
* *
* PURPOSE: Initializes the underlying *
* SOCKET object for the class. *
* *
* RETURNS: ERR_WSAERROR upon error, *
* otherwise ERR_SUCCESS *
* *
************************************** */
if ( (m_hSocket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP )) == INVALID_SOCKET )
{
set_LastError( " socket() failed " , WSAGetLastError() );
return ERR_WSAERROR;
}
return ERR_SUCCESS;
}
int winSocket::Close( void )
{
/* ***************************************
* FUNCTION: Close *
* *
* PURPOSE: Closes the underlying *
* SOCKET object. Does not destroy class *
* *
* RETURNS: ERR_WSAERROR upon error, *
* otherwise ERR_SUCCESS *
* *
**************************************** */
if ( closesocket( m_hSocket ) == SOCKET_ERROR )
{
set_LastError( " closesocket() failed " , WSAGetLastError() );
return ERR_WSAERROR;
}
memset( & m_sockaddr, 0 , sizeof ( sockaddr_in ) );
memset( & m_rsockaddr, 0 , sizeof ( sockaddr_in ) );
return ERR_SUCCESS;
}
int winSocket::Connect( char * strRemote, unsigned int iPort )
{
/* ****************************************
* FUNCTION: Connect *
* *
* PURPOSE: Establishes TCP/IP connection *
* with remote host (strRemote) on port *
* # (iPort) *
* *
* RETURNS: ERR_BADPARAM for invalid *
* parameters, ERR_WSAERROR upon error, *
* otherwise ERR_SUCCESS *
* *
***************************************** */
if ( strlen( strRemote ) == 0 || iPort == 0 )
return ERR_BADPARAM;
hostent * hostEnt = NULL;
long lIPAddress = 0 ;
hostEnt = gethostbyname( strRemote );
if ( hostEnt != NULL )
{
lIPAddress = ((in_addr * )hostEnt -> h_addr) -> s_addr;
m_sockaddr.sin_addr.s_addr = lIPAddress;
}
else
{
m_sockaddr.sin_addr.s_addr = inet_addr( strRemote );
}
m_sockaddr.sin_family = AF_INET;
m_sockaddr.sin_port = htons( iPort );
if ( connect( m_hSocket, (SOCKADDR * ) & m_sockaddr, sizeof ( m_sockaddr ) ) == SOCKET_ERROR )
{
set_LastError( " connect() failed " , WSAGetLastError() );
return ERR_WSAERROR;
}
return ERR_SUCCESS;
}
int winSocket::Listen( int iQueuedConnections )
{
/* ****************************************
* FUNCTION: Listen *
* *
* PURPOSE: Places the SOCKET in the *
* listening state. Requires that Bind() *
* be called previously. *
* *
* RETURNS: ERR_BADPARAM for invalid *
* parameters, ERR_WSAERROR upon error, *
* otherwise ERR_SUCCESS *
* *
***************************************** */
if ( iQueuedConnections == 0 )
return ERR_BADPARAM;
if ( listen( m_hSocket, iQueuedConnections ) == SOCKET_ERROR )
{
set_LastError( " listen() failed " , WSAGetLastError() );
return ERR_WSAERROR;
}
return ERR_SUCCESS;
}
int winSocket::Send( SOCKET s, char * strData, int iLen )
{
/* *********************************************
* FUNCTION: Send *
* *
* PURPOSE: Sends data (strData) to remote *
* side on socket s. *
* *
* RETURNS: ERR_BADPARAM for invalid *
* parameters, ERR_WSAERROR upon error, *
* otherwise ERR_SUCCESS *
* *
********************************************** */
if ( strData == NULL || iLen == 0 )
return ERR_BADPARAM;
if ( send( s, strData, iLen, 0 ) == SOCKET_ERROR )
{
set_LastError( " send() failed " , WSAGetLastError() );
return ERR_WSAERROR;
}
return ERR_SUCCESS;
}
int winSocket::Send( char * strData, int iLen )
{
/* *********************************************
* FUNCTION: Send *
* *
* PURPOSE: Sends data (strData) to remote *
* side on an established TCP/IP connection. *
* Requires that Connect be called previously. *
* *
* RETURNS: ERR_BADPARAM for invalid *
* parameters, ERR_WSAERROR upon error, *
* otherwise ERR_SUCCESS *
* *
********************************************** */
if ( strData == NULL || iLen == 0 )
return ERR_BADPARAM;
if ( send( m_hSocket, strData, iLen, 0 ) == SOCKET_ERROR )
{
set_LastError( " send() failed " , WSAGetLastError() );
return ERR_WSAERROR;
}
return ERR_SUCCESS;
}
int winSocket::Receive( SOCKET s, char * strData, int iLen )
{
/* **********************************************
* FUNCTION: Receive *
* *
* PURPOSE: Retreives data from incoming queue *
* and copies to (strData). (iLen) will contain *
* the length of data read in bytes *
* *
* RETURNS: ERR_BADPARAM for invalid *
* parameters, ERR_WSAERROR upon error, *
* otherwise passes what recv() returns. *
* *
********************************************** */
if ( strData == NULL )
return ERR_BADPARAM;
int len = 0 ;
int ret = 0 ;
ret = recv( s, strData, iLen, 0 );
if ( ret == SOCKET_ERROR )
{
set_LastError( " recv() failed " , WSAGetLastError() );
return ERR_WSAERROR;
}
return ret;
}
int winSocket::Receive( char * strData, int iLen )
{
/* **********************************************
* FUNCTION: Receive *
* *
* PURPOSE: Retreives data from incoming queue *
* and copies to (strData). (iLen) will contain *
* the length of data read in bytes *
* *
* RETURNS: ERR_BADPARAM for invalid *
* parameters, ERR_WSAERROR upon error, *
* otherwise passes what recv() returns. *
* *
********************************************** */
if ( strData == NULL )
return ERR_BADPARAM;
int len = 0 ;
int ret = 0 ;
ret = recv( m_hSocket, strData, iLen, 0 );
if ( ret == SOCKET_ERROR )
{
set_LastError( " recv() failed " , WSAGetLastError() );
return ERR_WSAERROR;
}
return ret;
}
int winSocket::Bind( char * strIP, unsigned int iPort )
{
/* ***********************************************
* FUNCTION: Bind *
* *
* PURPOSE: Associates the SOCKET object with an *
* IP address (strIP) and port number (iPort) *
* *
* RETURNS: ERR_BADPARAM for invalid *
* parameters, ERR_WSAERROR upon error, *
* otherwise ERR_SUCCESS *
* *
*********************************************** */
if ( strlen( strIP ) == 0 || iPort == 0 )
return ERR_BADPARAM;
memset( & m_sockaddr, 0 , sizeof ( m_sockaddr ) );
m_sockaddr.sin_family = AF_INET;
m_sockaddr.sin_addr.s_addr = inet_addr( strIP );
m_sockaddr.sin_port = htons( iPort );
if ( bind( m_hSocket, (SOCKADDR * ) & m_sockaddr, sizeof ( m_sockaddr ) ) == SOCKET_ERROR )
{
set_LastError( " bind() failed " , WSAGetLastError() );
return ERR_WSAERROR;
}
return ERR_SUCCESS;
}
int winSocket::Accept( SOCKET s )
{
/* **************************************************
* FUNCTION: Accept *
* *
* PURPOSE: Initializes the SOCKET object (if not *
* previously initialized), associates the SOCKET *
* object with the IP address and port of the *
* remote side, and accepts an incoming connection. *
* Usually called from a Window Procedure using *
* wParam as the argument. *
* *
* RETURNS: ERR_WSAERROR upon error, *
* otherwise ERR_SUCCESS *
* *
*************************************************** */
int Len = sizeof ( m_rsockaddr );
memset( & m_rsockaddr, 0 , sizeof ( m_rsockaddr ) );
if ( ( m_hSocket = accept( s, (SOCKADDR * ) & m_rsockaddr, & Len ) ) == INVALID_SOCKET )
{
set_LastError( " accept() failed " , WSAGetLastError() );
return ERR_WSAERROR;
}
return ERR_SUCCESS;
}
int winSocket::asyncSelect( HWND hWnd, unsigned int wMsg, long lEvent )
{
/* *************************************************
* FUNCTION: asyncSelect *
* *
* PURPOSE: Enables Windows Messaging notification *
* for the object. (wMsg) will be sent to the *
* Window Procedure of (hWnd) whenever one of the *
* events in (lEvent) has occurred. See MSDN docs *
* for WSAAsyncSelect() for more information. *
* *
* RETURNS: ERR_BADPARAM for invalid *
* parameters, ERR_WSAERROR upon error, *
* otherwise ERR_SUCCESS *
* *
************************************************** */
if ( ! IsWindow( hWnd ) || wMsg == 0 || lEvent == 0 )
return ERR_BADPARAM;
if ( WSAAsyncSelect( m_hSocket, hWnd, wMsg, lEvent ) == SOCKET_ERROR )
{
set_LastError( " WSAAsyncSelect() failed " , WSAGetLastError() );
return ERR_WSAERROR;
}
return ERR_SUCCESS;
}
int winSocket::get_RemoteIP( char * strIP )
{
/* ************************************************
* FUNCTION: get_RemoteIP *
* *
* PURPOSE: Copies the IP address for the remote *
* side on an established TCP/IP connection into *
* (strIP). *
* *
* RETURNS: ERR_BADPARAM for invalid parameters, *
* ERR_WSAERROR upon error, otherwise ERR_SUCCESS *
* *
************************************************* */
if ( strIP == NULL )
return ERR_BADPARAM;
int namelen = sizeof ( m_rsockaddr );
if ( getpeername( m_hSocket, (SOCKADDR * ) & m_rsockaddr, & namelen ) == SOCKET_ERROR )
{
set_LastError( " getpeername() failed " , WSAGetLastError() );
return ERR_WSAERROR;
}
longToDottedQuad( m_rsockaddr.sin_addr.s_addr, strIP );
return ERR_SUCCESS;
}
int winSocket::get_RemotePort( int * iPort )
{
/* ************************************************
* FUNCTION: get_RemotePort *
* *
* PURPOSE: Copies the port number for the remote *
* side on an established TCP/IP connection into *
* (iPort). *
* *
* RETURNS: ERR_BADPARAM for invalid parameters, *
* ERR_WSAERROR upon error, otherwise ERR_SUCCESS *
* *
************************************************* */
if ( iPort == NULL )
return ERR_BADPARAM;
int namelen = sizeof ( m_rsockaddr );
if ( getpeername( m_hSocket, (SOCKADDR * ) & m_rsockaddr, & namelen ) == SOCKET_ERROR )
{
set_LastError( " getpeername() failed " , WSAGetLastError() );
return ERR_WSAERROR;
}
* iPort = ntohs( m_rsockaddr.sin_port );
return ERR_SUCCESS;
}
int winSocket::get_LocalHost( char * strBuffer, int iBufLen )
{
/* ************************************************
* FUNCTION: get_LocalHost *
* *
* PURPOSE: Copies the fully qualified host name *
* for the local machine into (strBuffer). Will *
* fail if returned data is longer than (iBufLen).*
* *
* RETURNS: ERR_BADPARAM for invalid parameters, *
* ERR_WSAERROR upon error, otherwise ERR_SUCCESS *
* *
************************************************* */
if ( strBuffer == NULL )
return ERR_BADPARAM;
char strHost[ 512 ] = { 0 };
hostent * hostEnt = NULL;
int iLen = 0 ;
gethostname( strHost, 512 );
hostEnt = gethostbyname( strHost );
if ( hostEnt == NULL )
return ERR_WSAERROR;
iLen = strlen( hostEnt -> h_name );
if ( iLen > iBufLen )
return ERR_BADPARAM;
memset( strBuffer, 0 , iBufLen );
memcpy( strBuffer, hostEnt -> h_name, iLen );
return ERR_SUCCESS;
}
int winSocket::get_RemoteHost( char * strBuffer, int iBufLen )
{
/* ************************************************
* FUNCTION: get_RemoteHost *
* *
* PURPOSE: Copies the fully qualified host name *
* of the remote side (on a connected socket) *
* into (strBuffer). Will fail if data returned *
* is longer than iBufLen. *
* *
* RETURNS: ERR_BADPARAM for invalid parameters, *
* ERR_WSAERROR upon error, otherwise ERR_SUCCESS *
* *
************************************************* */
if ( strBuffer == NULL )
return ERR_BADPARAM;
hostent * hostEnt = NULL;
int iLen = 0 ;
int namelen = sizeof ( m_rsockaddr );
if ( getpeername( m_hSocket, (SOCKADDR * ) & m_rsockaddr, & namelen ) == SOCKET_ERROR )
return ERR_WSAERROR;
hostEnt = gethostbyaddr( ( char * ) & m_rsockaddr.sin_addr.s_addr, 4 ,PF_INET );
if ( hostEnt != NULL )
{
iLen = strlen( hostEnt -> h_name );
if ( iLen > iBufLen )
return ERR_BADPARAM;
memcpy( strBuffer, hostEnt -> h_name, iLen );
return ERR_SUCCESS;
}
return ERR_WSAERROR;
}
int winSocket::get_LocalIP( char * strIP )
{
/* ************************************************
* FUNCTION: get_LocalIP *
* *
* PURPOSE: Copies the IP address for the local *
* machine into (strIP). Requires that Connect or *
* Bind be called previously *
* *
* RETURNS: ERR_BADPARAM for invalid parameters, *
* otherwise ERR_SUCCESS *
* *
************************************************* */
if ( strIP == NULL )
return ERR_BADPARAM;
int namelen = sizeof ( m_sockaddr );
HOSTENT * hEnt = NULL;
char szHostName[ 512 ] = { 0 };
char szIP[ 16 ] = { 0 };
char szAddrField[ 4 ] = { 0 };
unsigned int ufield = 0 ;
if ( getsockname( m_hSocket, (SOCKADDR * ) & m_sockaddr, & namelen ) == SOCKET_ERROR )
return ERR_WSAERROR;
longToDottedQuad( m_sockaddr.sin_addr.s_addr, strIP );
return ERR_SUCCESS;
}
int winSocket::get_LocalPort( int * iPort )
{
/* ****************************************************
* FUNCTION: get_LocalPort *
* *
* PURPOSE: Copies the local port number associated *
* with the SOCKET object into (iPort). *
* Requires that Connect or Bind be called previously *
* *
* RETURNS: ERR_BADPARAM for invalid parameters, *
* otherwise ERR_SUCCESS *
* *
***************************************************** */
if ( iPort == NULL )
return ERR_BADPARAM;
* iPort = ntohs(m_sockaddr.sin_port);
return ERR_SUCCESS;
}
int winSocket::set_SendTimeout( int ms )
{
/* ****************************************************
* FUNCTION: set_SendTimeout *
* *
* PURPOSE: Sets the amount of time the socket will *
* wait before returning WSAETIMEDOUT when calling *
* Send(). Set to 0 for infinite (default) *
* *
* RETURNS: ERR_BADPARAM for invalid parameters, *
* ERR_WSAERROR for a winsock error, *
* otherwise ERR_SUCCESS *
* *
***************************************************** */
if ( ms < 0 )
return ERR_BADPARAM;
if ( setsockopt( m_hSocket, SOL_SOCKET, SO_SNDTIMEO, ( char * ) & ms, sizeof ( ms ) ) == SOCKET_ERROR )
{
set_LastError( " setsockopt() failed. " , WSAGetLastError() );
return ERR_WSAERROR;
}
return ERR_SUCCESS;
}
int winSocket::set_RecvTimeout( int ms )
{
/* ****************************************************
* FUNCTION: set_RecvTimeout *
* *
* PURPOSE: Sets the amount of time the socket will *
* wait before returning WSAETIMEDOUT when calling *
* Receive(). Set to 0 for infinite (default) *
* *
* RETURNS: ERR_BADPARAM for invalid parameters, *
* ERR_WSAERROR for a winsock error, *
* otherwise ERR_SUCCESS *
* *
***************************************************** */
if ( ms < 0 )
return ERR_BADPARAM;
if ( setsockopt( m_hSocket, SOL_SOCKET, SO_RCVTIMEO, ( char * ) & ms, sizeof ( ms ) ) == SOCKET_ERROR )
{
set_LastError( " setsockopt() failed. " , WSAGetLastError() );
return ERR_WSAERROR;
}
return ERR_SUCCESS;
}
void winSocket::set_LastError( char * newError, int errNum )
{
/* *************************************************
* FUNCTION: set_LastError *
* *
* PURPOSE: Sets error information for the object. *
* *
* RETURNS: None. *
* *
************************************************** */
memset( m_LastError, 0 , ERR_MAXLENGTH );
memcpy( m_LastError, newError, strlen( newError ) );
m_LastError[strlen(newError) + 1 ] = ' \0 ' ;
m_ErrorNumber = errNum;
}
void winSocket::get_LastError( char * strBuffer, int * iErrNum )
{
/* **************************************************
* FUNCTION: get_LastError *
* *
* PURPOSE: Retreives description and number of the *
* last error that occurred. Copies into (strBuffer)*
* and (iErrNum), repsectively. *
* *
* RETURNS: None. *
* *
*************************************************** */
int len = strlen( m_LastError );
if ( len > 0 )
{
memset( strBuffer, 0 , len );
memcpy( strBuffer, m_LastError, len );
strBuffer[len + 1 ] = ' \0 ' ;
* iErrNum = m_ErrorNumber;
}
}
void winSocket::longToDottedQuad( unsigned long ulLong, char * cBuffer )
{
/* ****************************************************
* FUNCTION: longToDottedQuad *
* *
* PURPOSE: Translates an IP address from 32-bit long *
* to dotted quad form (255.255.255.255). Translates *
* (ulLong) and copies results to (cBuffer). *
* *
* RETURNS: None. *
* *
***************************************************** */
wsprintf( cBuffer, " %d.%d.%d.%d " ,( int )((BYTE * ) & ulLong)[ 0 ],
( int )((BYTE * ) & ulLong)[ 1 ],( int )((BYTE * ) & ulLong)[ 2 ],( int )((BYTE * ) & ulLong)[ 3 ] );
}