1 /*
2 DSFML - The Simple and Fast Multimedia Library for D
3 
4 Copyright (c) 2013 - 2015 Jeremy DeHaan (dehaan.jeremiah@gmail.com)
5 
6 This software is provided 'as-is', without any express or implied warranty.
7 In no event will the authors be held liable for any damages arising from the use of this software.
8 
9 Permission is granted to anyone to use this software for any purpose, including commercial applications,
10 and to alter it and redistribute it freely, subject to the following restrictions:
11 
12 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software.
13 If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
14 
15 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
16 
17 3. This notice may not be removed or altered from any source distribution
18 */
19 
20 ///A module containing the IpAddress struct.
21 module dsfml.network.ipaddress;
22 
23 import core.time;
24 
25 /**
26  *Encapsulate an IPv4 network address.
27  *
28  *IpAddress is a utility class for manipulating network addresses.
29  *
30  *It provides a set a implicit constructors and conversion functions to easily build or transform an IP address from/to various representations.
31  */
32 struct IpAddress
33 {
34 	//Initialize m_address with "0.0.0.0" and finish filling it out with /0 characters.
35 	package char[16] m_address = ['0','.','0','.','0','.','0', 0,0,0,0,0,0,0,0,0];
36 
37 	///Construct the address from a string.
38 	///
39 	///Here address can be either a decimal address (ex: "192.168.1.56") or a network name (ex: "localhost").
40 	///
41 	///Params:
42     ///		address = IP address or network name.
43 	this(string address)
44 	{
45 		import dsfml.system.string;
46 		sfIpAddress_fromString(toStringz(address) ,m_address.ptr);
47 	}
48 	
49 	///Construct the address from 4 bytes.
50 	///
51 	///Calling IpAddress(a, b, c, d) is equivalent to calling IpAddress("a.b.c.d"), but safer as it doesn't have to parse a string to get the address components.
52 	///
53 	///Parameters
54     ///		byte0 = First byte of the address.
55     ///		byte1 = Second byte of the address.
56     ///		byte2 = Third byte of the address.
57     ///		byte3 = Fourth byte of the address.
58 	this(ubyte byte0,ubyte byte1,ubyte byte2,ubyte byte3)
59 	{
60 		sfIpAddress_fromBytes(byte0,byte1, byte2, byte3, m_address.ptr);
61 	}
62 	
63 	///Construct the address from a 32-bits integer.
64 	///
65 	///This constructor uses the internal representation of the address directly. It should be used only if you got that representation from IpAddress::ToInteger().
66 	///
67 	///Params:
68     ///		address = 4 bytes of the address packed into a 32-bits integer.
69 	this(uint address)
70 	{
71 		sfIpAddress_fromInteger(address, m_address.ptr);
72 	}
73 
74 	///Get an integer representation of the address.
75 	///
76 	///The returned number is the internal representation of the address, and should be used for optimization purposes only (like sending the address through a socket). The integer produced by this function can then be converted back to a sf::IpAddress with the proper constructor.
77 	///
78 	///Returns: 32-bits unsigned integer representation of the address.
79 	int toInteger() const
80 	{
81 		return sfIpAddress_toInteger(m_address.ptr);
82 	}
83 
84 	///Get a string representation of the address.
85 	///
86 	///The returned string is the decimal representation of the IP address (like "192.168.1.56"), even if it was constructed from a host name.
87 	///
88 	///Returns: String representation of the address
89 	string toString() const
90 	{
91 		import std.conv;
92 		//TODO: possibly cache the string? Maybe with a needsUpdatingMethod?
93 
94 		//Remove any null characters from the string representation
95 		int i = 0;
96 		while((m_address[i] != 0) )
97 		{
98 			++i;
99 		}
100 		//and present the string.
101 		return m_address[0..i].to!string();
102 	}
103 
104 	///Get the computer's local address.
105 	///
106 	///The local address is the address of the computer from the LAN point of view, i.e. something like 192.168.1.56. It is meaningful only for communications over the local network. Unlike getPublicAddress, this function is fast and may be used safely anywhere.
107 	///
108 	///Returns: Local IP address of the computer.
109 	static IpAddress getLocalAddress()
110 	{
111 		IpAddress temp;
112 		sfIpAddress_getLocalAddress(temp.m_address.ptr);
113 		return temp;
114 	}
115 	
116 	///Get the computer's public address.
117 	///
118 	///The public address is the address of the computer from the internet point of view, i.e. something like 89.54.1.169.
119 	///It is necessary for communications over the world wide web. The only way to get a public address is to ask it to a distant website; as a consequence, this function depends on both your network connection and the server, and may be very slow. You should use it as few as possible.
120 	///Because this function depends on the network connection and on a distant server, you may use a time limit if you don't want your program to be possibly stuck waiting in case there is a problem; this limit is deactivated by default.
121 	///
122 	///Params:
123     ///		timeout = Maximum time to wait.
124     ///
125 	///Returns: Public IP address of the computer.
126 	static IpAddress getPublicAddress(Duration timeout = Duration.zero())
127 	{
128 		IpAddress temp;
129 		sfIpAddress_getPublicAddress(temp.m_address.ptr, timeout.total!"usecs");
130 		return temp;
131 	}
132 	
133 	///Value representing an empty/invalid address. 
134 	static immutable(IpAddress) None;
135 	///The "localhost" address (for connecting a computer to itself locally) 
136 	static immutable(IpAddress) LocalHost;
137 	///The "broadcast" address (for sending UDP messages to everyone on a local network) 
138 	static immutable(IpAddress) Broadcast;
139 
140 	static this()
141 	{
142 		LocalHost = IpAddress(127,0,0,1);
143 		Broadcast = IpAddress(255,255,255,255);
144 	}
145 }
146 
147 unittest
148 {
149 	version(DSFML_Unittest_Network)
150 	{
151 		import std.stdio;
152 		
153 		writeln("Unittest for IpAdress");
154 
155 
156 		IpAddress address1;
157 
158 		assert(address1 == IpAddress.None);
159 
160 		assert(IpAddress.LocalHost == IpAddress("127.0.0.1"));
161 
162 		IpAddress googleIP = IpAddress("google.com");
163 
164 		writeln("Google's Ip address: ",googleIP.toString());
165 
166 		writeln("Your local Ip Address: ", IpAddress.getLocalAddress());
167 
168 		writeln("Your public Ip Address: ", IpAddress.getPublicAddress());
169 
170 		writeln();
171 	}
172 }
173 
174 private extern(C):
175 //Note: These functions rely on passing an existing array for the ipAddress.
176 
177 ///Create an address from a string
178 void sfIpAddress_fromString(const(char)* address, char* ipAddress);
179 
180 ///Create an address from 4 bytes
181 void sfIpAddress_fromBytes(ubyte byte0, ubyte byte1, ubyte byte2, ubyte byte3, char* ipAddress);
182 
183 ///Construct an address from a 32-bits integer
184 void sfIpAddress_fromInteger(uint address, char* ipAddress);
185 
186 ///Get an integer representation of the address
187 uint sfIpAddress_toInteger(const(char)* ipAddress);
188 
189 ///Get the computer's local address
190 void sfIpAddress_getLocalAddress(char* ipAddress);
191 
192 ///Get the computer's public address
193 void sfIpAddress_getPublicAddress(char* ipAddress, long timeout);