Windows2003-3790/enduser/netmeeting/av/callcont/gksocket.cpp

504 lines
13 KiB
C++
Raw Normal View History

2001-01-01 00:00:00 +01:00
/************************************************************************
* *
* 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 <precomp.h>
#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);
}