📄 swiipaddress.cpp
字号:
/****************License************************************************
* Vocalocity OpenVXI
* Copyright (C) 2004-2005 by Vocalocity, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* Vocalocity, the Vocalocity logo, and VocalOS are trademarks or
* registered trademarks of Vocalocity, Inc.
* OpenVXI is a trademark of Scansoft, Inc. and used under license
* by Vocalocity.
***********************************************************************/
#include <string.h>
#include "SWIipAddress.hpp"
#ifdef _WIN32
#include <winsock2.h>
#else
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#endif
#if defined(WIN32) || defined(_decunix_)
/* These OSes are thread safe by using thread local storage for the hostent */
static int my_gethostbyaddr_r (const char * addr, socklen_t len,
int type,
struct hostent * result_buf,
char * buf, size_t buflen,
struct hostent ** result,
int * h_errnop) {
*result = gethostbyaddr(addr, len, type);
return (result ? 0 : -1);
}
static int my_gethostbyname_r (const char * name,
struct hostent * result_buf,
char * buf, size_t buflen,
struct hostent ** result,
int * h_errnop) {
*result = gethostbyname(name);
return (result ? 0 : -1);
}
#elif defined(_solaris_)
static int my_gethostbyaddr_r (const char * addr, socklen_t len,
int type,
struct hostent * result_buf,
char * buf, size_t buflen,
struct hostent ** result,
int * h_errnop) {
*result = gethostbyaddr_r(addr, len, type, result_buf, buf, buflen,
h_errnop);
return (result ? 0 : -1);
}
static int my_gethostbyname_r (const char * name,
struct hostent * result_buf,
char * buf, size_t buflen,
struct hostent ** result,
int * h_errnop) {
*result = gethostbyname_r(name, result_buf, buf, buflen, h_errnop);
return (result ? 0 : -1);
}
#else
/* Linux, maybe others */
#define my_gethostbyaddr_r gethostbyaddr_r
#define my_gethostbyname_r gethostbyname_r
#endif
#ifdef _WIN32
// Class used for static initialization of mutex or WSA layer.
class SWIipAddressInit
{
public:
SWIipAddressInit();
~SWIipAddressInit();
};
SWIipAddressInit::SWIipAddressInit()
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
}
SWIipAddressInit::~SWIipAddressInit()
{
WSACleanup();
}
static SWIipAddressInit G_netInit;
#endif
#define SOCK_ERROR(classname, msg) \
do { \
if (_logger) \
{ \
if (errno) \
_logger->Error(500, L"%s%S%s%S%s%S%s%d", L"class", classname, L"msg", msg, \
L"errnoStr", strerror(errno), L"errno", errno); \
else \
_logger->Error(500, L"%s%S%s%S", L"class", classname, L"msg", msg); \
} \
} while(0)
SWIipAddress::SWIipAddress(const SWIipAddress &sina)
{
_logger = sina._logger;
sin_family = sina.sin_family;
sin_addr.s_addr = sina.sin_addr.s_addr;
sin_port = sina.sin_port;
}
SWIipAddress::SWIipAddress(SWIutilLogger *logger)
{
_logger = logger;
sin_family = AF_INET;
sin_addr.s_addr = htonl(INADDR_ANY);
sin_port = 0;
}
SWIipAddress::SWIipAddress(unsigned long addr,
int port_no,
SWIutilLogger *logger)
{
// addr and port_no are in host byte order
_logger = logger;
sin_family = AF_INET;
sin_addr.s_addr = htonl(addr);
sin_port = htons(port_no);
}
SWIipAddress::SWIipAddress(unsigned long addr,
const char* sn,
const char* pn,
SWIutilLogger *logger)
{
// addr is in host byte order
_logger = logger;
sin_family = AF_INET;
sin_addr.s_addr = htonl (addr);
setport(sn, pn);
}
SWIipAddress::SWIipAddress(const char* host_name,
int port_no,
SWIutilLogger *logger)
{
// port_no is in host byte order
_logger = logger;
sethostname(host_name);
sin_port = htons(port_no);
}
SWIipAddress::SWIipAddress(const char* hn,
const char* sn,
const char* pn,
SWIutilLogger *logger)
{
_logger = logger;
sethostname(hn);
setport(sn, pn);
}
void SWIipAddress::setport(int port_no)
{
sin_port = htons(port_no);
}
int SWIipAddress::setport(const char* sn, const char* pn)
{
servent* sp = getservbyname(sn, pn);
if (sp == 0)
{
SOCK_ERROR("SWIipAddress", "invalid service name");
return -1;
}
sin_port = sp->s_port;
return 0;
}
int SWIipAddress::getport() const
{
return ntohs (sin_port);
}
int SWIipAddress::sethostname(const char* host_name)
{
if ( (sin_addr.s_addr = inet_addr(host_name)) == (in_addr_t) -1) {
int hostErrno;
struct hostent hostResult;
char hostBuffer[4096];
hostent* hp;
if ((my_gethostbyname_r(host_name, &hostResult, hostBuffer,
2048, &hp, &hostErrno) != 0) ||
(hp == 0))
{
return -1;
}
memcpy(&sin_addr, hp->h_addr, hp->h_length);
sin_family = hp->h_addrtype;
}
else
sin_family = AF_INET;
return 0;
}
int SWIipAddress::gethostname(char *hostname, size_t hostnameLen) const
{
hostname[0] = '\0';
if (sin_addr.s_addr == htonl(INADDR_ANY)) {
if (::gethostname(hostname, hostnameLen) == -1) {
SOCK_ERROR("SWIipAddress", "gethostname");
hostname[0] = '\0';
return -1;
}
return 0;
}
int hostErrno;
struct hostent hostResult;
char hostBuffer[4096];
hostent* hp;
if ((my_gethostbyaddr_r((const char*) &sin_addr, sizeof(sin_addr),
family(), &hostResult, hostBuffer, 2048, &hp,
&hostErrno) != 0) ||
(hp == 0))
{
SWIipAddress::herror("gethostbyaddr");
return -1;
}
if ((hp->h_name) && (strlen(hp->h_name) < hostnameLen)) {
strcpy (hostname, hp->h_name);
return 0;
}
return -1;
}
unsigned int SWIipAddress::hashCode() const
{
unsigned int h = (unsigned int) ntohl(sin_addr.s_addr);
h <<= 16;
h |= ntohs(sin_port) & 0xFF;
return h;
}
bool SWIipAddress::operator==(const SWIipAddress& rhs) const
{
if (this == &rhs) return true;
return sin_addr.s_addr == rhs.sin_addr.s_addr &&
sin_port == rhs.sin_port;
}
SWIHashable *SWIipAddress::clone() const
{
return new SWIipAddress(*this);
}
bool SWIipAddress::equals(const SWIHashable *rhs) const
{
return operator==(*((const SWIipAddress *) rhs));
}
#ifdef _WIN32
static char* errmsg[] = {
"No error",
"Host not found",
"Try again",
"No recovery",
"No address"
"Unknown error"
};
/* Winsock.h maps h_errno to WSAGetLastError() function call */
void SWIipAddress::herror(const char* em) const
{
int err;
switch(h_errno) { /* calls WSAGetLastError() */
case HOST_NOT_FOUND:
err = 1;
break;
case TRY_AGAIN:
err = 2;
break;
case NO_RECOVERY:
err = 3;
break;
case NO_ADDRESS:
err = 4;
break;
default:
err = 5;
break;
}
SOCK_ERROR(em, errmsg[err]);
}
#else // !_WIN32
/* Use the native UNIX call */
void SWIipAddress::herror(const char* em) const
{
#ifdef _decunix_
if (_logger)
{
if (errno)
Error(500, L"%s%S%s%d%s%S%s%d", L"class", em, L"h_errno", h_errno,
L"errnoStr", strerror(errno), L"errno", errno);
else
Error(500, L"%s%S%s%d", L"class", em, L"h_errno", h_errno);
}
#else
SOCK_ERROR(em, hstrerror(h_errno));
#endif
}
#endif // !_WIN32
#if 0
SWIipAddress::SWIipAddress (int port)
: ipAddressSet(false)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -