|
reSIProcate/stack
9694
|
00001 #ifndef WIN32 00002 #include <sys/types.h> 00003 #include <sys/socket.h> 00004 #include <arpa/inet.h> 00005 #include <netdb.h> 00006 #else 00007 #include <sys/types.h> 00008 #endif 00009 00010 #include <stdio.h> 00011 #include <errno.h> 00012 00013 #include "rutil/Socket.hxx" 00014 00015 #include "resip/stack/Symbols.hxx" 00016 #include "resip/stack/Uri.hxx" 00017 00018 #include "rutil/Socket.hxx" 00019 #include "rutil/Data.hxx" 00020 #include "rutil/Logger.hxx" 00021 #include "rutil/ParseBuffer.hxx" 00022 00023 #include "Resolver.hxx" 00024 00025 #define RESIPROCATE_SUBSYSTEM resip::Subsystem::SIP 00026 00027 using namespace resip; 00028 00029 Resolver::Resolver(const Uri& uri) : 00030 mHost(uri.host()), 00031 mPort(uri.port() ? uri.port() : 5060) 00032 { 00033 bool isNumeric = isIpAddress(mHost); 00034 if (!uri.exists(p_transport) ) 00035 { 00036 if (isNumeric) 00037 { 00038 if (uri.scheme() == Symbols::Sip) 00039 { 00040 mTransport = UDP; 00041 } 00042 else if (uri.scheme() == Symbols::Sips) 00043 { 00044 mTransport = TCP; 00045 } 00046 } 00047 else // not numeric 00048 { 00049 if (1) // uri.portSpecified()) // !jf! 00050 { 00051 if (uri.scheme() == Symbols::Sip) 00052 { 00053 mTransport = UDP; 00054 } 00055 else if (uri.scheme() == Symbols::Sips) 00056 { 00057 mTransport = TCP; 00058 } 00059 } 00060 else // NAPTR query - yuck! 00061 { 00062 // Rohan, step up to the plate buddy. 00063 mTransport = UDP; // !jf! not done yet 00064 } 00065 } 00066 } 00067 00068 if (!isNumeric) 00069 { 00070 if (1) // !jf! uri.portSpecified()) 00071 { 00072 lookupARecords(); 00073 // do an A or AAAA DNS lookup 00074 00075 } 00076 else 00077 { 00078 // do SRV lookup on result of NAPTR lookup 00079 00080 // if no NAPTR lookup, do SRV lookup on _sips for sips and _sip for sip 00081 00082 // if no result on SRV lookup, do an A or AAAA lookup 00083 00084 } 00085 } 00086 else 00087 { 00088 Tuple tuple; 00089 if (inet_pton(AF_INET, mHost.c_str(), &tuple.ipv4.s_addr) <= 0) 00090 { 00091 DebugLog( << "inet_pton failed to parse address: " << mHost << " " << strerror(errno)); 00092 assert(0); 00093 } 00094 tuple.port = mPort; 00095 tuple.transportType = mTransport; 00096 00097 mNextHops.push_back(tuple); 00098 } 00099 00100 } 00101 00102 00103 Resolver::Resolver(const Data& host, int port, TransportType transport) 00104 : mTransport(transport), 00105 mHost(host), 00106 mPort(port) 00107 { 00108 bool isNumeric = isIpAddress(mHost); 00109 if (!isNumeric) 00110 { 00111 if (1) // !jf! uri.portSpecified()) 00112 { 00113 lookupARecords(); 00114 // do an A or AAAA DNS lookup 00115 00116 } 00117 else 00118 { 00119 // do SRV lookup on result of NAPTR lookup 00120 00121 // if no NAPTR lookup, do SRV lookup on _sips for sips and _sip for sip 00122 00123 // if no result on SRV lookup, do an A or AAAA lookup 00124 00125 } 00126 } 00127 else 00128 { 00129 Tuple tuple; 00130 if (inet_pton(AF_INET, mHost.c_str(), &tuple.ipv4.s_addr) <= 0) 00131 { 00132 DebugLog( << "inet_pton failed to parse address: " << mHost << " " << strerror(errno)); 00133 assert(0); 00134 } 00135 tuple.port = mPort; 00136 tuple.transportType = mTransport; 00137 00138 mNextHops.push_back(tuple); 00139 } 00140 } 00141 00142 00143 void 00144 Resolver::lookupARecords() 00145 { 00146 struct hostent hostbuf; 00147 struct hostent* result=0; 00148 00149 int herrno=0; 00150 char buffer[8192]; 00151 #ifdef __QNX__ 00152 result = gethostbyname_r (mHost.c_str(), &hostbuf, buffer, sizeof(buffer), &herrno); 00153 if (result == 0) 00154 { 00155 #else 00156 00157 #if defined( WIN32 ) || defined( __APPLE__ ) || defined (__SUNPRO_CC) || defined(__FreeBSD__) 00158 assert(0); // !cj! 00159 int ret = -1; 00160 #else 00161 int ret = gethostbyname_r (mHost.c_str(), &hostbuf, buffer, sizeof(buffer), &result, &herrno); 00162 #endif 00163 assert (ret != ERANGE); 00164 00165 if (ret != 0) 00166 { 00167 #endif 00168 switch (herrno) 00169 { 00170 case HOST_NOT_FOUND: 00171 InfoLog ( << "host not found: " << mHost); 00172 break; 00173 case NO_DATA: 00174 InfoLog ( << "no data found for: " << mHost); 00175 break; 00176 case NO_RECOVERY: 00177 InfoLog ( << "no recovery lookup up: " << mHost); 00178 break; 00179 case TRY_AGAIN: 00180 InfoLog ( << "try again: " << mHost); 00181 break; 00182 } 00183 } 00184 else 00185 { 00186 assert(result); 00187 assert(result->h_length == 4); 00188 00189 DebugLog (<< "DNS lookup of " << mHost << ": canonical name: " << result->h_name); 00190 char str[256]; 00191 for (char** pptr = result->h_addr_list; *pptr != 0; pptr++) 00192 { 00193 Tuple tuple; 00194 tuple.ipv4.s_addr = *((u_int32_t*)(*pptr)); 00195 tuple.port = mPort; 00196 tuple.transportType = mTransport; 00197 00198 mNextHops.push_back(tuple); 00199 #ifndef WIN32 00200 DebugLog (<< inet_ntop(AF_INET, &tuple.ipv4.s_addr, str, sizeof(str))); 00201 #endif 00202 00203 } 00204 } 00205 } 00206 00207 bool 00208 Resolver::isIpAddress(const Data& data) 00209 { 00210 // ok, this is fairly monstrous but it works. 00211 unsigned int p1,p2,p3,p4; 00212 int count=0; 00213 int result = sscanf( data.c_str(), 00214 "%u.%u.%u.%u%n", 00215 &p1, &p2, &p3, &p4, &count ); 00216 00217 if ( (result == 4) && (p1 <= 255) && (p2 <= 255) && (p3 <= 255) && (p4 <= 255) && (count == int(data.size())) ) 00218 { 00219 return true; 00220 } 00221 else 00222 { 00223 return false; 00224 } 00225 } 00226 00227 00228 Data 00229 Resolver::getHostName() 00230 { 00231 char buffer[255]; 00232 if (gethostname(buffer, sizeof(buffer)) < 0) 00233 { 00234 InfoLog (<< "Failed gethostname() " << strerror(errno)); 00235 return "localhost"; 00236 } 00237 else 00238 { 00239 return Data(buffer); 00240 } 00241 } 00242 /* ==================================================================== 00243 * The Vovida Software License, Version 1.0 00244 * 00245 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 00246 * 00247 * Redistribution and use in source and binary forms, with or without 00248 * modification, are permitted provided that the following conditions 00249 * are met: 00250 * 00251 * 1. Redistributions of source code must retain the above copyright 00252 * notice, this list of conditions and the following disclaimer. 00253 * 00254 * 2. Redistributions in binary form must reproduce the above copyright 00255 * notice, this list of conditions and the following disclaimer in 00256 * the documentation and/or other materials provided with the 00257 * distribution. 00258 * 00259 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 00260 * and "Vovida Open Communication Application Library (VOCAL)" must 00261 * not be used to endorse or promote products derived from this 00262 * software without prior written permission. For written 00263 * permission, please contact vocal@vovida.org. 00264 * 00265 * 4. Products derived from this software may not be called "VOCAL", nor 00266 * may "VOCAL" appear in their name, without prior written 00267 * permission of Vovida Networks, Inc. 00268 * 00269 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 00270 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00271 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 00272 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 00273 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 00274 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 00275 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00276 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00277 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 00278 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00279 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 00280 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 00281 * DAMAGE. 00282 * 00283 * ==================================================================== 00284 * 00285 * This software consists of voluntary contributions made by Vovida 00286 * Networks, Inc. and many individuals on behalf of Vovida Networks, 00287 * Inc. For more information on Vovida Networks, Inc., please see 00288 * <http://www.vovida.org/>. 00289 * 00290 */
1.7.5.1