windows-nt/Source/XPSP1/NT/sdktools/gutils/sockets.c
2020-09-26 16:20:57 +08:00

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;
}