dect
/
asterisk
Archived
13
0
Fork 0
This repository has been archived on 2022-02-17. You can view files and clone it, but cannot push or open issues or pull requests.
asterisk/addons/ooh323c/src/ooSocket.c

724 lines
20 KiB
C

/*
* Copyright (C) 1997-2005 by Objective Systems, Inc.
*
* This software is furnished under an open source license and may be
* used and copied only in accordance with the terms of this license.
* The text of the license may generally be found in the root
* directory of this installation in the COPYING file. It
* can also be viewed online at the following URL:
*
* http://www.obj-sys.com/open/license.html
*
* Any redistributions of this file including modified versions must
* maintain this copyright notice.
*
*****************************************************************************/
#include "ooSocket.h"
#include "ootrace.h"
#if defined(_WIN32_WCE)
static int inited = 0;
#define SEND_FLAGS 0
#define SHUTDOWN_FLAGS 0
#elif defined (_WIN32)
static LPFN_SEND send;
static LPFN_SOCKET socket;
static LPFN_SETSOCKOPT setsockopt;
static LPFN_BIND bind;
static LPFN_HTONL htonl;
static LPFN_HTONS htons;
static LPFN_CONNECT connect;
static LPFN_INET_ADDR inet_addr;
static LPFN_LISTEN listen;
static LPFN_ACCEPT accept;
static LPFN_NTOHL ntohl;
static LPFN_NTOHS ntohs;
static LPFN_RECV recv;
static LPFN_SHUTDOWN shutdown;
static LPFN_IOCTLSOCKET ioctlsocket;
static LPFN_SENDTO sendto;
static LPFN_INET_NTOA inet_ntoa;
static LPFN_RECVFROM recvfrom;
static LPFN_SELECT select;
static LPFN_GETHOSTNAME gethostname;
static LPFN_GETHOSTBYNAME gethostbyname;
static LPFN_WSAGETLASTERROR WSAGetLastError;
static LPFN_WSACLEANUP WSACleanup;
static LPFN_CLOSESOCKET closesocket;
static LPFN_GETSOCKNAME getsockname;
static HMODULE ws32 = 0;
#define SEND_FLAGS 0
#define SHUTDOWN_FLAGS SD_BOTH
#else
#define SEND_FLAGS 0
#define SHUTDOWN_FLAGS SHUT_RDWR
#define closesocket close
#endif
int ooSocketsInit ()
{
#if defined(_WIN32_WCE)
WORD wVersionRequested;
WSADATA wsaData;
int err;
if (inited) return ASN_OK;
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup (wVersionRequested, &wsaData);
if ( err != 0 ) {
/* Tell the user that we could not find a usable */
/* WinSock DLL. */
return ASN_E_NOTINIT;
}
inited = 1;
#elif defined (_WIN32)
LPFN_WSASTARTUP wsaStartup = NULL;
WSADATA wsaData;
if (ws32 != 0) return ASN_OK;
// ws32 = LoadLibrary ("WSOCK32.DLL");
ws32 = LoadLibrary ("WS2_32.DLL");
if (ws32 == NULL) return ASN_E_NOTINIT;
wsaStartup = (LPFN_WSASTARTUP) GetProcAddress (ws32, "WSAStartup");
if (wsaStartup == NULL) return ASN_E_NOTINIT;
send = (LPFN_SEND) GetProcAddress (ws32, "send");
if (send == NULL) return ASN_E_NOTINIT;
socket = (LPFN_SOCKET) GetProcAddress (ws32, "socket");
if (socket == NULL) return ASN_E_NOTINIT;
setsockopt = (LPFN_SETSOCKOPT) GetProcAddress (ws32, "setsockopt");
if (setsockopt == NULL) return ASN_E_NOTINIT;
bind = (LPFN_BIND) GetProcAddress (ws32, "bind");
if (bind == NULL) return ASN_E_NOTINIT;
htonl = (LPFN_HTONL) GetProcAddress (ws32, "htonl");
if (htonl == NULL) return ASN_E_NOTINIT;
htons = (LPFN_HTONS) GetProcAddress (ws32, "htons");
if (htons == NULL) return ASN_E_NOTINIT;
connect = (LPFN_CONNECT) GetProcAddress (ws32, "connect");
if (connect == NULL) return ASN_E_NOTINIT;
listen = (LPFN_LISTEN) GetProcAddress (ws32, "listen");
if (listen == NULL) return ASN_E_NOTINIT;
accept = (LPFN_ACCEPT) GetProcAddress (ws32, "accept");
if (accept == NULL) return ASN_E_NOTINIT;
inet_addr = (LPFN_INET_ADDR) GetProcAddress (ws32, "inet_addr");
if (inet_addr == NULL) return ASN_E_NOTINIT;
ntohl = (LPFN_NTOHL) GetProcAddress (ws32, "ntohl");
if (ntohl == NULL) return ASN_E_NOTINIT;
ntohs = (LPFN_NTOHS) GetProcAddress (ws32, "ntohs");
if (ntohs == NULL) return ASN_E_NOTINIT;
recv = (LPFN_RECV) GetProcAddress (ws32, "recv");
if (recv == NULL) return ASN_E_NOTINIT;
shutdown = (LPFN_SHUTDOWN) GetProcAddress (ws32, "shutdown");
if (shutdown == NULL) return ASN_E_NOTINIT;
closesocket = (LPFN_CLOSESOCKET) GetProcAddress (ws32, "closesocket");
if (closesocket == NULL) return ASN_E_NOTINIT;
getsockname = (LPFN_GETSOCKNAME) GetProcAddress (ws32, "getsockname");
if (getsockname == NULL) return ASN_E_NOTINIT;
ioctlsocket = (LPFN_IOCTLSOCKET) GetProcAddress(ws32, "ioctlsocket");
if(ioctlsocket == NULL) return ASN_E_NOTINIT;
sendto = (LPFN_SENDTO) GetProcAddress (ws32, "sendto");
if (sendto == NULL) return ASN_E_NOTINIT;
inet_ntoa = (LPFN_INET_NTOA) GetProcAddress (ws32, "inet_ntoa");
if (inet_ntoa == NULL) return ASN_E_NOTINIT;
recvfrom = (LPFN_RECVFROM) GetProcAddress (ws32, "recvfrom");
if (recvfrom == NULL) return ASN_E_NOTINIT;
select = (LPFN_SELECT) GetProcAddress (ws32, "select");
if (select == NULL) return ASN_E_NOTINIT;
gethostname = (LPFN_GETHOSTNAME) GetProcAddress (ws32, "gethostname");
if (gethostname == NULL) return ASN_E_NOTINIT;
gethostbyname = (LPFN_GETHOSTBYNAME) GetProcAddress (ws32, "gethostbyname");
if (gethostbyname == NULL) return ASN_E_NOTINIT;
WSAGetLastError = (LPFN_WSAGETLASTERROR) GetProcAddress (ws32,
"WSAGetLastError");
if (WSAGetLastError == NULL) return ASN_E_NOTINIT;
WSACleanup = (LPFN_WSACLEANUP) GetProcAddress (ws32, "WSACleanup");
if (WSACleanup == NULL) return ASN_E_NOTINIT;
if (wsaStartup (MAKEWORD(1, 1), &wsaData) == -1) return ASN_E_NOTINIT;
#endif
return ASN_OK;
}
#if defined (_WIN32) || \
defined(_HP_UX) || defined(__hpux) || defined(_HPUX_SOURCE)
typedef int OOSOCKLEN;
#else
typedef size_t OOSOCKLEN;
#endif
int ooSocketCreate (OOSOCKET* psocket)
{
int on;
struct linger linger;
OOSOCKET sock = socket (AF_INET,
SOCK_STREAM,
0);
if (sock == OOSOCKET_INVALID){
OOTRACEERR1("Error:Failed to create TCP socket\n");
return ASN_E_INVSOCKET;
}
on = 1;
if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
(const char* ) &on, sizeof (on)) == -1)
{
OOTRACEERR1("Error:Failed to set socket option SO_REUSEADDR\n");
return ASN_E_INVSOCKET;
}
linger.l_onoff = 1;
linger.l_linger = 0;
if (setsockopt (sock, SOL_SOCKET, SO_LINGER,
(const char* ) &linger, sizeof (linger)) == -1)
{
OOTRACEERR1("Error:Failed to set socket option linger\n");
return ASN_E_INVSOCKET;
}
*psocket = sock;
return ASN_OK;
}
int ooSocketCreateUDP (OOSOCKET* psocket)
{
int on;
struct linger linger;
OOSOCKET sock = socket (AF_INET,
SOCK_DGRAM,
0);
if (sock == OOSOCKET_INVALID){
OOTRACEERR1("Error:Failed to create UDP socket\n");
return ASN_E_INVSOCKET;
}
on = 1;
if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
(const char* ) &on, sizeof (on)) == -1)
{
OOTRACEERR1("Error:Failed to set socket option SO_REUSEADDR\n");
return ASN_E_INVSOCKET;
}
linger.l_onoff = 1;
linger.l_linger = 0;
/*if (setsockopt (sock, SOL_SOCKET, SO_LINGER,
(const char* ) &linger, sizeof (linger)) == -1)
return ASN_E_INVSOCKET;
*/
*psocket = sock;
return ASN_OK;
}
int ooSocketClose (OOSOCKET socket)
{
shutdown (socket, SHUTDOWN_FLAGS);
if (closesocket (socket) == -1)
return ASN_E_INVSOCKET;
return ASN_OK;
}
int ooSocketBind (OOSOCKET socket, OOIPADDR addr, int port)
{
struct sockaddr_in m_addr;
if (socket == OOSOCKET_INVALID)
{
OOTRACEERR1("Error:Invalid socket passed to bind\n");
return ASN_E_INVSOCKET;
}
memset (&m_addr, 0, sizeof (m_addr));
m_addr.sin_family = AF_INET;
m_addr.sin_addr.s_addr = (addr == 0) ? INADDR_ANY : htonl (addr);
m_addr.sin_port = htons ((unsigned short)port);
if (bind (socket, (struct sockaddr *) (void*) &m_addr,
sizeof (m_addr)) == -1)
{
perror ("bind");
OOTRACEERR1("Error:Bind failed\n");
return ASN_E_INVSOCKET;
}
return ASN_OK;
}
int ooSocketGetSockName(OOSOCKET socket, struct sockaddr_in *name, int *size)
{
int ret;
ret = getsockname(socket, (struct sockaddr*)name, size);
if(ret == 0)
return ASN_OK;
else{
OOTRACEERR1("Error:ooSocketGetSockName - getsockname\n");
return ASN_E_INVSOCKET;
}
}
int ooSocketGetIpAndPort(OOSOCKET socket, char *ip, int len, int *port)
{
int ret=ASN_OK, size;
struct sockaddr_in addr;
char *host=NULL;
size = sizeof(addr);
ret = ooSocketGetSockName(socket, &addr, &size);
if(ret != 0)
return ASN_E_INVSOCKET;
host = inet_ntoa(addr.sin_addr);
if(host && strlen(host) < (unsigned)len)
strcpy(ip, host);
else{
OOTRACEERR1("Error:Insufficient buffer for ip address - "
"ooSocketGetIpAndPort\n");
return -1;
}
*port = addr.sin_port;
return ASN_OK;
}
int ooSocketListen (OOSOCKET socket, int maxConnection)
{
if (socket == OOSOCKET_INVALID) return ASN_E_INVSOCKET;
if (listen (socket, maxConnection) == -1)
return ASN_E_INVSOCKET;
return ASN_OK;
}
int ooSocketAccept (OOSOCKET socket, OOSOCKET *pNewSocket,
OOIPADDR* destAddr, int* destPort)
{
struct sockaddr_in m_addr;
OOSOCKLEN addr_length = sizeof (m_addr);
if (socket == OOSOCKET_INVALID) return ASN_E_INVSOCKET;
if (pNewSocket == 0) return ASN_E_INVPARAM;
*pNewSocket = accept (socket, (struct sockaddr *) (void*) &m_addr,
(socklen_t *) &addr_length);
if (*pNewSocket <= 0) return ASN_E_INVSOCKET;
if (destAddr != 0)
*destAddr = ntohl (m_addr.sin_addr.s_addr);
if (destPort != 0)
*destPort = ntohs (m_addr.sin_port);
return ASN_OK;
}
int ooSocketConnect (OOSOCKET socket, const char* host, int port)
{
struct sockaddr_in m_addr;
if (socket == OOSOCKET_INVALID)
{
return ASN_E_INVSOCKET;
}
memset (&m_addr, 0, sizeof (m_addr));
m_addr.sin_family = AF_INET;
m_addr.sin_port = htons ((unsigned short)port);
m_addr.sin_addr.s_addr = inet_addr (host);
if (connect (socket, (struct sockaddr *) (void*) &m_addr,
sizeof (struct sockaddr_in)) == -1)
{
return ASN_E_INVSOCKET;
}
return ASN_OK;
}
/*
// **Need to add check whether complete data was sent by checking the return
// **value of send and if complete data is not sent then add mechanism to
// **send remaining bytes. This will make ooSocketSend call atomic.
*/
int ooSocketSend (OOSOCKET socket, const ASN1OCTET* pdata, ASN1UINT size)
{
if (socket == OOSOCKET_INVALID) return ASN_E_INVSOCKET;
if (send (socket, (const char*) pdata, size, SEND_FLAGS) == -1)
return ASN_E_INVSOCKET;
return ASN_OK;
}
int ooSocketSendTo(OOSOCKET socket, const ASN1OCTET* pdata, ASN1UINT size,
const char* host, int port)
{
struct sockaddr_in m_addr;
if (socket == OOSOCKET_INVALID) return ASN_E_INVSOCKET;
memset (&m_addr, 0, sizeof (m_addr));
m_addr.sin_family = AF_INET;
m_addr.sin_port = htons ((unsigned short)port);
m_addr.sin_addr.s_addr = inet_addr (host);
if (sendto (socket, (const char*) pdata, size, SEND_FLAGS,
(const struct sockaddr*)&m_addr,
sizeof(m_addr)) == -1)
return ASN_E_INVSOCKET;
return ASN_OK;
}
int ooSocketRecvPeek(OOSOCKET socket, ASN1OCTET* pbuf, ASN1UINT bufsize)
{
int len;
int flags = MSG_PEEK;
if (socket == OOSOCKET_INVALID) return ASN_E_INVSOCKET;
if ((len = recv (socket, (char*) pbuf, bufsize, flags)) == -1)
return ASN_E_INVSOCKET;
return len;
}
int ooSocketRecv (OOSOCKET socket, ASN1OCTET* pbuf, ASN1UINT bufsize)
{
int len;
if (socket == OOSOCKET_INVALID) return ASN_E_INVSOCKET;
if ((len = recv (socket, (char*) pbuf, bufsize, 0)) == -1)
return ASN_E_INVSOCKET;
return len;
}
int ooSocketRecvFrom (OOSOCKET socket, ASN1OCTET* pbuf, ASN1UINT bufsize,
char* remotehost, ASN1UINT hostBufLen, int * remoteport)
{
struct sockaddr_in m_addr;
int len, addrlen;
char * host=NULL;
if (socket == OOSOCKET_INVALID) return ASN_E_INVSOCKET;
addrlen = sizeof(m_addr);
memset (&m_addr, 0, sizeof (m_addr));
if ((len = recvfrom (socket, (char*) pbuf, bufsize, 0,
(struct sockaddr*)&m_addr, &addrlen)) == -1)
return ASN_E_INVSOCKET;
if(remoteport)
*remoteport = ntohs(m_addr.sin_port);
if(remotehost)
{
host = inet_ntoa(m_addr.sin_addr);
if(strlen(host) < (hostBufLen-1))
strcpy(remotehost, host);
else
return -1;
}
return len;
}
int ooSocketSelect(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval * timeout)
{
int ret;
#if defined (_WIN32)
ret = select(nfds, readfds, writefds, exceptfds,
(const struct timeval *) timeout);
#else
ret = select(nfds, readfds, writefds, exceptfds, timeout);
#endif
return ret;
}
int ooGetLocalIPAddress(char * pIPAddrs)
{
int ret;
struct hostent *phost;
struct in_addr addr;
char hostname[100];
if(pIPAddrs == NULL)
return -1; /* Need to find suitable return value */
ret = gethostname(hostname, 100);
if(ret == 0)
{
phost = gethostbyname(hostname);
if(phost == NULL)
return -1; /* Need to define a return value if made part of rtsrc */
memcpy(&addr, phost->h_addr_list[0], sizeof(struct in_addr));
strcpy(pIPAddrs, inet_ntoa(addr));
}
else{
return -1;
}
return ASN_OK;
}
int ooSocketStrToAddr (const char* pIPAddrStr, OOIPADDR* pIPAddr)
{
int b1, b2, b3, b4;
int rv = sscanf (pIPAddrStr, "%d.%d.%d.%d", &b1, &b2, &b3, &b4);
if (rv != 4 ||
(b1 < 0 || b1 > 256) || (b2 < 0 || b2 > 256) ||
(b3 < 0 || b3 > 256) || (b4 < 0 || b4 > 256))
return ASN_E_INVPARAM;
*pIPAddr = ((b1 & 0xFF) << 24) | ((b2 & 0xFF) << 16) |
((b3 & 0xFF) << 8) | (b4 & 0xFF);
return ASN_OK;
}
int ooSocketConvertIpToNwAddr(char *inetIp, char *netIp)
{
struct sockaddr_in sin = {0};
#ifdef _WIN32
sin.sin_addr.s_addr = inet_addr(inetIp);
if(sin.sin_addr.s_addr == INADDR_NONE)
{
OOTRACEERR1("Error:Failed to convert address\n");
return -1;
}
#else
if(!inet_aton(inetIp, &sin.sin_addr))
{
OOTRACEERR1("Error:Failed to convert address\n");
return -1;
}
#endif
memcpy(netIp, (char*)&sin.sin_addr.s_addr, sizeof(unsigned long));
return ASN_OK;
}
int ooSocketAddrToStr (OOIPADDR ipAddr, char* pbuf, int bufsize)
{
char buf1[5], buf2[5], buf3[5], buf4[5];
int cnt = 0;
if (bufsize < 8)
return ASN_E_BUFOVFLW;
cnt += sprintf (buf1, "%lu", (ipAddr >> 24) & 0xFF);
cnt += sprintf (buf2, "%lu", (ipAddr >> 16) & 0xFF);
cnt += sprintf (buf3, "%lu", (ipAddr >> 8) & 0xFF);
cnt += sprintf (buf4, "%lu", ipAddr & 0xFF);
if (bufsize < cnt + 4)
return ASN_E_BUFOVFLW;
sprintf (pbuf, "%s.%s.%s.%s", buf1, buf2, buf3, buf4);
return ASN_OK;
}
int ooSocketsCleanup (void)
{
#ifdef _WIN32
int ret = WSACleanup();
if(ret == 0)
return ASN_OK;
else
return ret;
#endif
return ASN_OK;
}
long ooSocketHTONL(long val)
{
return htonl(val);
}
short ooSocketHTONS(short val)
{
return htons(val);
}
#ifndef _WIN32
int ooSocketGetInterfaceList(OOCTXT *pctxt, OOInterface **ifList)
{
OOSOCKET sock;
struct ifconf ifc;
int ifNum;
OOInterface *pIf=NULL;
OOTRACEDBGA1("Retrieving local interfaces\n");
if(ooSocketCreateUDP(&sock)!= ASN_OK)
{
OOTRACEERR1("Error:Failed to create udp socket - "
"ooSocketGetInterfaceList\n");
return -1;
}
#ifdef SIOCGIFNUM
if(ioctl(sock, SIOCGIFNUM, &ifNum) >= 0)
{
OOTRACEERR1("Error: ioctl for ifNum failed\n");
return -1;
}
#else
ifNum = 50;
#endif
ifc.ifc_len = ifNum * sizeof(struct ifreq);
ifc.ifc_req = (struct ifreq *)memAlloc(pctxt, ifNum *sizeof(struct ifreq));
if(!ifc.ifc_req)
{
OOTRACEERR1("Error:Memory - ooSocketGetInterfaceList - ifc.ifc_req\n");
return -1;
}
if (ioctl(sock, SIOCGIFCONF, &ifc) >= 0) {
void * ifEndList = (char *)ifc.ifc_req + ifc.ifc_len;
struct ifreq *ifName;
struct ifreq ifReq;
int flags;
for (ifName = ifc.ifc_req; (void*)ifName < ifEndList; ifName++) {
char *pName=NULL;
char addr[50];
#ifdef ifr_netmask
char mask[50];
#endif
pIf = (struct OOInterface*)memAlloc(pctxt, sizeof(struct OOInterface));
pName = (char*)memAlloc(pctxt, strlen(ifName->ifr_name)+1);
if(!pIf)
{
OOTRACEERR1("Error:Memory - ooSocketGetInterfaceList - "
"pIf/pName\n");
return -1;
}
OOTRACEDBGA2("\tInterface name: %s\n", ifName->ifr_name);
strcpy(ifReq.ifr_name, ifName->ifr_name);
strcpy(pName, ifName->ifr_name);
pIf->name = pName;
/* Check whether the interface is up*/
if (ioctl(sock, SIOCGIFFLAGS, &ifReq) < 0) {
OOTRACEERR2("Error:Unable to determine status of interface %s\n",
pName);
memFreePtr(pctxt, pIf->name);
memFreePtr(pctxt, pIf);
continue;
}
flags = ifReq.ifr_flags;
if (!(flags & IFF_UP)) {
OOTRACEWARN2("Warn:Interface %s is not up\n", pName);
memFreePtr(pctxt, pIf->name);
memFreePtr(pctxt, pIf);
continue;
}
/* Retrieve interface address */
if (ioctl(sock, SIOCGIFADDR, &ifReq) < 0)
{
OOTRACEWARN2("Warn:Unable to determine address of interface %s\n",
pName);
memFreePtr(pctxt, pIf->name);
memFreePtr(pctxt, pIf);
continue;
}
strcpy(addr, inet_ntoa(((struct sockaddr_in*)&ifReq.ifr_addr)->sin_addr));
OOTRACEDBGA2("\tIP address is %s\n", addr);
pIf->addr = (char*)memAlloc(pctxt, strlen(addr)+1);
if(!pIf->addr)
{
OOTRACEERR1("Error:Memory - ooSocketGetInterfaceList - "
"pIf->addr\n");
memFreePtr(pctxt, pIf->name);
memFreePtr(pctxt, pIf);
return -1;
}
strcpy(pIf->addr, addr);
#ifdef ifr_netmask
if (ioctl(sock, SIOCGIFNETMASK, &ifReq) < 0)
{
OOTRACEWARN2("Warn:Unable to determine mask for interface %s\n",
pName);
memFreePtr(pctxt, pIf->name);
memFreePtr(pctxt, pIf->addr);
memFreePtr(pctxt, pIf);
continue;
}
strcpy(mask, inet_ntoa(((struct sockaddr_in *)&ifReq.ifr_netmask)->sin_addr));
OOTRACEDBGA2("\tMask is %s\n", mask);
pIf->mask = (char*)memAlloc(pctxt, strlen(mask)+1);
if(!pIf->mask)
{
OOTRACEERR1("Error:Memory - ooSocketGetInterfaceList - "
"pIf->mask\n");
memFreePtr(pctxt, pIf->name);
memFreePtr(pctxt, pIf->addr);
memFreePtr(pctxt, pIf);
return -1;
}
strcpy(pIf->mask, mask);
#endif
pIf->next = NULL;
/* Add to the list */
if(!*ifList)
{
*ifList = pIf;
pIf = NULL;
}
else{
pIf->next = *ifList;
*ifList = pIf;
pIf=NULL;
}
/*
#if defined(OO_FREEBSD) || defined(OO_OPENBSD) || defined(OO_NETBSD) || defined(OO_MACOSX) || defined(OO_VXWORKS) || defined(OO_RTEMS) || defined(OO_QNX)
#ifndef _SIZEOF_ADDR_IFREQ
#define _SIZEOF_ADDR_IFREQ(ifr) \
((ifr).ifr_addr.sa_len > sizeof(struct sockaddr) ? \
(sizeof(struct ifreq) - sizeof(struct sockaddr) + \
(ifr).ifr_addr.sa_len) : sizeof(struct ifreq))
#endif
ifName = (struct ifreq *)((char *)ifName + _SIZEOF_ADDR_IFREQ(*ifName));
#else
ifName++;
*/
}
}
return ASN_OK;
}
#endif