267 lines
6 KiB
C
267 lines
6 KiB
C
|
/*************************************************************************************************\
|
||
|
*
|
||
|
* SOCKETS.C
|
||
|
*
|
||
|
* This file contains routines used for establishing Sockets connections.
|
||
|
*
|
||
|
\*************************************************************************************************/
|
||
|
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include <winsock.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include "gutils.h"
|
||
|
|
||
|
|
||
|
/* ---- Local variables and #defines ----
|
||
|
*/
|
||
|
|
||
|
WSADATA WSAData;
|
||
|
|
||
|
|
||
|
#define MAX_PENDING_CONNECTS 4 /* The backlog allowed for listen() */
|
||
|
|
||
|
static PCHAR DBG_WSAERRORTEXT = "%s failed at line %d in %s: Error %d\n";
|
||
|
|
||
|
#define WSAERROR(func) \
|
||
|
// ERROR(( DBG_WSAERRORTEXT, func, __LINE__, __FILE__, WSAGetLastError() ))
|
||
|
|
||
|
|
||
|
|
||
|
/* Error message macro:
|
||
|
*/
|
||
|
#ifdef SOCKETS
|
||
|
#undef SOCKETS
|
||
|
#endif
|
||
|
#define SOCKETS( args ) DBGMSG( DBG_SOCKETS, args )
|
||
|
|
||
|
|
||
|
/* ---- Local function prototypes ----
|
||
|
*/
|
||
|
|
||
|
|
||
|
|
||
|
/* ---- Function definitions ----
|
||
|
*/
|
||
|
|
||
|
/****************************************************************************\
|
||
|
*
|
||
|
* FUNCTION: FillAddr(HWND, PSOCKADDR_IN, LPSTR)
|
||
|
*
|
||
|
* PURPOSE: Retrieves the IP address and port number.
|
||
|
*
|
||
|
* COMMENTS:
|
||
|
* This function is called in two conditions.
|
||
|
* 1.) When a client is preparing to call connect(), or
|
||
|
* 2.) When a server host is going to call bind(), listen() and
|
||
|
* accept().
|
||
|
* In both situations, a SOCKADDR_IN structure is filled.
|
||
|
* However, different fields are filled depending on the condition.
|
||
|
*
|
||
|
* ASSUMPTION:
|
||
|
* bConnect determines if the socket address is being set up for a listen()
|
||
|
* (bConnect == TRUE) or a connect() (bConnect == FALSE)
|
||
|
*
|
||
|
*
|
||
|
*\***************************************************************************/
|
||
|
BOOL
|
||
|
FillAddr(
|
||
|
HWND hWnd,
|
||
|
PSOCKADDR_IN psin,
|
||
|
LPSTR pServerName
|
||
|
)
|
||
|
{
|
||
|
DWORD dwSize;
|
||
|
PHOSTENT phe;
|
||
|
char szTemp[200];
|
||
|
CHAR szBuff[80];
|
||
|
|
||
|
psin->sin_family = AF_INET;
|
||
|
|
||
|
/*
|
||
|
** If we are setting up for a listen() call (pServerName == NULL),
|
||
|
** fill servent with our address.
|
||
|
*/
|
||
|
if (!pServerName)
|
||
|
{
|
||
|
/*
|
||
|
** Retrieve my ip address. Assuming the hosts file in
|
||
|
** in %systemroot%/system/drivers/etc/hosts contains my computer name.
|
||
|
*/
|
||
|
|
||
|
dwSize = sizeof(szBuff);
|
||
|
GetComputerName(szBuff, &dwSize);
|
||
|
CharLowerBuff( szBuff, dwSize );
|
||
|
|
||
|
}
|
||
|
|
||
|
/* gethostbyname() fails if the remote name is in upper-case characters!
|
||
|
*/
|
||
|
else
|
||
|
{
|
||
|
strcpy( szBuff, pServerName );
|
||
|
CharLowerBuff( szBuff, strlen( szBuff ) );
|
||
|
}
|
||
|
|
||
|
phe = gethostbyname(szBuff);
|
||
|
if (phe == NULL) {
|
||
|
|
||
|
wsprintf( szTemp, "%d is the error. Make sure '%s' is"
|
||
|
" listed in the hosts file.", WSAGetLastError(), szBuff );
|
||
|
MessageBox(hWnd, szTemp, "gethostbyname() failed.", MB_OK);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
memcpy((char FAR *)&(psin->sin_addr), phe->h_addr, phe->h_length);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/* SocketConnect
|
||
|
*
|
||
|
* The counterpart to SocketListen.
|
||
|
* Creates a socket and initializes it with the supplied TCP/IP
|
||
|
* port address, then connects to a listening server.
|
||
|
* The returned socket can be used to send() and recv() data.
|
||
|
*
|
||
|
* Parameters: TCPPort - The port to use.
|
||
|
* pSocket - A pointer to a SOCKET, which will be filled in
|
||
|
* if the call succeeds.
|
||
|
*
|
||
|
* Returns: TRUE if successful.
|
||
|
*
|
||
|
*
|
||
|
* Created 16 November 1993 (andrewbe)
|
||
|
*
|
||
|
*/
|
||
|
BOOL SocketConnect( LPSTR pstrServerName, u_short TCPPort, SOCKET *pSocket )
|
||
|
{
|
||
|
SOCKET Socket;
|
||
|
SOCKADDR_IN dest_sin; /* DESTination Socket INternet */
|
||
|
|
||
|
/* Create a socket:
|
||
|
*/
|
||
|
Socket = socket( AF_INET, SOCK_STREAM, 0);
|
||
|
|
||
|
if (Socket == INVALID_SOCKET)
|
||
|
{
|
||
|
WSAERROR( "socket()");
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (!FillAddr( NULL, &dest_sin, pstrServerName ) )
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
dest_sin.sin_port = htons( TCPPort );
|
||
|
|
||
|
/* Someone must be listen()ing for this to succeed:
|
||
|
*/
|
||
|
if (connect( Socket, (PSOCKADDR)&dest_sin, sizeof( dest_sin)) == SOCKET_ERROR)
|
||
|
{
|
||
|
closesocket( Socket );
|
||
|
WSAERROR("connect()");
|
||
|
MessageBox(NULL,
|
||
|
"ERROR: Could not connect the socket. "
|
||
|
"It may be that the hardcoded Sleep() value "
|
||
|
"on the caller's side is not long enough.",
|
||
|
"Video Conferencing Prototype", MB_OK);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
*pSocket = Socket;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/* SocketListen
|
||
|
*
|
||
|
* The counterpart to SocketConnect.
|
||
|
* Creates a socket and initializes it with the supplied TCP/IP
|
||
|
* port address, then listens for a connecting client.
|
||
|
* The returned socket can be used to send() and recv() data.
|
||
|
*
|
||
|
* Parameters: TCPPort - The port to use.
|
||
|
* pSocket - A pointer to a SOCKET, which will be filled in
|
||
|
* if the call succeeds.
|
||
|
*
|
||
|
* Returns: TRUE if successful.
|
||
|
*
|
||
|
*
|
||
|
* Created 16 November 1993 (andrewbe)
|
||
|
*
|
||
|
*/
|
||
|
BOOL SocketListen( u_short TCPPort, SOCKET *pSocket )
|
||
|
{
|
||
|
SOCKET Socket;
|
||
|
SOCKADDR_IN local_sin; /* Local socket - internet style */
|
||
|
SOCKADDR_IN acc_sin; /* Accept socket address - internet style */
|
||
|
int acc_sin_len; /* Accept socket address length */
|
||
|
|
||
|
/* Create a socket:
|
||
|
*/
|
||
|
Socket = socket( AF_INET, SOCK_STREAM, 0);
|
||
|
|
||
|
if (Socket == INVALID_SOCKET)
|
||
|
{
|
||
|
WSAERROR( "socket()");
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Retrieve the IP address and TCP Port number
|
||
|
*/
|
||
|
|
||
|
if (!FillAddr(NULL, &local_sin, NULL ))
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Associate an address with a socket. (bind)
|
||
|
*/
|
||
|
local_sin.sin_port = htons( TCPPort );
|
||
|
|
||
|
if (bind( Socket, (struct sockaddr FAR *)&local_sin, sizeof(local_sin)) == SOCKET_ERROR)
|
||
|
{
|
||
|
WSAERROR( "bind()" );
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
if (listen( Socket, MAX_PENDING_CONNECTS ) == SOCKET_ERROR)
|
||
|
{
|
||
|
WSAERROR( "listen()" );
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
acc_sin_len = sizeof(acc_sin);
|
||
|
|
||
|
Socket = accept( Socket, (struct sockaddr *)&acc_sin, (int *)&acc_sin_len );
|
||
|
|
||
|
if (Socket == INVALID_SOCKET)
|
||
|
{
|
||
|
WSAERROR( "accept()" );
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
*pSocket = Socket;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|