llhost.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /**
  2. * @file llhost.cpp
  3. * @brief Encapsulates an IP address and a port.
  4. *
  5. * $LicenseInfo:firstyear=2000&license=viewergpl$
  6. *
  7. * Copyright (c) 2000-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #include "linden_common.h"
  33. #include "llhost.h"
  34. #if LL_WINDOWS
  35. #define WIN32_LEAN_AND_MEAN
  36. #include <winsock2.h>
  37. #else
  38. #include <netdb.h>
  39. #include <netinet/in.h> // ntonl()
  40. #include <sys/types.h>
  41. #include <sys/socket.h>
  42. #include <arpa/inet.h>
  43. #endif
  44. const char* LOOPBACK_ADDRESS_STRING = "127.0.0.1";
  45. const char* BROADCAST_ADDRESS_STRING = "255.255.255.255";
  46. ///////////////////////////////////////////////////////////////////////////////
  47. // Utility functions (used to be in llnet.cpp, but not related to the OS
  48. // specific network implementation, thus moved here). HB
  49. ///////////////////////////////////////////////////////////////////////////////
  50. const char* u32_to_ip_string(U32 ip)
  51. {
  52. static char buffer[MAXADDRSTR];
  53. // Convert the IP address into a string
  54. in_addr in;
  55. in.s_addr = ip;
  56. char* result = inet_ntoa(in);
  57. // NULL indicates error in conversion
  58. if (result)
  59. {
  60. strncpy(buffer, result, MAXADDRSTR);
  61. buffer[MAXADDRSTR - 1] = '\0';
  62. return buffer;
  63. }
  64. return "(bad IP addr)";
  65. }
  66. // Returns ip_string if successful, NULL if not. Copies into ip_string
  67. char* u32_to_ip_string(U32 ip, char* ip_string)
  68. {
  69. char* result;
  70. in_addr in;
  71. // Convert the IP address into a string
  72. in.s_addr = ip;
  73. result = inet_ntoa(in);
  74. // NULL indicates error in conversion
  75. if (result != NULL)
  76. {
  77. // the function signature needs to change to pass in the lengfth of
  78. // first and last.
  79. strcpy(ip_string, result);
  80. return ip_string;
  81. }
  82. else
  83. {
  84. return NULL;
  85. }
  86. }
  87. // Wrapper for inet_addr()
  88. U32 ip_string_to_u32(const char* ip_string)
  89. {
  90. // *NOTE: Windows does not support inet_aton() so we are using inet_addr().
  91. // Unfortunately, INADDR_NONE == INADDR_BROADCAST, so we have to check
  92. // whether the input is a broadcast address before deciding that @ip_string
  93. // is invalid. Also, our definition of INVALID_HOST_IP_ADDRESS does not
  94. // allow us to use wildcard addresses. -Ambroff
  95. U32 ip = inet_addr(ip_string);
  96. if (ip == INADDR_NONE &&
  97. strncmp(ip_string, BROADCAST_ADDRESS_STRING, MAXADDRSTR) != 0)
  98. {
  99. llwarns << "ip_string_to_u32() failed, Error: Invalid IP string '"
  100. << ip_string << "'" << llendl;
  101. return INVALID_HOST_IP_ADDRESS;
  102. }
  103. return ip;
  104. }
  105. ///////////////////////////////////////////////////////////////////////////////
  106. // LLHost class proper
  107. ///////////////////////////////////////////////////////////////////////////////
  108. //static
  109. const LLHost LLHost::invalid(INVALID_PORT, INVALID_HOST_IP_ADDRESS);
  110. LLHost::LLHost(const std::string& ip_and_port)
  111. {
  112. std::string::size_type colon_index = ip_and_port.find(":");
  113. if (colon_index == std::string::npos)
  114. {
  115. mIP = ip_string_to_u32(ip_and_port.c_str());
  116. mPort = 0;
  117. }
  118. else
  119. {
  120. std::string ip_str(ip_and_port, 0, colon_index);
  121. std::string port_str(ip_and_port, colon_index+1);
  122. mIP = ip_string_to_u32(ip_str.c_str());
  123. mPort = atol(port_str.c_str());
  124. }
  125. }
  126. std::string LLHost::getIPandPort() const
  127. {
  128. return llformat("%s:%u", u32_to_ip_string(mIP), mPort);
  129. }
  130. std::string LLHost::getIPString() const
  131. {
  132. return std::string(u32_to_ip_string(mIP));
  133. }
  134. std::string LLHost::getHostName() const
  135. {
  136. hostent* he;
  137. if (INVALID_HOST_IP_ADDRESS == mIP)
  138. {
  139. llwarns << "LLHost::getHostName() : Invalid IP address" << llendl;
  140. return std::string();
  141. }
  142. he = gethostbyaddr((char*)&mIP, sizeof(mIP), AF_INET);
  143. if (!he)
  144. {
  145. #if LL_WINDOWS
  146. llwarns << "Could not find host name for address " << mIP
  147. << ". Error: " << WSAGetLastError() << llendl;
  148. #else
  149. llwarns << "Could not find host name for address " << mIP
  150. << ". Error: " << h_errno << llendl;
  151. #endif
  152. return std::string();
  153. }
  154. return ll_safe_string(he->h_name);
  155. }
  156. bool LLHost::setHostByName(const std::string& hostname)
  157. {
  158. hostent* he;
  159. std::string local_name(hostname);
  160. #if LL_WINDOWS
  161. // We may need an equivalent for Linux, but not sure - djs
  162. LLStringUtil::toUpper(local_name);
  163. #endif
  164. he = gethostbyname(local_name.c_str());
  165. if (!he)
  166. {
  167. U32 ip_address = ip_string_to_u32(hostname.c_str());
  168. he = gethostbyaddr((char *)&ip_address, sizeof(ip_address), AF_INET);
  169. }
  170. if (he)
  171. {
  172. mIP = *(U32*)he->h_addr_list[0];
  173. return true;
  174. }
  175. else
  176. {
  177. setAddress(local_name);
  178. // In windows, h_errno is a macro for WSAGetLastError(), so store value
  179. // here
  180. S32 error_number = h_errno;
  181. switch (error_number)
  182. {
  183. case TRY_AGAIN: // XXX how to handle this case?
  184. llwarns << "Try again" << llendl;
  185. break;
  186. case HOST_NOT_FOUND:
  187. case NO_ADDRESS: // NO_DATA
  188. llwarns << "Host not found" << llendl;
  189. break;
  190. case NO_RECOVERY:
  191. llwarns << "Unrecoverable error" << llendl;
  192. break;
  193. default:
  194. llwarns << "Unknown error #" << error_number << llendl;
  195. }
  196. return false;
  197. }
  198. }
  199. LLHost& LLHost::operator=(const LLHost& rhs)
  200. {
  201. if (this != &rhs)
  202. {
  203. set(rhs.getAddress(), rhs.getPort());
  204. }
  205. return *this;
  206. }
  207. std::ostream& operator<<(std::ostream& os, const LLHost& hh)
  208. {
  209. os << u32_to_ip_string(hh.mIP) << ":" << hh.mPort ;
  210. return os;
  211. }
  212. #if 0
  213. std::istream& operator>>(std::istream& is, LLHost& rh)
  214. {
  215. is >> rh.mIP;
  216. is >> rh.mPort;
  217. return is;
  218. }
  219. #endif