/*************************************************************************************************\ * * SOCKETS.C * * This file contains routines used for establishing Sockets connections. * \*************************************************************************************************/ #include #include #include #include #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; }