.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] );
}