Spinning Topp Logo BlackTopp Studios
inc
platformsocket.h.cpp
1 // © Copyright 2010 - 2014 BlackTopp Studios Inc.
2 /* This file is part of The Mezzanine Engine.
3 
4  The Mezzanine Engine is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  The Mezzanine Engine is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with The Mezzanine Engine. If not, see <http://www.gnu.org/licenses/>.
16 */
17 /* The original authors have included a copy of the license specified above in the
18  'Docs' folder. See 'gpl.txt'
19 */
20 /* We welcome the use of the Mezzanine engine to anyone, including companies who wish to
21  Build professional software and charge for their product.
22 
23  However there are some practical restrictions, so if your project involves
24  any of the following you should contact us and we will try to work something
25  out:
26  - DRM or Copy Protection of any kind(except Copyrights)
27  - Software Patents You Do Not Wish to Freely License
28  - Any Kind of Linking to Non-GPL licensed Works
29  - Are Currently In Violation of Another Copyright Holder's GPL License
30  - If You want to change our code and not add a few hundred MB of stuff to
31  your distribution
32 
33  These and other limitations could cause serious legal problems if you ignore
34  them, so it is best to simply contact us or the Free Software Foundation, if
35  you have any questions.
36 
37  Joseph Toppi - toppij@gmail.com
38  John Blackwood - makoenergy02@gmail.com
39 */
40 
41 #ifndef _networkplatformsocket_h_cpp
42 #define _networkplatformsocket_h_cpp
43 
44 #include "Network/platformincludes.h.cpp"
45 
46 #include "Network/socketdescription.h"
47 #include "Network/systemaddress.h"
48 
49 namespace Mezzanine
50 {
51  namespace Network
52  {
53  #if defined(MEZZ_WINDOWS)
54  /// @internal
55  /// @brief Convenience type for the length of the address in Winsock 2.
56  typedef int AddrLen;
57  /// @internal
58  /// @brief Convenience type for the system handle to the socket in Winsock 2.
59  typedef SOCKET SocketHandleImplementation;
60  #elif defined(MEZZ_MACOSX) || defined(MEZZ_LINUX)
61  /// @internal
62  /// @brief Convenience type for the length of the address in Berkeley Sockets.
63  typedef socklen_t AddrLen;
64  /// @internal
65  /// @brief Convenience type for the system handle to the socket in Berkeley Sockets.
66  typedef int SocketHandleImplementation;
67  #ifndef INVALID_SOCKET
68  #define INVALID_SOCKET -1
69  #endif
70  #ifndef SOCKET_ERROR
71  #define SOCKET_ERROR -1
72  #endif
73  #endif
74 
75  ///////////////////////////////////////////////////////////////////////////////
76  /// @internal
77  /// @brief Used to allow type inference on @ref PlatformSocket constructors.
78  /// @details on Windows an @ref SocketHandleImplementation would be a SOCKET on Linux it
79  /// would be an int. This class allows easy differentiation between @ref PlatformSocket
80  /// where method calls would be identical otherwise.
81  ///////////////////////////////////////
83  {
84  protected:
85  /// @internal
86  /// @brief The actual handle store as a platform specific type thanks to typedefs.
87  SocketHandleImplementation handle;
88  public:
89  /// @brief Platform specific contructor
90  /// @details Because of the @ref SocketHandleImplementation typedef the
91  /// signature of this constructor changes to match lower level OS constructs.
92  /// Because this constructor accepts only on parameter the compiler will
93  /// automatically use this when passing a @ref SocketHandleImplementation to a
94  /// function or method that accepts a SocketHandle.
95  /// @param OSHandle The handle the OS would use to reference this.
96  SocketHandle(SocketHandleImplementation OSHandle = INVALID_SOCKET) :
97  handle(OSHandle)
98  { }
99 
100  #if defined(MEZZ_WINDOWS)
101  /// @brief Casting operator for Winsock.
102  /// @details When a function accepts a platform specific socket handle (SOCKET),
103  /// but an instance of this class was passed the compiler will find this method
104  /// and use it to correctly convert to a SOCKET.
105  /// @return A valid platform specific socket.
106  operator SOCKET() const
107  { return handle; }
108  #elif defined(MEZZ_MACOSX) || defined(MEZZ_LINUX)
109  /// @brief Casting operator for Berkeley Sockets.
110  /// @details When a function accepts a platform specific socket handle (int),
111  /// but an instance of this class was passed the compiler will find this method
112  /// and use it to correctly convert to an int.
113  /// @return A valid platform specific socket.
114  operator int() const
115  { return handle; }
116  #endif
117  };
118 
119  /// @brief An enum for the different configurable levels of socket options.
121  {
122  Sol_IPv4 = IPPROTO_IP,
123  Sol_IPv6 = IPPROTO_IPV6,
124  Sol_TCP = IPPROTO_TCP,
125  Sol_UDP = IPPROTO_UDP,
126  Sol_Socket = SOL_SOCKET
127  };
128 
129  /// @brief An enum for the configurable options that exist on the socket level.
131  {
132  // Datagram Options
133  SockOpts_Broadcast = SO_BROADCAST,
134  // Stream Options
135  SockOpts_KeepAlive = SO_KEEPALIVE,
136  // Regular Options
137  SockOpts_DebugInfo = SO_DEBUG,
138  SockOpts_DontRoute = SO_DONTROUTE,
139  SockOpts_ReuseAddress = SO_REUSEADDR,
140  SockOpts_RecieveBufSize = SO_RCVBUF,
141  SockOpts_SendBufSize = SO_SNDBUF
142  };
143 
144  /// @brief An enum for the configurable options that exist on the TCP protocol level.
146  {
147  TCPOpts_NoDelay = TCP_NODELAY
148  };
149 
150  /// @brief An enum for the configurable options that exist on the UDP protocol level.
152  {
153  // Heh
154  };
155 
156  /// @brief An enum for the configurable options that exist on the IPv4 protocol level.
158  {
159  // Datagram Options
160  // Not fragmenting between the two platforms is weird.
161  #if defined(MEZZ_WINDOWS)
162  IPv4Opts_Fragmentation = IP_DONTFRAGMENT,
163  #elif defined(MEZZ_MACOSX)
164  // No Support
165  #elif defined(MEZZ_LINUX)
166  IPv4Opts_Fragmentation = IP_MTU_DISCOVER,
167  #endif
168  // Multicasting Options
169  IPv4Opts_MulticastLoop = IP_MULTICAST_LOOP,
170  IPv4Opts_MulticastTTL = IP_MULTICAST_TTL,
171  // Regular Options
172  //IPv4Opts_ReceiveBroadcast = IP_RECEIVE_BROADCAST, // Windows Specific
173  IPv4Opts_OptionsHeader = IP_OPTIONS, // Not used
174  IPv4Opts_TimeToLive = IP_TTL
175  };
176 
177  /// @brief An enum for the easy mapping of the actual values needed to toggle IPv4 fragmentation.
179  {
180  #if defined(MEZZ_WINDOWS)
181  MFV_Frag_Enable = 0,
182  MFV_Frag_Disable = 1
183  #elif defined(MEZZ_MACOSX)
184  // No Support
185  #elif defined(MEZZ_LINUX)
186  MFV_Frag_Enable = IP_PMTUDISC_DONT,
187  MFV_Frag_Disable = IP_PMTUDISC_DO
188  #endif
189  };
190 
191  /// @brief An enum for the configurable options that exist on the IPv6 protocol level.
193  {
194  // Datagram Options
195  //IPv6Opts_HopLimit = IPV6_HOPLIMIT, // Not used
196  // Multicasting Options
197  IPv6Opts_MulticastHops = IPV6_MULTICAST_HOPS,
198  IPv6Opts_MulticastLoop = IPV6_MULTICAST_LOOP,
199  // Regular Options
200  IPv6Opts_UnicastHops = IPV6_UNICAST_HOPS,
201  IPv6Opts_V6Only = IPV6_V6ONLY
202  };
203 
204  /// @brief Converts from a Mezzanine address protocol type to it's internal counterpart.
205  /// @param Protocol The Mezzanine protocol type to be converted.
206  /// @return Returns the converted value from the Mezzanine type to the internal type.
207  short int MEZZ_LIB ConvertLayer3ProtocolType(const NetworkLayerProtocol Protocol);
208  /// @brief Converts from an internal address protocol type to it's Mezzanine counterpart.
209  /// @param Protocol The internal protocol type to be converted.
210  /// @return Returns the converted value from the internal type to the Mezzanine type.
212 
213  /// @brief Converts from a Mezzanine transport protocol type to it's internal counterpart.
214  /// @param Protocol The Mezzanine protocol type to be converted.
215  /// @return Returns the converted value from the Mezzanine type to the internal type.
217  /// @brief Converts from an internal transport protocol type to it's Mezzanine counterpart.
218  /// @param Protocol The internal protocol type to be converted.
219  /// @return Returns the converted value from the internal type to the Mezzanine type.
221 
222  /// @brief Converts from a Mezzanine transport protocol type to it's internal counterpart.
223  /// @param Protocol The Mezzanine protocol type to be converted.
224  /// @return Returns the converted value from the Mezzanine type to the internal type.
226  /// @brief Converts from an internal transport protocol type to it's Mezzanine counterpart.
227  /// @param SockType The internal socket type to be converted.
228  /// @return Returns the converted value from the internal type to the Mezzanine type.
230 
231  /// @brief Converts a Mezzanine address to a Berkeley sockets address.
232  /// @param MezzAddr The Mezzanine system address to be converted.
233  /// @return Returns an std::pair containing the converted socket and it's size to indicate it's type.
234  sockaddr_storage MEZZ_LIB ConvertToSocketStorage(const SystemAddress& MezzAddr);
235  /// @brief Converts a Mezzanine address to a Berkeley sockets address.
236  /// @param MezzAddr The Mezzanine socket descriptor to be converted.
237  /// @return Returns an std::pair containing the converted socket and it's size to indicate it's type.
238  sockaddr_storage MEZZ_LIB ConvertToSocketStorage(const SocketDescription& MezzAddr);
239  /// @brief Converts a Berkeley sockets address to a Mezzanine address.
240  /// @param BerkAddr The Berkeley Sockets sockaddr structure to be converted.
241  /// @return Returns a Mezzanine System address containing the converted socket descriptor.
242  SystemAddress MEZZ_LIB ConvertToSystemAddress(const sockaddr_storage& BerkAddr);
243  /// @brief Converts a Berkeley sockets address to a Mezzanine socket descriptor.
244  /// @param BerkAddr The Berkeley Sockets sockaddr structure to be converted.
245  /// @return Returns a Mezzanine socket description containing the converted socket descriptor.
246  SocketDescription MEZZ_LIB ConvertToSocketDescription(const sockaddr_storage& BerkAddr);
247 
248  ///////////////////////////////////////////////////////////////////////////////
249  /// @internal
250  /// @brief This is helper class for managing platform specific data of socket implementations.
251  ///////////////////////////////////////
253  {
254  protected:
255  /// @brief The handle to the internal socket implementation.
257  /// @brief The address type used for transmissions on this socket.
258  const int SockDomain;
259  /// @brief Whether this is a stream or datagram socket.
260  const int SockType;
261  /// @brief Whether or not this socket is currently in blocking mode.
263  public:
264  ///////////////////////////////////////////////////////////////////////////////
265  // Construction and Destruction
266 
267  /// @brief Non-binding constructor.
268  /// @param Domain The Address family of the socket to create.
269  /// @param Type Whether this is a stream or datagram socket.
270  /// @param Protocol The specific protocol to use with this socket.
271  PlatformSocket(int Domain, int Type, int Protocol);
272  /// @brief Binding constructor.
273  /// @param Domain The Address family of the socket to create.
274  /// @param Type Whether this is a stream or datagram socket.
275  /// @param Protocol The specific protocol to use with this socket.
276  /// @param Port The port to bind this socket to.
277  PlatformSocket(int Domain, int Type, int Protocol, const UInt16 Port);
278  /// @brief Accept constructor.
279  /// @param Handle The socket handle to wrap.
280  /// @param Domain The Address family of the socket to create.
281  /// @param Type Whether this is a stream or datagram socket.
282  PlatformSocket(SocketHandle Handle, int Domain, int Type);
283  /// @brief Class destructor.
284  ~PlatformSocket();
285 
286  ///////////////////////////////////////////////////////////////////////////////
287  // Core Operations
288 
289  /// @brief Binds this socket only to a port, accepting transmissions from any interface.
290  /// @param The port to bind this socket to.
291  /// @return Returns true if the Bind was successful, false if there was a failure.
292  Boole Bind(const UInt16 Port);
293  /// @brief Binds this socket to a local address so that it may receive transmissions addressed only to that interface.
294  /// @param Address The local address to bind this sockets transmissions to.
295  /// @return Returns true if the Bind was successful, false if there was a failure.
296  Boole Bind(const SystemAddress& Address);
297  /// @brief Binds this socket to a local address so that it may receive transmissions addressed only to that interface.
298  /// @param Address The local address to bind this sockets transmissions to.
299  /// @param Length The length of the address structure used to indicate it's type.
300  /// @return Returns true if the Bind was successful, false if there was a failure.
301  Boole Bind(sockaddr* Address, const AddrLen Length);
302 
303  /// @brief Disables some or all I/O on the socket.
304  /// @param How Which I/O should be disabled (send, receive, or both).
305  /// @return Returns true if the Shutdown was successful, false if there was a failure.
306  Boole Shutdown(const int How);
307 
308  ///////////////////////////////////////////////////////////////////////////////
309  // Core Operations - Stream
310 
311  /// @brief Connects this socket to a remote host connected to the network.
312  /// @param Address The remote address to connect to.
313  /// @return Returns true if the Connect was successful, false on a failure.
314  Boole Connect(const SystemAddress& Address);
315  /// @brief Connects this socket to a remote host connected to the network.
316  /// @param Address The remote address to connect to.
317  /// @param Length The length of the address structure used to indicate it's type.
318  /// @return Returns true if the Connect was successful, false on a failure.
319  Boole Connect(sockaddr* Address, const AddrLen Length);
320 
321  /// @brief Prepares this socket for incoming connections.
322  /// @param Backlog The amount of pending connections to keep track of in the queue before rejecting other connections.
323  /// @return Returns true if this put the socket into a listening state, false if there was a failure.
324  Boole Listen(const int Backlog = 5);
325 
326  /// @brief Accepts an incoming connection from a remote host.
327  /// @param Address The address structure to be populated with connection data to the Accepted remote host.
328  /// @return Returns a pointer to a new socket specifically configured to talk to the Accepted remote host, or NULL if there was a failure.
329  PlatformSocket* Accept(SystemAddress& Address);
330  /// @brief Accepts an incoming connection from a remote host.
331  /// @param Address A pointer to the address structure to be populated with connection data to the Accepted remote host.
332  /// @param Length The size of the address structure passed in. Will be set to a smaller value if a smaller struct is used to express the address.
333  /// @return Returns a pointer to a new socket specifically configured to talk to the Accepted remote host, or NULL if there was a failure.
334  PlatformSocket* Accept(sockaddr* Address, AddrLen* Length);
335 
336  /// @brief Sends data to the connected remote host.
337  /// @param Buffer The data to be sent to the remote host.
338  /// @param BufSize The size of the available buffer.
339  /// @param Flags A bitfield containing additional options for transmission.
340  /// @return Returns the number of bytes sent, or -1 if there was an error.
341  Integer Send(const void* Buffer, const Integer BufSize, const Integer Flags);
342 
343  /// @brief Receives data from the connected remote host.
344  /// @param Buffer The buffer to place the data received from the remote host.
345  /// @param BufSize The size of the available buffer.
346  /// @param Flags A bitfield containing additional options for transmission.
347  /// @return Returns the number of bytes received/written to the buffer, or -1 if there was an error.
348  Integer Receive(void* Buffer, const Integer BufSize, const Integer Flags);
349 
350  ///////////////////////////////////////////////////////////////////////////////
351  // Core Operations - Datagram
352 
353  /// @brief Sends data to a remote host.
354  /// @param Buffer The data to be sent to the remote host.
355  /// @param BufSize The size of the available buffer.
356  /// @param Flags A bitfield containing additional options for transmission.
357  /// @param Address The address of the remote host to send to.
358  /// @return Returns the number of bytes sent, or -1 if there was an error.
359  Integer SendTo(const void* Buffer, const Integer BufSize, const Integer Flags, const SystemAddress& Address);
360  /// @brief Sends data to a remote host.
361  /// @param Buffer The data to be sent to the remote host.
362  /// @param BufSize The size of the available buffer.
363  /// @param Flags A bitfield containing additional options for transmission.
364  /// @param Address The address of the remote host to send to.
365  /// @param Length The size of the address structure passed in.
366  /// @return Returns the number of bytes sent, or -1 if there was an error.
367  Integer SendTo(const void* Buffer, const Integer BufSize, const Integer Flags, const sockaddr* Address, const AddrLen Length);
368 
369  /// @brief Receives data from a remote host.
370  /// @param Buffer The buffer to place the data received from the remote host.
371  /// @param BufSize The size of the available buffer.
372  /// @param Flags A bitfield containing additional options for transmission.
373  /// @param Address The address of the remote host the data is being received from.
374  /// @return Returns the number of bytes received/written to the buffer, or -1 if there was an error.
375  Integer ReceiveFrom(void* Buffer, const Integer BufSize, const Integer Flags, SystemAddress& Address);
376  /// @brief Receives data from a remote host.
377  /// @param Buffer The buffer to place the data received from the remote host.
378  /// @param BufSize The size of the available buffer.
379  /// @param Flags A bitfield containing additional options for transmission.
380  /// @param Address The address of the remote host the data is being received from.
381  /// @param Length The size of the address structure that was populated.
382  /// @return Returns the number of bytes received/written to the buffer, or -1 if there was an error.
383  Integer ReceiveFrom(void* Buffer, const Integer BufSize, const Integer Flags, sockaddr* Address, AddrLen* Length);
384 
385  ///////////////////////////////////////////////////////////////////////////////
386  // Utility
387 
388  /// @brief Sets whether or not this socket will sleep on I/O calls.
389  /// @param Block Whether or not you want the calling thread to block until data is available on I/O calls.
390  /// @return Returns true if the operation was successful, false on a failure.
391  Boole SetBlocking(const Boole Block);
392  /// @brief Gets whether or not this socket will sleep on I/O calls.
393  /// @return Returns true if this socket will block the calling thread on I/O calls, false otherwise.
394  Boole GetBlocking() const;
395 
396  /// @brief Gets the number of bytes currently available to be read from the receive buffer.
397  /// @remarks It is entirely possible for additional data to arrive immediately after this method is called,
398  /// and before another method gets called. Thus, the number returned cannot be a guarentee in all cases.
399  /// @return Returns the amount of data that can be read from the receive buffer in bytes, or -1 if there was an error.
400  Integer GetNumBytesAvailable() const;
401  /// @brief Gets whether or not this socket is invalid, indicating an error during creation.
402  /// @return Returns true if this socket is invalid, false if this socket has a valid file descriptor.
403  Boole IsInvalid() const;
404 
405  /// @brief Set a low level socket parameter.
406  /// @param Level The type of option to be set.
407  /// @param OptID The ID of the option to be set.
408  /// @param Value A buffer containing the value to set for the specified option.
409  /// @param ValueLen The length of the Value buffer.
410  /// @return Returns true if the socket option was set successfully, false on a failure.
411  Boole SetSocketOption(const Integer Level, const Integer OptID, const char* Value, const AddrLen ValueLen);
412  /// @brief Get a low level socket parameter.
413  /// @param Level The type of option to retrieve.
414  /// @param OptID The ID of the option to retrieve.
415  /// @param Value A buffer to be populated with the requested option value.
416  /// @param ValueLen The length of the Value buffer.
417  /// @return Returns true if the socket option was set successfully, false on a failure.
418  Boole GetSocketOption(const Integer Level, const Integer OptID, char* Value, AddrLen* ValueLen) const;
419 
420  ///////////////////////////////////////////////////////////////////////////////
421  // Error Handling
422 
423  /// @brief Gets the last error that occured on a socket.
424  /// @return Returns the error code of the most recent socket error.
425  static int GetLastError();
426  /// @brief Throws an exception containing the message for a specific error code.
427  /// @param ErrorCode The error code to throw an exception for.
428  static void ThrowError(const int ErrorCode);
429  /// @brief Throws an exception containing the message from the last socket error.
430  static void ThrowLastError();
431  };//PlatformSocket
432  }//Network
433 }//Mezzanine
434 
435 #endif
int ConvertLayer4ProtocolType(const TransportLayerProtocol Protocol)
Converts from a Mezzanine transport protocol type to it's internal counterpart.
bool Boole
Generally acts a single bit, true or false.
Definition: datatypes.h:173
sockaddr_storage ConvertToSocketStorage(const SystemAddress &MezzAddr)
Converts a Mezzanine address to a Berkeley sockets address.
TCPLevelOptions
An enum for the configurable options that exist on the TCP protocol level.
short int ConvertLayer3ProtocolType(const NetworkLayerProtocol Protocol)
Converts from a Mezzanine address protocol type to it's internal counterpart.
IPv6LevelOptions
An enum for the configurable options that exist on the IPv6 protocol level.
NetworkLayerProtocol
This is an enum listing for recognized protocols on Layer 3 of the OSI model.
int ConvertToSocketType(const TransportLayerProtocol Protocol)
Converts from a Mezzanine transport protocol type to it's internal counterpart.
int Integer
A datatype used to represent any integer close to.
Definition: datatypes.h:154
SocketHandleImplementation handle
The actual handle store as a platform specific type thanks to typedefs.
SocketDescription ConvertToSocketDescription(const sockaddr_storage &BerkAddr)
Converts a Berkeley sockets address to a Mezzanine socket descriptor.
SocketHandle(SocketHandleImplementation OSHandle=INVALID_SOCKET)
Platform specific contructor.
const int SockType
Whether this is a stream or datagram socket.
uint16_t UInt16
An 16-bit unsigned integer.
Definition: datatypes.h:122
MsgFragValues
An enum for the easy mapping of the actual values needed to toggle IPv4 fragmentation.
SocketOptionLevel
An enum for the different configurable levels of socket options.
TransportLayerProtocol
This is an enum listing for recognized protocols on Layer 4 of the OSI model.
SocketLevelOptions
An enum for the configurable options that exist on the socket level.
This is helper class for managing platform specific data of socket implementations.
const int SockDomain
The address type used for transmissions on this socket.
SystemAddress ConvertToSystemAddress(const sockaddr_storage &BerkAddr)
Converts a Berkeley sockets address to a Mezzanine address.
#define MEZZ_LIB
Some platforms require special decorations to denote what is exported/imported in a share library...
IPv4LevelOptions
An enum for the configurable options that exist on the IPv4 protocol level.
The bulk of the engine components go in this namspace.
Definition: actor.cpp:56
SocketHandle InternalSocket
The handle to the internal socket implementation.
Boole Blocking
Whether or not this socket is currently in blocking mode.
Used to allow type inference on PlatformSocket constructors.
UDPLevelOptions
An enum for the configurable options that exist on the UDP protocol level.
A simple class that stores a complete set of information for establishing connections.
Definition: systemaddress.h:53