00001 // Filename: netAddress.cxx 00002 // Created by: drose (08Feb00) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved 00008 // 00009 // All use of this software is subject to the terms of the Panda 3d 00010 // Software license. You should have received a copy of this license 00011 // along with this source code; you will also find a current copy of 00012 // the license at http://www.panda3d.org/license.txt . 00013 // 00014 // To contact the maintainers of this program write to 00015 // panda3d@yahoogroups.com . 00016 // 00017 //////////////////////////////////////////////////////////////////// 00018 00019 #include "netAddress.h" 00020 #include "pprerror.h" 00021 #include "config_net.h" 00022 00023 #include <prio.h> 00024 #include <prnetdb.h> 00025 00026 00027 //////////////////////////////////////////////////////////////////// 00028 // Function: NetAddress::Constructor 00029 // Access: Public 00030 // Description: Constructs an unspecified address. 00031 //////////////////////////////////////////////////////////////////// 00032 NetAddress:: 00033 NetAddress() { 00034 PR_InitializeNetAddr(PR_IpAddrLoopback, 0, &_addr); 00035 } 00036 00037 //////////////////////////////////////////////////////////////////// 00038 // Function: NetAddress::Constructor 00039 // Access: Public 00040 // Description: Constructs an address from a given PRNetAddr. 00041 // Normally, this constructor should not be used by user 00042 // code; instead, create a default NetAddress and use 00043 // one of the set_*() functions to set up an address. 00044 //////////////////////////////////////////////////////////////////// 00045 NetAddress:: 00046 NetAddress(const PRNetAddr &addr) : _addr(addr) { 00047 } 00048 00049 00050 //////////////////////////////////////////////////////////////////// 00051 // Function: NetAddress::set_any 00052 // Access: Public 00053 // Description: Sets the address up to refer to a particular port, 00054 // but not to any particular IP. Returns true if 00055 // successful, false otherwise (currently, this only 00056 // returns true). 00057 //////////////////////////////////////////////////////////////////// 00058 bool NetAddress:: 00059 set_any(int port) { 00060 PR_InitializeNetAddr(PR_IpAddrAny, port, &_addr); 00061 00062 return true; 00063 } 00064 00065 //////////////////////////////////////////////////////////////////// 00066 // Function: NetAddress::set_localhost 00067 // Access: Public 00068 // Description: Sets the address up to refer to a particular port, 00069 // on this host. 00070 //////////////////////////////////////////////////////////////////// 00071 bool NetAddress:: 00072 set_localhost(int port) { 00073 PR_InitializeNetAddr(PR_IpAddrLoopback, port, &_addr); 00074 00075 return true; 00076 } 00077 00078 //////////////////////////////////////////////////////////////////// 00079 // Function: NetAddress::set_host 00080 // Access: Public 00081 // Description: Sets the address up to refer to a particular port 00082 // on a particular host. Returns true if the hostname 00083 // is known, false otherwise. 00084 //////////////////////////////////////////////////////////////////// 00085 bool NetAddress:: 00086 set_host(const string &hostname, int port) { 00087 // If the hostname appears to be a dot-separated IPv4 address, then 00088 // parse it directly and store it. Some OS system libraries 00089 // (notably Win95) can't parse this themselves. 00090 union { 00091 PRUint32 l; 00092 unsigned char n[4]; 00093 } ipaddr; 00094 int ni = 0; 00095 bool is_ip = true; 00096 size_t p = 0; 00097 size_t q = 0; 00098 unsigned int num = 0; 00099 00100 while (p < hostname.length() && ni < 4 && is_ip) { 00101 if (hostname[p] == '.' && p > q) { 00102 // Now we have a number between q and p. 00103 ipaddr.n[ni] = (unsigned char)num; 00104 p++; 00105 q = p; 00106 num = 0; 00107 ni++; 00108 00109 if (num >= 256 || ni >= 4) { 00110 is_ip = false; 00111 } 00112 00113 } else if (isdigit(hostname[p])) { 00114 num = 10 * num + (unsigned int)(hostname[p] - '0'); 00115 p++; 00116 if (num >= 256) { 00117 is_ip = false; 00118 } 00119 } else { 00120 is_ip = false; 00121 } 00122 } 00123 00124 if (p == hostname.length() && ni < 4 && is_ip && p > q) { 00125 ipaddr.n[ni] = (unsigned char)num; 00126 ni++; 00127 00128 if (num >= 256) { 00129 is_ip = false; 00130 } 00131 } 00132 00133 if (p == hostname.length() && ni == 4 && is_ip) { 00134 net_cat.debug() 00135 << "Parsed IP " << (int)ipaddr.n[0] << "." << (int)ipaddr.n[1] 00136 << "." << (int)ipaddr.n[2] << "." << (int)ipaddr.n[3] << "\n"; 00137 00138 memset(&_addr, 0, sizeof(PRNetAddr)); 00139 _addr.inet.family = PR_AF_INET; 00140 _addr.inet.port = PR_htons(port); 00141 _addr.inet.ip = ipaddr.l; 00142 00143 } else { 00144 // If it's not a numeric IPv4 address, pass the whole thing on to 00145 // GetHostByName and let NSPR deal with it. 00146 00147 char buf[PR_NETDB_BUF_SIZE]; 00148 PRHostEnt host; 00149 PRStatus result = 00150 PR_GetHostByName(hostname.c_str(), buf, PR_NETDB_BUF_SIZE, &host); 00151 if (result != PR_SUCCESS) { 00152 pprerror("PR_GetHostByName"); 00153 net_cat.error() 00154 << "Unable to look up hostname " << hostname << ".\n"; 00155 return false; 00156 } 00157 00158 PRIntn next = PR_EnumerateHostEnt(0, &host, port, &_addr); 00159 00160 if (next == -1) { 00161 pprerror("PR_EnumerateHostEnt"); 00162 return false; 00163 } else if (next == 0) { 00164 net_cat.error() 00165 << "No addresses available for " << hostname << ".\n"; 00166 return false; 00167 } 00168 } 00169 00170 return true; 00171 } 00172 00173 //////////////////////////////////////////////////////////////////// 00174 // Function: NetAddress::clear 00175 // Access: Public 00176 // Description: Resets the NetAddress to its initial state. 00177 //////////////////////////////////////////////////////////////////// 00178 void NetAddress:: 00179 clear() { 00180 PR_InitializeNetAddr(PR_IpAddrLoopback, 0, &_addr); 00181 } 00182 00183 //////////////////////////////////////////////////////////////////// 00184 // Function: NetAddress::get_port 00185 // Access: Public 00186 // Description: Returns the port number to which this address refers. 00187 //////////////////////////////////////////////////////////////////// 00188 int NetAddress:: 00189 get_port() const { 00190 return PR_ntohs(_addr.inet.port); 00191 } 00192 00193 //////////////////////////////////////////////////////////////////// 00194 // Function: NetAddress::set_port 00195 // Access: Public 00196 // Description: Resets the port number without otherwise changing the 00197 // address. 00198 //////////////////////////////////////////////////////////////////// 00199 void NetAddress:: 00200 set_port(int port) { 00201 PR_InitializeNetAddr(PR_IpAddrNull, port, &_addr); 00202 } 00203 00204 //////////////////////////////////////////////////////////////////// 00205 // Function: NetAddress::get_ip_string 00206 // Access: Public 00207 // Description: Returns the IP address to which this address refers, 00208 // formatted as a string. 00209 //////////////////////////////////////////////////////////////////// 00210 string NetAddress:: 00211 get_ip_string() const { 00212 static const int buf_len = 1024; 00213 char buf[buf_len]; 00214 00215 PRStatus result = 00216 PR_NetAddrToString(&_addr, buf, buf_len); 00217 if (result != PR_SUCCESS) { 00218 pprerror("PR_NetAddrToString"); 00219 return "error"; 00220 } 00221 00222 return string(buf); 00223 } 00224 00225 //////////////////////////////////////////////////////////////////// 00226 // Function: NetAddress::get_ip 00227 // Access: Public 00228 // Description: Returns the IP address to which this address refers, 00229 // as a 32-bit integer, in host byte order. 00230 //////////////////////////////////////////////////////////////////// 00231 PN_uint32 NetAddress:: 00232 get_ip() const { 00233 return PR_ntohl(_addr.inet.ip); 00234 } 00235 00236 //////////////////////////////////////////////////////////////////// 00237 // Function: NetAddress::get_ip_component 00238 // Access: Public 00239 // Description: Returns the nth 8-bit component of the IP address. 00240 // An IP address has four components; component 0 is the 00241 // first (leftmost), and component 3 is the last 00242 // (rightmost) in the dotted number convention. 00243 //////////////////////////////////////////////////////////////////// 00244 PN_uint8 NetAddress:: 00245 get_ip_component(int n) const { 00246 nassertr(n >= 0 && n < 4, 0); 00247 const PN_uint8 *ip = (const PN_uint8 *)&_addr.inet.ip; 00248 return ip[n]; 00249 } 00250 00251 00252 //////////////////////////////////////////////////////////////////// 00253 // Function: NetAddress::get_addr 00254 // Access: Public 00255 // Description: Returns the PRNetAddr for this address. 00256 //////////////////////////////////////////////////////////////////// 00257 PRNetAddr *NetAddress:: 00258 get_addr() const { 00259 return (PRNetAddr *)&_addr; 00260 } 00261 00262 //////////////////////////////////////////////////////////////////// 00263 // Function: NetAddress::output 00264 // Access: Public 00265 // Description: 00266 //////////////////////////////////////////////////////////////////// 00267 void NetAddress:: 00268 output(ostream &out) const { 00269 out << get_ip_string(); 00270 }