Spinning Topp Logo BlackTopp Studios
inc
socket.h
1 // © Copyright 2010 - 2016 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 _networksocket_h
42 #define _networksocket_h
43 
44 #include "Network/networkenumerations.h"
45 
46 #include "Network/packet.h"
47 #include "Network/systemaddress.h"
48 
49 namespace Mezzanine
50 {
51  namespace Network
52  {
53  ///////////////////////////////////////////////////////////////////////////////
54  // Socket Errors - Common
55 
56  /// @brief An unknown error occured. This is for when our errors error.
57  extern const Integer SE_Unknown;
58  /// @brief The OS modules needed for networking are unavailable.
59  extern const Integer SE_NetworkNotReady;
60  /// @brief The OS modules for networking haven't been started.
61  extern const Integer SE_Uninitialized;
62 
63  /// @brief The thread or process running a socket operation was terminated prematurely.
64  extern const Integer SE_Interrupted;
65  /// @brief Insufficient access permissions to perform specified socket operation.
66  extern const Integer SE_AccessDenied;
67  /// @brief The address data provided was faulty or invalid.
68  extern const Integer SE_InvalidAddr;
69  /// @brief An argument/parameter was provided to a socket operation.
70  extern const Integer SE_InvalidParam;
71  /// @brief Too many IO handles (Files and sockets share a pool) are open. This may be a global, process, or thread limit depending on platform.
72  extern const Integer SE_IOLimit;
73  /// @brief A resource is temporarily unavailable. This can be returned from operations on non-blocking sockets that cannot be completed immediately.
74  extern const Integer SE_WouldBlock;
75  /// @brief The socket is non-blocking and the operation cannot be completed immediately, but is now in progress.
76  extern const Integer SE_NowInProgress;
77  /// @brief The socket is non-blocking and an operation is already in progress.
78  extern const Integer SE_AlreadyInProgress;
79  /// @brief Specifying a destination address is required for the erroring operation. This often applies to a socket that isn't connected or has no peer address set in the socket call.
80  extern const Integer SE_DestAddrReq;
81  /// @brief The message to be sent through a socket is too large. The buffer provided to be sent on a datagram socket was larger than the internal buffer or another network limit.
82  extern const Integer SE_MessageSize;
83  /// @brief The system does not have the specified protocol installed or configured.
84  extern const Integer SE_ProtoNotSupported;
85  /// @brief Either the specified socket type does not exist or support for the specified socket type with the specified address family does not exist on the system.
86  extern const Integer SE_SocketNotSupported;
87  /// @brief The system does not have the specified protocol family installed or configured. This is mostly interchangable with SE_AFNotSupported.
88  extern const Integer SE_PFNotSupported;
89  /// @brief The system does not have the specified address family installed or configured. This is mostly interchangable with SE_PFNotSupported.
90  extern const Integer SE_AFNotSupported;
91  /// @brief The address specified for binding is already in use by another socket.
92  extern const Integer SE_AddrInUse;
93  /// @brief The address specified is not valid in the current context.
94  extern const Integer SE_AddrNotAvail;
95  /// @brief The operation encountered a dead network. This could be because of a failure of the network system, the interface, of the local network itself.
96  extern const Integer SE_NetworkDown;
97  /// @brief The operation could not find a valid route to the remote host specified.
98  extern const Integer SE_NetworkUnreachable;
99  /// @brief The connection was dropped. Usually occurs after keep-alive detected a failure while an operation was in progress.
100  extern const Integer SE_ConnectionDropped;
101  /// @brief The connection was aborted by software on the local host.
102  extern const Integer SE_ConnectionAborted;
103  /// @brief The connection was reset/closed by the remote host. This can also occur if keep-alive detected a failure.
104  extern const Integer SE_ConnectionReset;
105  /// @brief Either the OS lacked sufficient buffer space or the queue was full.
106  extern const Integer SE_NoBufferSpace;
107  /// @brief The socket is already connected. Additional connections are not supported.
108  extern const Integer SE_AlreadyConnected;
109  /// @brief The socket is not connected. Operations requiring a connection cannot be performed.
110  extern const Integer SE_NotConnected;
111  /// @brief The socket has already been shut down and operations cannot be performed on it.
112  extern const Integer SE_SocketShutdown;
113  /// @brief The connection timed out. The connect failed because the remote host didn't respond within the timeout peroid.
114  extern const Integer SE_ConnectionTimeout;
115  /// @brief The connection was refused. The remote host doesn't like you. Probably because you smell funny. Or slightly more likely no application was running on the specified port.
116  extern const Integer SE_ConnectionRefused;
117  /// @brief The operation failed because the remote host is down or doesn't exist.
118  extern const Integer SE_HostIsDown;
119  /// @brief No route to the specified host could be found.
120  extern const Integer SE_HostUnreachable;
121  /*/// @brief The number of processes interacting with the network subsystem has met or exceeded it's limit.
122  extern const Integer SE_ProcessLimit;// */
123 
124  ///////////////////////////////////////////////////////////////////////////////
125  // Socket Errors - Could occur, but you shouldn't see because of our API wrapper
126 
127  /// @brief Attempting to perform a socket operation on a handle that does not belong to a valid socket.
128  extern const Integer SE_NonSocket;
129  /// @brief The specified protocol is of the wrong type for the socket type specified. This error occurs on socket creation.
130  extern const Integer SE_InvalidProtoType;
131  /// @brief An invalid option level was specified for a call setting or getting a socket option.
132  extern const Integer SE_InvalidProtoOpt;
133  /// @brief The operation requested is not supported for the socket provided. For example "accept" being called on a datagram socket.
134  extern const Integer SE_InvalidOperation;
135 
136  class PlatformSocket;
137  ///////////////////////////////////////////////////////////////////////////////
138  /// @brief This is a basic socket interface for the transmission and retrieval of packets.
139  /// @note This class is intented to house methods for the configuration of all Socket and IPv4 (because IPv6 is a superset of IPv4 in the
140  /// case of socket options) options that can be set using a sockets API. For the most part this is accomplished, however some functionality
141  /// has been skipped. On windows in particular, there are a ton of additional options related to multi-casting which may be addressed in the
142  /// future. Some socket options that are available cross-platform were also not implemented included: SO_ERROR, SO_LINGER, SO_RCVLOWAT,
143  /// SO_RCVTIMEO, SO_SNDLOWAT, and SO_SNDTIMEO. @n @n
144  /// Some QoS functionality also didn't make the cut due to some strange circumstances. The SO_PRIORITY socket option seems to simply not exist
145  /// in Winsock. SO_PRIORITY overlaps somewhat in purpose with the IP_TOS socket option on the IP level. While that option does exist in
146  /// Winsock, the API documentation for Winsock says explicitly to not use it, favoring the Windows QoS API instead. This makes a crossplatform
147  /// layer over these options non-trivial. For both SO_PRIORITY and IP_TOS, what it does is set the priority flags in the IP header for
148  /// transmissions going out the socket, which could impact how and when packets are handled starting as early as the hosts local machine. This
149  /// is very low level and while it's possible some game devs could make use of it, it is outside of the scope for most devs. Thus for revision
150  /// 1 of the network subsystem this is skipped.
151  ///////////////////////////////////////
153  {
154  /*public:
155  /// @brief This enum is used to describe the current working status of the socket.
156  enum SocketStatus
157  {
158 
159  };// */
160  protected:
161  /// @internal
162  /// @brief A pointer to the internal system socket.
164  public:
165  /// @brief Class constructor.
166  Socket();
167  /// @brief Class destructor.
168  virtual ~Socket();
169 
170  ///////////////////////////////////////////////////////////////////////////////
171  // Utility
172 
173  /*/// @brief Gets the current status of this socket.
174  /// @return Returns a SocketStatus enum value representing the current working state of this socket.
175  virtual SocketStatus GetStatus() const = 0;// */
176 
177  /// @brief Gets the layer 3 protocol this socket is operating on.
178  /// @return Returns a NetworkLayerProtocol enum value describing the layer 3 protocol being used.
179  virtual NetworkLayerProtocol GetNetworkLayerProtocol() const = 0;
180  /// @brief Gets the layer 4 protocol this socket is operating on.
181  /// @return Returns a TransportLayerProtocol enum value describing the layer 4 protocol being used.
182  virtual TransportLayerProtocol GetTransportLayerProtocol() const = 0;
183 
184  /// @brief Sets whether or not this socket will sleep on I/O calls.
185  /// @param Block Whether or not you want the calling thread to block until data is available on I/O calls.
186  /// @return Returns true if the operation was successful, false on a failure.
187  Boole SetBlocking(const Boole Block);
188  /// @brief Gets whether or not this socket will sleep on I/O calls.
189  /// @return Returns true if this socket will block the calling thread on I/O calls, false otherwise.
190  Boole GetBlocking() const;
191 
192  /// @brief Gets the number of bytes currently available to be read from the receive buffer.
193  /// @remarks It is entirely possible for additional data to arrive immediately after this method is called,
194  /// and before another method gets called. Thus, the number returned cannot be a guarentee in all cases.
195  /// @return Returns the amount of data that can be read from the receive buffer in bytes, or -1 if there was an error.
196  Integer GetNumBytesAvailable() const;
197  /// @brief Gets whether or not this socket is invalid, indicating an error during creation.
198  /// @return Returns true if this socket is invalid, false if this socket has a valid file descriptor.
199  Boole IsInvalid() const;
200 
201  ///////////////////////////////////////////////////////////////////////////////
202  // Core Operations
203 
204  /// @brief Binds this socket only to a port, accepting transmissions from any interface.
205  /// @param The port to bind this socket to.
206  /// @return Returns true if the Bind was successful, false if there was a failure.
207  Boole Bind(const UInt16 Port);
208  /// @brief Binds this socket to a local address so that it may receive transmissions addressed only to that interface.
209  /// @param Address The local address to bind this sockets transmissions to.
210  /// @return Returns true if the Bind was successful, false if there was a failure.
211  Boole Bind(const SystemAddress& Address);
212 
213  /// @brief Connects this socket to a remote host connected to the network.
214  /// @remarks This method will block transmissions from any address other than the one the socket is connected to.
215  /// @param Address The remote address to connect to.
216  /// @return Returns true if the Connect was successful, false on a failure.
217  Boole Connect(const SystemAddress& Address);
218 
219  /// @brief Sends raw data out the socket to it's configured peer.
220  /// @remarks This should only be used on connected sockets. Calling this method on unconnected sockets will error.
221  /// @param Buffer A raw buffer to be sent.
222  /// @param BufSize The size of the raw buffer to send.
223  /// @return Returns the number of bytes sent, or -1 if there was an error.
224  Integer Send(const void* Buffer, const UInt32 BufSize) const;
225 
226  /// @brief Reads raw data recieved on this socket from it's configured peer.
227  /// @remarks This should only be used on connected sockets. Calling this method on unconnected sockets will error.
228  /// @param Buffer A raw buffer to be written to.
229  /// @param BufSize The size of the raw buffer to write to.
230  /// @return Returns the number of bytes received/written to the buffer, or -1 if there was an error.
231  Integer Receive(void* Buffer, const UInt32 BufSize) const;
232  /// @brief Reads raw data recieved on this socket from it's configured peer, but doesn't remove that data from the receive buffer.
233  /// @remarks This should only be used on connected sockets. Calling this method on unconnected sockets will error.
234  /// An additional call to Receive will return the same data returned by this call, as the data wasn't removed from the queue with this method.
235  /// @param Buffer A raw buffer to be written to.
236  /// @param BufSize The size of the raw buffer to write to.
237  /// @return Returns the number of bytes received/written to the buffer, or -1 if there was an error.
238  Integer ReceivePeek(void* Buffer, const UInt32 BufSize) const;
239 
240  /// @brief Disables some or all I/O on the socket.
241  /// @param How Which I/O should be disabled (send, receive, or both).
242  /// @return Returns true if the Shutdown was successful, false if there was a failure.
243  Boole Shutdown(const Network::SocketShutdown How);
244 
245  ///////////////////////////////////////////////////////////////////////////////
246  // Configuration
247 
248  /// @brief Sets the number of hops permitted when sending to a non-multicast address before the message is destroyed.
249  /// @remarks A "Hop" is a single stop at a router in the path to the destination host. Limiting the number of hops taken prevents
250  /// situations where a host cannot be reached, but it's state also can't be assessed in advance, thus the message just keeps moving
251  /// around the network without possibly arriving, creating congestion.
252  /// @param Hops The number of hops a message sent from this socket is allowed to make. Cannot be greater than 255.
253  virtual void SetNumUnicastHops(const Integer Hops) = 0;
254  /// @brief Gets the number of hops permitted when sending to a non-multicast address before the message is destroyed.
255  /// @return Returns the number of times a unicast message from this socket sent to a non-multicast address is allowed to be routed before being destroyed.
256  virtual Integer GetNumUnicastHops() const = 0;
257 
258  /// @brief Sets whether or not local addresses can be re-used for socket binding.
259  /// @param Reuse Whether or not the port/IPaddress this socket is bound to can be shared.
260  void SetReuseAddress(const Boole Reuse);
261  /// @brief Gets whether or not local addresses can be re-used for socket binding.
262  /// @return Returns true if this socket can share its bound local address with other sockets, false otherwise.
263  Boole GetReuseAddress() const;
264  /// @brief Sets whether or not packets should be sent directly to other nodes on the network if possible.
265  /// @param Route Whether or not more advanced routing through internetworking devices should be skipped if possible.
266  void SetDontRoute(const Boole Route);
267  /// @brief Gets whether or not packets should be sent directly to other nodes on the network if possible.
268  /// @return Returns true if packets should be sent to the host directly if possible, false otherwise.
269  Boole GetDontRoute() const;
270  /// @brief Sets whether or not additional debugging information should be collected during socket operations.
271  /// @param Debug Whether or not additional debug facilities in internal sockets should be enabled.
272  void SetDebugInformation(const Boole Debug);
273  /// @brief Gets whether or not additional debugging information should be collected during socket operations.
274  /// @return Returns true if debug information on errors should be logged, false otherwise.
275  Boole GetDebugInformation() const;
276  /// @brief Sets the size of the buffer for sending packets.
277  /// @remarks This buffer is not for singular packets, but for all the packets intended to be sent out to the network. Datagram sockets are fire
278  /// and forget so unless you are trying to send out a ton of packets in a single frame you are unlikely to fill the buffer before the kernel
279  /// unloads it to the network. In stream sockets however it is possible for a network failure to occur and cause some parts to need to be resent.
280  /// In those cases adding more packets can cause the send buffer to become more populated and even fill up in extreme cases.
281  /// @param Size The size to set the send buffer as in bytes.
282  void SetSendBufferSize(const Integer Size);
283  /// @brief Gets the size of the buffer for sending packets.
284  /// @return Returns an Integer representing the size of the send buffer in bytes.
285  Integer GetSendBufferSize() const;
286  /// @brief Sets the size of the buffer for receiving packets.
287  /// @remarks This buffer is not for singular packets but, for the entire backlog of packets you receive. In stream sockets the sending host will
288  /// be notified to slow down to preserve data. In datagram sockets any packets received after the buffer is filled will have their contents
289  /// discarded.
290  /// @param Size The size to set the receive buffer as in bytes.
291  void SetReceiveBufferSize(const Integer Size);
292  /// @brief Gets the size of the buffer for receiving packets.
293  /// @return Returns an Integer representing the size of the receive buffer in bytes.
294  Integer GetReceiveBufferSize() const;
295 
296  ///////////////////////////////////////////////////////////////////////////////
297  // Error Handling
298 
299  /// @brief Gets the last error that occured on a socket.
300  /// @return Returns the error code of the most recent socket error.
301  static Integer GetLastError();
302  /// @brief Throws an exception containing the message for a specific error code.
303  /// @param ErrorCode The error code to throw an exception for.
304  static void ThrowError(const Integer ErrorCode);
305  /// @brief Throws an exception containing the message from the last socket error.
306  static void ThrowLastError();
307 
308  ///////////////////////////////////////////////////////////////////////////////
309  // Internal
310 
311  /// @brief Starts the socket subsystem.
312  /// @remarks This exists primarily because Winsock is lame. Always returns success on non-winsock platforms.
313  /// @return Returns zero if startup was successful, or an error code if something went wrong.
314  static Integer Initialize();
315  /// @brief Stops the socket subsystem.
316  /// @remarks This exists primarily because Winsock is lame. Always returns success on non-winsock platforms.
317  /// @return Returns zero if shutdown was successful, or an error code if something went wrong.
318  static Integer Deinitialize();
319 
320  /// @brief Gets a pointer to the internal socket.
321  /// @return Returns a pointer to the internal platform-specific socket.
322  PlatformSocket* _GetPlatformSocket() const;
323  };//Socket
324  }//Network
325 }//Mezzanine
326 
327 #endif
const Integer SE_InvalidProtoType
The specified protocol is of the wrong type for the socket type specified. This error occurs on socke...
const Integer SE_NotConnected
The socket is not connected. Operations requiring a connection cannot be performed.
const Integer SE_AFNotSupported
The system does not have the specified address family installed or configured. This is mostly interch...
PlatformSocket * InternalSocket
A pointer to the internal system socket.
Definition: socket.h:163
const Integer SE_Interrupted
The thread or process running a socket operation was terminated prematurely.
const Integer SE_DestAddrReq
Specifying a destination address is required for the erroring operation. This often applies to a sock...
This is a basic socket interface for the transmission and retrieval of packets.
Definition: socket.h:152
bool Boole
Generally acts a single bit, true or false.
Definition: datatypes.h:173
const Integer SE_AlreadyConnected
The socket is already connected. Additional connections are not supported.
const Integer SE_Unknown
An unknown error occured. This is for when our errors error.
Definition: socket.cpp:60
NetworkLayerProtocol
This is an enum listing for recognized protocols on Layer 3 of the OSI model.
const Integer SE_ConnectionDropped
The connection was dropped. Usually occurs after keep-alive detected a failure while an operation was...
int Integer
A datatype used to represent any integer close to.
Definition: datatypes.h:154
const Integer SE_ConnectionTimeout
The connection timed out. The connect failed because the remote host didn't respond within the timeou...
const Integer SE_Uninitialized
The OS modules for networking haven't been started.
const Integer SE_InvalidParam
An argument/parameter was provided to a socket operation.
const Integer SE_NetworkDown
The operation encountered a dead network. This could be because of a failure of the network system...
const Integer SE_HostUnreachable
No route to the specified host could be found.
const Integer SE_ProtoNotSupported
The system does not have the specified protocol installed or configured.
const Integer SE_MessageSize
The message to be sent through a socket is too large. The buffer provided to be sent on a datagram so...
uint16_t UInt16
An 16-bit unsigned integer.
Definition: datatypes.h:122
const Integer SE_NowInProgress
The socket is non-blocking and the operation cannot be completed immediately, but is now in progress...
const Integer SE_NoBufferSpace
Either the OS lacked sufficient buffer space or the queue was full.
TransportLayerProtocol
This is an enum listing for recognized protocols on Layer 4 of the OSI model.
const Integer SE_NetworkNotReady
The OS modules needed for networking are unavailable.
uint32_t UInt32
An 32-bit unsigned integer.
Definition: datatypes.h:126
const Integer SE_WouldBlock
A resource is temporarily unavailable. This can be returned from operations on non-blocking sockets t...
const Integer SE_InvalidOperation
The operation requested is not supported for the socket provided. For example "accept" being called o...
This is helper class for managing platform specific data of socket implementations.
const Integer SE_SocketNotSupported
Either the specified socket type does not exist or support for the specified socket type with the spe...
const Integer SE_InvalidProtoOpt
An invalid option level was specified for a call setting or getting a socket option.
const Integer SE_ConnectionRefused
The connection was refused. The remote host doesn't like you. Probably because you smell funny...
const Integer SE_NonSocket
Attempting to perform a socket operation on a handle that does not belong to a valid socket...
const Integer SE_AddrNotAvail
The address specified is not valid in the current context.
const Integer SE_NetworkUnreachable
The operation could not find a valid route to the remote host specified.
const Integer SE_InvalidAddr
The address data provided was faulty or invalid.
const Integer SE_IOLimit
Too many IO handles (Files and sockets share a pool) are open. This may be a global, process, or thread limit depending on platform.
const Integer SE_AddrInUse
The address specified for binding is already in use by another socket.
const Integer SE_AlreadyInProgress
The socket is non-blocking and an operation is already in progress.
#define MEZZ_LIB
Some platforms require special decorations to denote what is exported/imported in a share library...
const Integer SE_AccessDenied
Insufficient access permissions to perform specified socket operation.
const Integer SE_HostIsDown
The operation failed because the remote host is down or doesn't exist.
The bulk of the engine components go in this namspace.
Definition: actor.cpp:56
const Integer SE_ConnectionReset
The connection was reset/closed by the remote host. This can also occur if keep-alive detected a fail...
SocketShutdown
This is a small enum used for socket shutdown parameters.
const Integer SE_SocketShutdown
The socket has already been shut down and operations cannot be performed on it.
const Integer SE_ConnectionAborted
The connection was aborted by software on the local host.
A simple class that stores a complete set of information for establishing connections.
Definition: systemaddress.h:53
const Integer SE_PFNotSupported
The system does not have the specified protocol family installed or configured. This is mostly interc...