IPAddress.cpp

00001 
00002 //
00003 // SFML - Simple and Fast Multimedia Library
00004 // Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com)
00005 //
00006 // This software is provided 'as-is', without any express or implied warranty.
00007 // In no event will the authors be held liable for any damages arising from the use of this software.
00008 //
00009 // Permission is granted to anyone to use this software for any purpose,
00010 // including commercial applications, and to alter it and redistribute it freely,
00011 // subject to the following restrictions:
00012 //
00013 // 1. The origin of this software must not be misrepresented;
00014 //    you must not claim that you wrote the original software.
00015 //    If you use this software in a product, an acknowledgment
00016 //    in the product documentation would be appreciated but is not required.
00017 //
00018 // 2. Altered source versions must be plainly marked as such,
00019 //    and must not be misrepresented as being the original software.
00020 //
00021 // 3. This notice may not be removed or altered from any source distribution.
00022 //
00024 
00026 // Headers
00028 #include <SFML/Network/IPAddress.hpp>
00029 #include <SFML/Network/Sockets.hpp>
00030 
00031 
00035 const sfIPAddress sfIPAddress::LocalHost("127.0.0.1");
00036 
00037 
00041 sfIPAddress::sfIPAddress() :
00042 myAddress(INADDR_NONE)
00043 {
00044 
00045 }
00046 
00047 
00051 sfIPAddress::sfIPAddress(const std::string& Address)
00052 {
00053     // First try to convert it as a byte representation ("xxx.xxx.xxx.xxx")
00054     myAddress = inet_addr(Address.c_str());
00055 
00056     // If not successful, try to convert it as a host name
00057     if (!IsValid())
00058     {
00059         hostent* Host = gethostbyname(Address.c_str());
00060         if (Host)
00061         {
00062             // Host found, extract its IP address
00063             myAddress = reinterpret_cast<in_addr*>(Host->h_addr)->s_addr;
00064         }
00065         else
00066         {
00067             // Host name not found on the network
00068             myAddress = INADDR_NONE;
00069         }
00070     }
00071 }
00072 
00073 
00077 sfIPAddress::sfIPAddress(sfUint8 Byte0, sfUint8 Byte1, sfUint8 Byte2, sfUint8 Byte3)
00078 {
00079     myAddress = htonl((Byte0 << 24) | (Byte1 << 16) | (Byte2 << 8) | Byte3);
00080 }
00081 
00082 
00086 bool sfIPAddress::IsValid() const
00087 {
00088     return myAddress != INADDR_NONE;
00089 }
00090 
00091 
00095 std::string sfIPAddress::ToString() const
00096 {
00097     in_addr InAddr;
00098     InAddr.s_addr = myAddress;
00099 
00100     return inet_ntoa(InAddr);
00101 }
00102 
00103 
00107 sfIPAddress sfIPAddress::GetLocalAddress()
00108 {
00109     // The method here is to connect a UDP socket to anyone (here to localhost),
00110     // and get the local socket address with the getsockname function.
00111     // UDP connection will not send anything to the network, so this function won't cause any overhead
00112 
00113     sfIPAddress LocalAddress;
00114 
00115     // Create the socket
00116     sf_private::sfSocketType Socket = socket(PF_INET, SOCK_DGRAM, 0);
00117     if (Socket == INVALID_SOCKET)
00118         return LocalAddress;
00119 
00120     // Build the host address (use a random port)
00121     sockaddr_in SockAddr;
00122     memset(SockAddr.sin_zero, 0, sizeof(SockAddr.sin_zero));
00123     SockAddr.sin_addr.s_addr = INADDR_LOOPBACK;
00124     SockAddr.sin_family      = AF_INET;
00125     SockAddr.sin_port        = htons(4567);
00126 
00127     // Connect the socket
00128     if (connect(Socket, reinterpret_cast<sockaddr*>(&SockAddr), sizeof(SockAddr)) == -1)
00129     {
00130         sf_private::close(Socket);
00131         return LocalAddress;
00132     }
00133  
00134     // Get the local address of the socket connection
00135     socklen_t Size = sizeof(SockAddr);
00136     if (getsockname(Socket, reinterpret_cast<sockaddr*>(&SockAddr), &Size) == -1)
00137     {
00138         sf_private::close(Socket);
00139         return LocalAddress;
00140     }
00141 
00142     // Close the socket
00143     sf_private::close(Socket);
00144 
00145     // Finally build the IP address
00146     LocalAddress.myAddress = SockAddr.sin_addr.s_addr;
00147 
00148     return LocalAddress;
00149 }
00150 
00151 
00155 sfIPAddress sfIPAddress::GetPublicAddress()
00156 {
00157     // The trick here is more complicated, because the only way
00158     // to get our public IP address is to get it from a distant computer.
00159     // Here we get the web page from http://www.whatismyip.org
00160     // and parse the result to extract our IP address
00161     // (not very hard : the web page contains only our IP address)
00162 
00163     sfIPAddress PublicAddress;
00164 
00165     // Create the socket
00166     sf_private::sfSocketType Socket = socket(PF_INET, SOCK_STREAM, 0);
00167     if (Socket == INVALID_SOCKET)
00168         return PublicAddress;
00169 
00170     // Build the server address (use port 80 for HTTP)
00171     sfIPAddress Server("www.whatismyip.org");
00172     sockaddr_in SockAddr;
00173     memset(SockAddr.sin_zero, 0, sizeof(SockAddr.sin_zero));
00174     SockAddr.sin_addr.s_addr = inet_addr(Server.ToString().c_str());
00175     SockAddr.sin_family      = AF_INET;
00176     SockAddr.sin_port        = htons(80);
00177 
00178     // Connect the socket
00179     if (connect(Socket, reinterpret_cast<sockaddr*>(&SockAddr), sizeof(SockAddr)) == -1)
00180     {
00181         sf_private::close(Socket);
00182         return PublicAddress;
00183     }
00184 
00185     // Send a request for getting the index page
00186     const char Request[] = "GET / HTTP/1.0\r\n"
00187                            "From: camembert@fromage.com\r\n"
00188                            "User-Agent: SFML/1.0\r\n"
00189                            "\r\n";
00190     if (send(Socket, Request, sizeof(Request), 0) <= 0)
00191     {
00192         sf_private::close(Socket);
00193         return PublicAddress;
00194     }
00195 
00196     // Get the response (the source code of the web page)
00197     char Response[1024];
00198     int Received = recv(Socket, Response, sizeof(Response), 0);
00199     if (Received <= 0)
00200     {
00201         sf_private::close(Socket);
00202         return PublicAddress;
00203     }
00204 
00205     // Close the socket
00206     sf_private::close(Socket);
00207 
00208     // Extract the address from the source code of the web page
00209     // (extract from first \r\n\r\n to the end)
00210     std::string Page(Response, Received);
00211     std::string::size_type Start = Page.find("\r\n\r\n");
00212     if (Start != std::string::npos)
00213     {
00214         PublicAddress = Page.substr(Start + 4);
00215     }
00216 
00217     return PublicAddress;
00218 }
00219 
00220 
00224 bool sfIPAddress::operator ==(const sfIPAddress& Other) const
00225 {
00226     return myAddress == Other.myAddress;
00227 }
00228 
00229 
00233 bool sfIPAddress::operator !=(const sfIPAddress& Other) const
00234 {
00235     return myAddress != Other.myAddress;
00236 }
00237 
00238 
00242 bool sfIPAddress::operator <(const sfIPAddress& Other) const
00243 {
00244     return myAddress < Other.myAddress;
00245 }
00246 
00247 
00251 bool sfIPAddress::operator >(const sfIPAddress& Other) const
00252 {
00253     return myAddress > Other.myAddress;
00254 }
00255 
00256 
00260 bool sfIPAddress::operator <=(const sfIPAddress& Other) const
00261 {
00262     return myAddress <= Other.myAddress;
00263 }
00264 
00265 
00269 bool sfIPAddress::operator >=(const sfIPAddress& Other) const
00270 {
00271     return myAddress >= Other.myAddress;
00272 }
00273 
00274 
00278 std::istream& operator >>(std::istream& Stream, sfIPAddress& Address)
00279 {
00280     std::string Str;
00281     Stream >> Str;
00282     Address = sfIPAddress(Str);
00283 
00284     return Stream;
00285 }
00286 
00287 
00291 std::ostream& operator <<(std::ostream& Stream, const sfIPAddress& Address)
00292 {
00293     return Stream << Address.ToString();
00294 }