📄 networkaddress.cxx
字号:
/* ==================================================================== * The Vovida Software License, Version 1.0 * * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The names "VOCAL", "Vovida Open Communication Application Library", * and "Vovida Open Communication Application Library (VOCAL)" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact vocal@vovida.org. * * 4. Products derived from this software may not be called "VOCAL", nor * may "VOCAL" appear in their name, without prior written * permission of Vovida Networks, Inc. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. * * ==================================================================== * * This software consists of voluntary contributions made by Vovida * Networks, Inc. and many individuals on behalf of Vovida Networks, * Inc. For more information on Vovida Networks, Inc., please see * <http://www.vovida.org/>. * */static const char* const NetworkAddress_cxx_Version ="$Id: NetworkAddress.cxx,v 1.41.2.12 2003/03/13 17:08:03 bko Exp $";#include <string>#if defined(__FreeBSD__) || defined (__APPLE__)#include <sys/types.h>#include <netdb_r.h>#endif#if defined (__APPLE__)#include <sys/types.h>#include "netdb_r.h"#endif#include "errno.h"#include <errno.h>#include <netinet/in.h>#include <arpa/inet.h>#include <strstream>#include <netdb.h>#include <iostream>#include <string.h>#include "global.h"#include "NetworkAddress.h"#include "NetworkConfig.hxx"#include "cpLog.h"#include "vsock.hxx"#ifdef WIN32#include "Lock.hxx"#include "Mutex.hxx"using Vocal::Threads::Mutex;using Vocal::Threads::Lock;#endifconst int NetworkAddress::getHostLookupFailed = 1;const int NetworkAddress::getHostLookupOK = 0;string NetworkAddress::localHostName;NetworkAddress::UnresolvedException::UnresolvedException(const string& reason, const string& file, const int line) : VException(reason, file, line){}NetworkAddress::NetworkAddress ( int port /* = -1 */) : aPort(port), ipAddressSet(false), sockAddrSet(false){ hostName = getLocalHostName();}NetworkAddress::NetworkAddress ( const Data& hostname, int port /* = -1 */) : aPort(port), ipAddressSet(false), sockAddrSet(false){ setHostName(hostname);}DataNetworkAddress::getLocalHostName() { if(localHostName.size() == 0) { char buffer[256]; if (gethostname(buffer,256) == -1) { throw UnresolvedException("Could not get hostname", __FILE__,__LINE__); } localHostName = buffer; } return localHostName;}voidNetworkAddress::setHostName ( const Data& hostname ){ cpLog (LOG_DEBUG_STACK, "NetworkAddress::setHostName(%s)", hostname.c_str()); ipAddressSet = false; bool v6Addr = false; sockAddrSet = false; Data tmpAddr = hostname; int pos = hostname.find("]"); //case 1 [ipv6Address] if (pos != Data::npos) { int match = hostname.find("["); if (match!=Data::npos) //Found matching [ { cpLog (LOG_DEBUG_STACK, "Detected v6 address"); hostName = hostname; tmpAddr = hostname.substr(match+1,pos-1); v6Addr = true; } pos = hostname.find(":", pos); if (pos != Data::npos) { setPort(atoi(hostname.substr(pos+1, Data::npos).c_str())); } } else if(is_valid_ip6_addr(hostname)) { //case 2 - ipv6address //Do nothing v6Addr = true; } else { pos = hostname.find(":", 0); hostName = hostname.substr(0,pos); tmpAddr = hostName; if (pos != Data::npos) { setPort(atoi(hostname.substr(pos+1, Data::npos).c_str())); } } //fall through - all other cases if (v6Addr || (is_valid_ip_addr(tmpAddr))) // Hostname is infact an IP address { cpLog (LOG_DEBUG_STACK, "Setting ipAddress to %s", tmpAddr.c_str()); ipAddress = tmpAddr; ipAddressSet = true; hostName = ""; //Set it later when someone asks for it //Get the hostName from the IP address //hostName = getHostByAddress(tmpAddr); } else { ipAddressSet = false; }}voidNetworkAddress::setPort( int iPort ){ if(iPort != aPort) { cpLog (LOG_DEBUG_STACK, "NetworkAddress::setPort(%d)", iPort); sockAddrSet = false; aPort = iPort; }}const Data&NetworkAddress::getHostName( ) const{ cpLog(LOG_DEBUG_STACK, "NetworkAddress::getHostName()"); if(hostName.length() == 0) { hostName = getHostByAddress(ipAddress); } return hostName;}const Data&NetworkAddress::getIpName () const{ cpLog(LOG_DEBUG_STACK, "NetworkAddress::getIpName()"); if(!ipAddressSet) initIpAddress(); cpLog(LOG_DEBUG_STACK, "returning: %s", ipAddress.logData()); return ipAddress;}u_int32_tNetworkAddress::getIp4Address () const{ cpLog(LOG_ERR, "****** UNSUPPORTED NetworkAddress::getIp4Address() called"); // TODO!!/* u_int32_t lTmp; initIpAddress(); memcpy((void *) &lTmp, ipAddress, IPV4_LENGTH); return lTmp; */ return 0;}voidNetworkAddress::getSockAddr (struct sockaddr_storage * socka, struct addrinfo* uhints /* default 0 */) const{ //cpLog(LOG_DEBUG_STACK, "NetworkAddress::getSockAddr()"); if(sockAddrSet) { memcpy((void *)socka, (void *)&sa_cache, sizeof(sa_cache)); return ; } char* port = 0; // Check port isnt -1 if(aPort==-1) { cpLog(LOG_DEBUG, "No port for host name:%s", hostName.c_str()); port = 0; } else { port = new char[56]; sprintf(port, "%u", aPort); } if(!ipAddressSet || !is_valid_ip_addr(ipAddress)) initIpAddress(); if(ipAddress.length()==0 && port==NULL) { cpLog(LOG_ERR, "Failed to get address info"); return; // Nothing for us to do } cpLog(LOG_DEBUG_STACK, "ipAddress: %s", ipAddress.logData()); struct addrinfo hints; struct addrinfo *res = 0; // xxx workaround for glibc ambiguity // Setup structures memset(&hints, 0, sizeof(hints)); cpLog(LOG_DEBUG_STACK, "getaddrinfo()"); int error; if(uhints != 0) { //Use the hints caller have provide memcpy(&hints, uhints, sizeof(hints)); if(hints.ai_flags == AI_PASSIVE) { error = getaddrinfo(0, port, &hints, &res); } else { error = getaddrinfo(ipAddress.logData(), port, &hints, &res); } } else { hints.ai_flags = AI_NUMERICHOST; hints.ai_family = NetworkConfig::instance().getAddrFamily(); hints.ai_socktype = SOCK_DGRAM; if(ipAddress.length()) { error = getaddrinfo(ipAddress.logData(), port, &hints, &res); } else { error = getaddrinfo(0, port, &hints, &res); } } if (error) { cpLog(LOG_ERR, gai_strerror(error)); cpLog(LOG_ERR, "IP Address: %s, port: %s\n", ipAddress.logData(), port); if(res != 0) { freeAddrInfo(res); } } else { memcpy((void *)socka, (void *)res->ai_addr, res->ai_addrlen); // Cache it memcpy((void *)&sa_cache, (void *)res->ai_addr, res->ai_addrlen); sockAddrSet = true; freeAddrInfo(res); } delete[] port;}intNetworkAddress::getPort () const{ cpLog(LOG_DEBUG_STACK, "NetworkAddress::getPort()"); return aPort;}booloperator == ( const NetworkAddress & xAddress, const NetworkAddress & yAddress ){ cpLog(LOG_DEBUG_STACK, "hostname %s %s", xAddress.getHostName().c_str(), yAddress.getHostName().c_str()); cpLog(LOG_DEBUG_STACK, "ipAddress %s %s", xAddress.getIpName().c_str(), yAddress.getIpName().c_str()); cpLog(LOG_DEBUG_STACK, "port %d %d", xAddress.getPort(), yAddress.getPort()); if ((xAddress.getHostName() == yAddress.getHostName()) && (xAddress.getIpName() == yAddress.getIpName()) && (xAddress.getPort()==yAddress.getPort())) return true; else return false;}booloperator != ( const NetworkAddress & xAddress, const NetworkAddress & yAddress ){ return !(xAddress == yAddress);}NetworkAddress& NetworkAddress::operator=( const NetworkAddress& x ){ if(this != &x) { aPort = x.getPort(); ipAddress = x.getIpName(); ipAddressSet = x.ipAddressSet; x.getSockAddr(&(sa_cache)); sockAddrSet = x.sockAddrSet; hostName = x.hostName; } return ( *this );}ostream &NetworkAddress::print ( ostream & xStr ) const{ try {// initIpAddress(); xStr << hostName << "(" << getIpName() << ")"; } catch (UnresolvedException& e) { xStr << hostName << "(unresolved)"; } if ( aPort ) { xStr << ":" << aPort; } return xStr;}u_int32_tNetworkAddress::hashIpPort( ) const{ struct sockaddr_storage xSrc; getSockAddr(&xSrc); u_int32_t ipAddressLocal; //Either it is IPv4 or IPv6, just take the first 32 bits memcpy(&ipAddressLocal, &xSrc, sizeof(ipAddressLocal)); int port = getPort (); return (hashIpPort( ipAddressLocal, port )) ;}u_int32_tNetworkAddress::hashIpPort( const u_int32_t lipAddress, const int port ){ u_int32_t hashKey = 0x0; hashKey = (lipAddress << 16) | (port & 0xFF); return hashKey;}voidNetworkAddress::initIpAddress() const{ cpLog(LOG_DEBUG_STACK, "initIpAddress() for hostName %s", hostName.c_str()); if (ipAddressSet) return; struct addrinfo hints; struct addrinfo *res = 0; // Setup structures memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_STREAM; Data the_host = hostName; if(the_host.find("[", 0) != Data::npos) the_host = the_host.substr(1, the_host.length()-2); bool nameIsAddress = false; hints.ai_family = NetworkConfig::instance().getAddrFamily(); if (is_valid_ip6_addr(the_host)) { hints.ai_family = PF_INET6; nameIsAddress = true; } else if (is_valid_ip4_addr(the_host)) { hints.ai_family = PF_INET; nameIsAddress = true; } //if nameIsAddress, we are done if(nameIsAddress) { ipAddress = the_host; cpLog(LOG_DEBUG_STACK, "Set ipAddress to %s", ipAddress.c_str()); ipAddressSet = true; return; } cpLog(LOG_DEBUG_STACK, "getaddrinfo()"); //it is a host name to do nslookup to get the IP address
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -