/************************************************************************ * * * INTEL CORPORATION PROPRIETARY INFORMATION * * * * This software is supplied under the terms of a license * * agreement or non-disclosure agreement with Intel Corporation * * and may not be copied or disclosed except in accordance * * with the terms of that agreement. * * * * Copyright (C) 1997 Intel Corp. All Rights Reserved * * * * $Archive: S:\sturgeon\src\gki\vcs\gksocket.cpv $ * * * $Revision: 1.5 $ * $Date: 28 Feb 1997 15:46:24 $ * * * $Author: CHULME $ * * * $Log: S:\sturgeon\src\gki\vcs\gksocket.cpv $ // // Rev 1.5 28 Feb 1997 15:46:24 CHULME // Check additional return value on recvfrom for a closed socket // // Rev 1.4 17 Jan 1997 09:02:28 CHULME // Changed reg.h to gkreg.h to avoid name conflict with inc directory // // Rev 1.3 10 Jan 1997 16:15:48 CHULME // Removed MFC dependency // // Rev 1.2 18 Dec 1996 14:23:30 CHULME // Changed discovery to send broadcast and multicast GRQs - debug only disable // // Rev 1.1 22 Nov 1996 14:56:04 CHULME // Added detection of LastError = 0 for treatment on socket close *************************************************************************/ // gksocket.cpp : Provides the implementation for the CGKSocket class // #include #define IP_MULTICAST_TTL 3 /* set/get IP multicast timetolive */ #include "dspider.h" #include "dgkilit.h" #include "DGKIPROT.H" #include "GATEKPR.H" #include "gksocket.h" #include "GKREG.H" #include "h225asn.h" #include "coder.hpp" #include "dgkiext.h" #if (defined(_DEBUG) || defined(PCS_COMPLIANCE)) // INTEROP #include "interop.h" #include "rasplog.h" extern LPInteropLogger RasLogger; #endif #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CGKSocket construction CGKSocket::CGKSocket() { #ifdef _DEBUG char szGKDebug[80]; #endif SPIDER_TRACE(SP_CONDES, "CGKSocket::CGKSocket()\n", 0); m_hSocket = INVALID_SOCKET; m_nLastErr = 0; m_nAddrFam = 0; m_usPort = 0; } ///////////////////////////////////////////////////////////////////////////// // CGKSocket destruction CGKSocket::~CGKSocket() { #ifdef _DEBUG char szGKDebug[80]; #endif SPIDER_TRACE(SP_CONDES, "CGKSocket::~CGKSocket()\n", 0); if (m_hSocket != INVALID_SOCKET) Close(); } int CGKSocket::Create(int nAddrFam, unsigned short usPort) { // ABSTRACT: Creates the socket for the supplied address family (transport) // and binds it to the specified port. This function returns 0 // if successful, else it will return the winsock comm error code. // AUTHOR: Colin Hulme int nRet, nLen; SOCKADDR_IN sAddrIn; #ifdef _DEBUG char szGKDebug[80]; #endif SPIDER_TRACE(SP_FUNC, "CGKSocket::Create(nAddrFam, %X)\n", usPort); // Create a socket for the supplied address family SPIDER_TRACE(SP_WSOCK, "socket(%X, SOCK_DGRAM, 0)\n", nAddrFam); if ((m_hSocket = socket(nAddrFam, SOCK_DGRAM, 0)) == INVALID_SOCKET) { m_nLastErr = WSAGetLastError(); // Get winsock error code SpiderWSErrDecode(m_nLastErr); // Debug print of error decode return (m_nLastErr); } m_nAddrFam = nAddrFam; // Bind socket to a local address switch (nAddrFam) { case PF_INET: sAddrIn.sin_family = AF_INET; break; case PF_IPX: sAddrIn.sin_family = AF_IPX; break; } sAddrIn.sin_addr.s_addr = htonl(INADDR_ANY); sAddrIn.sin_port = htons(usPort); SPIDER_TRACE(SP_WSOCK, "bind(%X, &sAddrIn, sizeof(sAddrIn))\n", m_hSocket); nRet = bind(m_hSocket, (LPSOCKADDR)&sAddrIn, sizeof(sAddrIn)); if (nRet != 0) { m_nLastErr = WSAGetLastError(); SpiderWSErrDecode(m_nLastErr); Close(); // Close the socket return (m_nLastErr); } // Get dynamic port number - not actually guaranteed til after connect SPIDER_TRACE(SP_WSOCK, "getsockname(%X, (LPSOCKADDR)&sAddrIn, sizeof(sAddrIn))\n", m_hSocket); nLen = sizeof(sAddrIn); nRet = getsockname(m_hSocket, (LPSOCKADDR)&sAddrIn, &nLen); if (nRet == SOCKET_ERROR) { m_nLastErr = WSAGetLastError(); SpiderWSErrDecode(m_nLastErr); Close(); // Close the socket return (SOCKET_ERROR); } SPIDER_DEBUG(sAddrIn.sin_port); m_usPort = ntohs(sAddrIn.sin_port); return (0); } int CGKSocket::Connect(PSOCKADDR_IN pAddr) { // ABSTRACT: This simulates a connect. It simply stores the relevant // information in a member variable that will be used by the // Send and Receive member functions. // AUTHOR: Colin Hulme m_sAddrIn = *pAddr; m_sAddrIn.sin_family = AF_INET; m_sAddrIn.sin_port = htons(GKIP_RAS_PORT); return (0); } int CGKSocket::Send(char *pBuffer, int nLen) { // ABSTRACT: This function will send a datagram on the connected socket. // AUTHOR: Colin Hulme int nRet; #ifdef _DEBUG char szGKDebug[80]; #endif SPIDER_TRACE(SP_FUNC, "CGKSocket::Send(pBuffer, %X)\n", nLen); SPIDER_TRACE(SP_WSOCK, "sendto(%X, pBuffer, nLen, 0, &m_sAddrIn, sizeof(m_sAddrIn))\n", m_hSocket); #ifdef _DEBUG //INTEROP if (dwGKIDLLFlags & SP_LOGGER) InteropOutput((LPInteropLogger)RasLogger, (BYTE FAR *)pBuffer, nLen, RASLOG_SENT_PDU); #endif #ifdef PCS_COMPLIANCE //INTEROP InteropOutput((LPInteropLogger)RasLogger, (BYTE FAR *)pBuffer, nLen, RASLOG_SENT_PDU); #endif nRet = sendto(m_hSocket, pBuffer, nLen, 0, (LPSOCKADDR)&m_sAddrIn, sizeof(m_sAddrIn)); SPIDER_DEBUG(nRet); if (nRet == SOCKET_ERROR) { m_nLastErr = WSAGetLastError(); SpiderWSErrDecode(m_nLastErr); Close(); // Close the socket return (SOCKET_ERROR); } return (nRet); } int CGKSocket::SendTo(char *pBuffer, int nLen, const struct sockaddr FAR * to, int tolen) { // ABSTRACT: This function will send a datagram on the connected socket. // AUTHOR: Colin Hulme int nRet; #ifdef _DEBUG char szGKDebug[80]; #endif SPIDER_TRACE(SP_FUNC, "CGKSocket::SendTo(pBuffer, %X, to, tolen)\n", nLen); SPIDER_TRACE(SP_WSOCK, "sendto(%X, pBuffer, nLen, 0, to, tolen)\n", m_hSocket); #ifdef _DEBUG //INTEROP if (dwGKIDLLFlags & SP_LOGGER) InteropOutput((LPInteropLogger)RasLogger, (BYTE FAR *)pBuffer, nLen, RASLOG_SENT_PDU); #endif #ifdef PCS_COMPLIANCE //INTEROP InteropOutput((LPInteropLogger)RasLogger, (BYTE FAR *)pBuffer, nLen, RASLOG_SENT_PDU); #endif nRet = sendto(m_hSocket, pBuffer, nLen, 0, to, tolen); SPIDER_DEBUG(nRet); if (nRet == SOCKET_ERROR) { m_nLastErr = WSAGetLastError(); SpiderWSErrDecode(m_nLastErr); Close(); // Close the socket return (SOCKET_ERROR); } return (nRet); } int CGKSocket::Receive(char *pBuffer, int nLen) { // ABSTRACT: This function will post a receive for an incoming datagram. // AUTHOR: Colin Hulme int nRet; #ifdef _DEBUG char szGKDebug[80]; #endif SPIDER_TRACE(SP_FUNC, "CGKSocket::Receive(pBuffer, %X)\n", nLen); SPIDER_TRACE(SP_WSOCK, "recvfrom(%X, pBuffer, nLen, 0, 0, 0)\n", m_hSocket); nRet = recvfrom(m_hSocket, pBuffer, nLen, 0, 0, 0); SPIDER_DEBUG(nRet); if (nRet == SOCKET_ERROR) { m_nLastErr = WSAGetLastError(); if ((m_nLastErr == 2) || (m_nLastErr == 0) || (m_nLastErr == WSAEINVAL)) // Weird return values seen m_nLastErr = WSAEINTR; // occasionally when socket closed SpiderWSErrDecode(m_nLastErr); if (m_nLastErr != WSAEINTR) Close(); // Close the socket return (SOCKET_ERROR); } #ifdef _DEBUG //INTEROP if (dwGKIDLLFlags & SP_LOGGER) InteropOutput((LPInteropLogger)RasLogger, (BYTE FAR *)pBuffer, nLen, RASLOG_RECEIVED_PDU); #endif #ifdef PCS_COMPLIANCE //INTEROP InteropOutput((LPInteropLogger)RasLogger, (BYTE FAR *)pBuffer, nLen, RASLOG_RECEIVED_PDU); #endif return (nRet); } int CGKSocket::SendBroadcast(char *pBuffer, int nLen) { // ABSTRACT: This function will send a datagram to the broadcast address // and to the multicast address. In the case of a debug build, // a registry setting can be used to disable the multicast // transmission. Both transmissions will always occur in the // release build. // AUTHOR: Colin Hulme int nRet, nValue; struct sockaddr_in sAddrIn; #ifdef _DEBUG char szGKDebug[80]; #endif SPIDER_TRACE(SP_FUNC, "CGKSocket::SendBroadcast(pBuffer, %X)\n", nLen); ASSERT(g_pGatekeeper); if(g_pGatekeeper == NULL) return SOCKET_ERROR; // Setup family and port information switch (m_nAddrFam) { case PF_INET: sAddrIn.sin_family = AF_INET; sAddrIn.sin_port = htons(GKIP_DISC_PORT); break; case PF_IPX: sAddrIn.sin_family = AF_IPX; sAddrIn.sin_port = htons(GKIPX_DISC_PORT); break; } // ================= SEND BROADCAST =================== //if ((nValue = (int)Gatekeeper.GetMCastTTL()) == 0) // Set socket options to allow broadcasting on this socket nValue = 1; // TRUE - for setting BOOLEAN SPIDER_TRACE(SP_WSOCK, "setsockopt(%X, SOL_SOCKET, SO_BROADCAST, &nValue, sizeof(nValue))\n", m_hSocket); nRet = setsockopt(m_hSocket, SOL_SOCKET, SO_BROADCAST, (const char *)&nValue, sizeof(nValue)); // TBD - Don't know if SOL_SOCKET is going to work for other transports if (nRet == SOCKET_ERROR) { m_nLastErr = WSAGetLastError(); SpiderWSErrDecode(m_nLastErr); Close(); // Close the socket return (SOCKET_ERROR); } sAddrIn.sin_addr.s_addr = htonl(INADDR_BROADCAST); SPIDER_TRACE(SP_WSOCK, "sendto(%X, pBuffer, nLen, 0, (LPSOCKADDR)&sAddrIn, sizeof(sAddrIn))\n", m_hSocket); #ifdef _DEBUG //INTEROP if (dwGKIDLLFlags & SP_LOGGER) InteropOutput((LPInteropLogger)RasLogger, (BYTE FAR *)pBuffer, nLen, RASLOG_SENT_PDU); #endif #ifdef PCS_COMPLIANCE //INTEROP InteropOutput((LPInteropLogger)RasLogger, (BYTE FAR *)pBuffer, nLen, RASLOG_SENT_PDU); #endif nRet = sendto(m_hSocket, pBuffer, nLen, 0, (LPSOCKADDR)&sAddrIn, sizeof(sAddrIn)); SPIDER_DEBUG(nRet); if (nRet == SOCKET_ERROR) { m_nLastErr = WSAGetLastError(); SpiderWSErrDecode(m_nLastErr); Close(); // Close the socket return (SOCKET_ERROR); } #ifdef _DEBUG if ((nValue = (int)g_pGatekeeper->GetMCastTTL()) != 0) { // debug only conditional for avoiding sending multicast #endif // ================= SEND MULTICAST =================== // Set socket options for multicast time to live nValue = 16; //FMN SPIDER_TRACE(SP_WSOCK, "setsockopt(%X, IPPROTO_IP, IP_MULTICAST_TTL, &nValue, sizeof(nValue))\n", m_hSocket); nRet = setsockopt(m_hSocket, IPPROTO_IP, IP_MULTICAST_TTL, (const char *)&nValue, sizeof(nValue)); // TBD - IP specific - handle IPX case with broadcast? if (nRet == SOCKET_ERROR) { m_nLastErr = WSAGetLastError(); SpiderWSErrDecode(m_nLastErr); Close(); // Close the socket return (SOCKET_ERROR); } sAddrIn.sin_addr.s_addr = inet_addr(GKIP_DISC_MCADDR); SPIDER_TRACE(SP_WSOCK, "sendto(%X, pBuffer, nLen, 0, (LPSOCKADDR)&sAddrIn, sizeof(sAddrIn))\n", m_hSocket); #ifdef _DEBUG //INTEROP if (dwGKIDLLFlags & SP_LOGGER) InteropOutput((LPInteropLogger)RasLogger, (BYTE FAR *)pBuffer, nLen, RASLOG_SENT_PDU); #endif #ifdef PCS_COMPLIANCE //INTEROP InteropOutput((LPInteropLogger)RasLogger, (BYTE FAR *)pBuffer, nLen, RASLOG_SENT_PDU); #endif nRet = sendto(m_hSocket, pBuffer, nLen, 0, (LPSOCKADDR)&sAddrIn, sizeof(sAddrIn)); SPIDER_DEBUG(nRet); if (nRet == SOCKET_ERROR) { m_nLastErr = WSAGetLastError(); SpiderWSErrDecode(m_nLastErr); Close(); // Close the socket return (SOCKET_ERROR); } #ifdef _DEBUG } // End debug only conditional for avoiding sending multicast #endif return (nRet); } int CGKSocket::ReceiveFrom(char *pBuffer, int nLen) { // ABSTRACT: This function will post a receivefrom looking for a GCF or GRJ // AUTHOR: Colin Hulme int nRet; #ifdef _DEBUG char szGKDebug[80]; #endif SPIDER_TRACE(SP_FUNC, "CGKSocket::ReceiveFrom(pBuffer, %X)\n", nLen); SPIDER_TRACE(SP_WSOCK, "recvfrom(%X, pBuffer, nLen, 0, 0, 0)\n", m_hSocket); nRet = recvfrom(m_hSocket, pBuffer, nLen, 0, 0, 0); SPIDER_DEBUG(nRet); if (nRet == SOCKET_ERROR) { m_nLastErr = WSAGetLastError(); if ((m_nLastErr == 2) || (m_nLastErr == 0)) // Weird return values seen m_nLastErr = WSAEINTR; // occasionally when socket closed SpiderWSErrDecode(m_nLastErr); if (m_nLastErr != WSAEINTR) Close(); // Close the socket return (SOCKET_ERROR); } #ifdef _DEBUG //INTEROP if (dwGKIDLLFlags & SP_LOGGER) InteropOutput((LPInteropLogger)RasLogger, (BYTE FAR *)pBuffer, nLen, RASLOG_RECEIVED_PDU); #endif #ifdef PCS_COMPLIANCE //INTEROP InteropOutput((LPInteropLogger)RasLogger, (BYTE FAR *)pBuffer, nLen, RASLOG_RECEIVED_PDU); #endif return (nRet); } int CGKSocket::Close(void) { // ABSTRACT: This function will close the socket // AUTHOR: Colin Hulme int nRet; #ifdef _DEBUG char szGKDebug[80]; #endif SPIDER_TRACE(SP_FUNC, "CGKSocket::Close()\n", 0); // Close the socket SPIDER_TRACE(SP_WSOCK, "closesocket(%X)\n", m_hSocket); nRet = closesocket(m_hSocket); m_hSocket = INVALID_SOCKET; return (0); }