Spinning Topp Logo BlackTopp Studios
inc
socket.cpp
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_cpp
42 #define _networksocket_cpp
43 
44 #include "Network/platformsocket.h.cpp"
45 
46 #include "Network/socket.h"
47 
48 
49  #include <errno.h>
50 
51 namespace Mezzanine
52 {
53  namespace Network
54  {
55  ///////////////////////////////////////////////////////////////////////////////
56  // Socket Errors
57 
58  // SE_Unknown is the only error intended to have a value of -1. However some errors exist on one platform but not others.
59  // For those cases where there is not cross-platform equivalent a value of -1 is used.
60  const Integer SE_Unknown = -1;
61  #if defined(MEZZ_WINDOWS)
62  const Integer SE_Uninitialized = WSANOTINITIALISED;
63  const Integer SE_NetworkNotReady = WSASYSNOTREADY;
64  const Integer SE_Interrupted = WSAEINTR;
65  const Integer SE_AccessDenied = WSAEACCES;
66  const Integer SE_InvalidAddr = WSAEFAULT;
67  const Integer SE_InvalidParam = WSAEINVAL;
68  const Integer SE_IOLimit = WSAEMFILE;
69  const Integer SE_WouldBlock = WSAEWOULDBLOCK;
70  const Integer SE_NowInProgress = WSAEINPROGRESS;
71  const Integer SE_AlreadyInProgress = WSAEALREADY;
72  const Integer SE_DestAddrReq = WSAEDESTADDRREQ;
73  const Integer SE_MessageSize = WSAEMSGSIZE;
74  const Integer SE_ProtoNotSupported = WSAEPROTONOSUPPORT;
75  const Integer SE_SocketNotSupported = WSAESOCKTNOSUPPORT;
76  const Integer SE_PFNotSupported = WSAEPFNOSUPPORT;
77  const Integer SE_AFNotSupported = WSAEAFNOSUPPORT;
78  const Integer SE_AddrInUse = WSAEADDRINUSE;
79  const Integer SE_AddrNotAvail = WSAEADDRNOTAVAIL;
80  const Integer SE_NetworkDown = WSAENETDOWN;
81  const Integer SE_NetworkUnreachable = WSAENETUNREACH;
82  const Integer SE_ConnectionDropped = WSAENETRESET;
83  const Integer SE_ConnectionAborted = WSAECONNABORTED;
84  const Integer SE_ConnectionReset = WSAECONNRESET;
85  const Integer SE_NoBufferSpace = WSAENOBUFS;
86  const Integer SE_AlreadyConnected = WSAEISCONN;
87  const Integer SE_NotConnected = WSAENOTCONN;
88  const Integer SE_SocketShutdown = WSAESHUTDOWN;
89  const Integer SE_ConnectionTimeout = WSAETIMEDOUT;
90  const Integer SE_ConnectionRefused = WSAECONNREFUSED;
91  const Integer SE_HostIsDown = WSAEHOSTDOWN;
92  const Integer SE_HostUnreachable = WSAEHOSTUNREACH;
93  //const Integer SE_ProcessLimit = WSAEPROCLIM;
94  #elif defined(MEZZ_MACOSX) || defined(MEZZ_LINUX)
95  const Integer SE_Uninitialized = -1;
96  const Integer SE_NetworkNotReady = -1;
97  const Integer SE_Interrupted = EINTR;
98  const Integer SE_AccessDenied = EACCES;
99  const Integer SE_InvalidAddr = EFAULT;
100  const Integer SE_InvalidParam = EINVAL;
101  const Integer SE_IOLimit = EMFILE;
102  const Integer SE_WouldBlock = EWOULDBLOCK;
103  const Integer SE_NowInProgress = EINPROGRESS;
104  const Integer SE_AlreadyInProgress = EALREADY;
105  const Integer SE_DestAddrReq = EDESTADDRREQ;
106  const Integer SE_MessageSize = EMSGSIZE;
107  const Integer SE_ProtoNotSupported = EPROTONOSUPPORT;
108  const Integer SE_SocketNotSupported = ESOCKTNOSUPPORT;
109  const Integer SE_PFNotSupported = EPFNOSUPPORT;
110  const Integer SE_AFNotSupported = EAFNOSUPPORT;
111  const Integer SE_AddrInUse = EADDRINUSE;
112  const Integer SE_AddrNotAvail = EADDRNOTAVAIL;
113  const Integer SE_NetworkDown = ENETDOWN;
114  const Integer SE_NetworkUnreachable = ENETUNREACH;
115  const Integer SE_ConnectionDropped = ENETRESET;
116  const Integer SE_ConnectionAborted = ECONNABORTED;
117  const Integer SE_ConnectionReset = ECONNRESET;
118  const Integer SE_NoBufferSpace = ENOBUFS;
119  const Integer SE_AlreadyConnected = EISCONN;
120  const Integer SE_NotConnected = ENOTCONN;
121  const Integer SE_SocketShutdown = ESHUTDOWN;
122  const Integer SE_ConnectionTimeout = ETIMEDOUT;
123  const Integer SE_ConnectionRefused = ECONNREFUSED;
124  const Integer SE_HostIsDown = EHOSTDOWN;
125  const Integer SE_HostUnreachable = EHOSTUNREACH;
126  //const Integer SE_ProcessLimit = EPROCLIM;
127  #endif
128 
129  ///////////////////////////////////////////////////////////////////////////////
130  // Socket Errors - Could occur, but you shouldn't see because of our API wrapper
131 
132  #if defined(MEZZ_WINDOWS)
133  const Integer SE_NonSocket = WSAENOTSOCK;
134  const Integer SE_InvalidProtoType = WSAEPROTOTYPE;
135  const Integer SE_InvalidProtoOpt = WSAENOPROTOOPT;
136  const Integer SE_InvalidOperation = WSAEOPNOTSUPP;
137  #elif defined(MEZZ_MACOSX) || defined(MEZZ_LINUX)
138  const Integer SE_NonSocket = ENOTSOCK;
139  const Integer SE_InvalidProtoType = EPROTOTYPE;
140  const Integer SE_InvalidProtoOpt = ENOPROTOOPT;
141  const Integer SE_InvalidOperation = EOPNOTSUPP;
142  #endif
143 
144  ///////////////////////////////////////////////////////////////////////////////
145  // Socket Methods
146 
148  InternalSocket(NULL)
149  { }
150 
152  { }
153 
154  ///////////////////////////////////////////////////////////////////////////////
155  // Utility
156 
158  { return this->InternalSocket->SetBlocking(Block); }
159 
161  { return this->InternalSocket->GetBlocking(); }
162 
164  { return this->InternalSocket->GetNumBytesAvailable(); }
165 
167  { return this->InternalSocket->IsInvalid(); }
168 
169  ///////////////////////////////////////////////////////////////////////////////
170  // Core Operations
171 
173  { return this->InternalSocket->Bind(Port); }
174 
176  { return this->InternalSocket->Bind(Address); }
177 
179  { return this->InternalSocket->Connect(Address); }
180 
181  Integer Socket::Send(const void* Buffer, const UInt32 BufSize) const
182  { return this->InternalSocket->Send(Buffer,BufSize,0); }
183 
184  Integer Socket::Receive(void* Buffer, const UInt32 BufSize) const
185  { return this->InternalSocket->Receive(Buffer,BufSize,0); }
186 
187  Integer Socket::ReceivePeek(void* Buffer, const UInt32 BufSize) const
188  { return this->InternalSocket->Receive(Buffer,BufSize,MSG_PEEK); }
189 
191  { return this->InternalSocket->Shutdown(How); }
192 
193  ///////////////////////////////////////////////////////////////////////////////
194  // Configuration
195 
196  void Socket::SetReuseAddress(const Boole Reuse)
197  {
198  int Value = ( Reuse ? 1 : 0 );
199  this->InternalSocket->SetSocketOption(Network::Sol_Socket,Network::SockOpts_ReuseAddress,(char*)&Value,sizeof(Value));
200  }
201 
203  {
204  int Value = 0;
205  AddrLen Size;
206  this->InternalSocket->GetSocketOption(Network::Sol_Socket,Network::SockOpts_ReuseAddress,(char*)&Value,&Size);
207  return ( Value != 0 );
208  }
209 
210  void Socket::SetDontRoute(const Boole Route)
211  {
212  int Value = ( Route ? 1 : 0 );
213  this->InternalSocket->SetSocketOption(Network::Sol_Socket,Network::SockOpts_DontRoute,(char*)&Value,sizeof(Value));
214  }
215 
217  {
218  int Value = 0;
219  AddrLen Size;
220  this->InternalSocket->GetSocketOption(Network::Sol_Socket,Network::SockOpts_DontRoute,(char*)&Value,&Size);
221  return ( Value != 0 );
222  }
223 
225  {
226  int Value = ( Debug ? 1 : 0 );
227  this->InternalSocket->SetSocketOption(Network::Sol_Socket,Network::SockOpts_DebugInfo,(char*)&Value,sizeof(Value));
228  }
229 
231  {
232  int Value = 0;
233  AddrLen Size;
234  this->InternalSocket->GetSocketOption(Network::Sol_Socket,Network::SockOpts_DebugInfo,(char*)&Value,&Size);
235  return ( Value != 0 );
236  }
237 
239  {
240  #if defined(MEZZ_WINDOWS)
241  DWORD Value = ( Size < 0 ? 0 : Size );
242  this->InternalSocket->SetSocketOption(Network::Sol_Socket,Network::SockOpts_SendBufSize,(char*)&Value,sizeof(Value));
243  #elif defined(MEZZ_MACOSX) || defined(MEZZ_LINUX)
244  this->InternalSocket->SetSocketOption(Network::Sol_Socket,Network::SockOpts_SendBufSize,(char*)&Size,sizeof(Size));
245  #endif
246  }
247 
249  {
250  #if defined(MEZZ_WINDOWS)
251  DWORD Value = 0;
252  #elif defined(MEZZ_MACOSX) || defined(MEZZ_LINUX)
253  int Value = 0;
254  #endif
255  AddrLen Size;
256  this->InternalSocket->GetSocketOption(Network::Sol_Socket,Network::SockOpts_SendBufSize,(char*)&Value,&Size);
257  return static_cast<Integer>(Value);
258  }
259 
261  {
262  #if defined(MEZZ_WINDOWS)
263  DWORD Value = ( Size < 0 ? 0 : Size );
264  this->InternalSocket->SetSocketOption(Network::Sol_Socket,Network::SockOpts_RecieveBufSize,(char*)&Value,sizeof(Value));
265  #elif defined(MEZZ_MACOSX) || defined(MEZZ_LINUX)
266  this->InternalSocket->SetSocketOption(Network::Sol_Socket,Network::SockOpts_RecieveBufSize,(char*)&Size,sizeof(Size));
267  #endif
268  }
269 
271  {
272  #if defined(MEZZ_WINDOWS)
273  DWORD Value = 0;
274  #elif defined(MEZZ_MACOSX) || defined(MEZZ_LINUX)
275  int Value = 0;
276  #endif
277  AddrLen Size;
278  this->InternalSocket->GetSocketOption(Network::Sol_Socket,Network::SockOpts_RecieveBufSize,(char*)&Value,&Size);
279  return static_cast<Integer>(Value);
280  }
281 
282  ///////////////////////////////////////////////////////////////////////////////
283  // Error Handling
284 
286  { return PlatformSocket::GetLastError(); }
287 
288  void Socket::ThrowError(const Integer ErrorCode)
289  { PlatformSocket::ThrowError(ErrorCode); }
290 
293 
294  ///////////////////////////////////////////////////////////////////////////////
295  // Internal
296 
298  {
299  #if defined(MEZZ_WINDOWS)
300  WORD Version = MAKEWORD(2,2);
301  WSADATA StartupData;
302  return ::WSAStartup(Version,&StartupData);
303  #elif defined(MEZZ_MACOSX) || defined(MEZZ_LINUX)
304  return 0;
305  #endif
306  }
307 
309  {
310  #if defined(MEZZ_WINDOWS)
311  return ::WSACleanup();
312  #elif defined(MEZZ_MACOSX) || defined(MEZZ_LINUX)
313  return 0;
314  #endif
315  }
316 
318  { return this->InternalSocket; }
319  }//Network
320 }//Mezzanine
321 
322 #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...
Boole Shutdown(const int How)
Disables some or all I/O on the socket.
Boole IsInvalid() const
Gets whether or not this socket is invalid, indicating an error during creation.
Definition: socket.cpp:166
static void ThrowLastError()
Throws an exception containing the message from the last socket error.
bool Boole
Generally acts a single bit, true or false.
Definition: datatypes.h:173
Integer Receive(void *Buffer, const UInt32 BufSize) const
Reads raw data recieved on this socket from it's configured peer.
Definition: socket.cpp:184
Boole GetSocketOption(const Integer Level, const Integer OptID, char *Value, AddrLen *ValueLen) const
Get a low level socket parameter.
Boole IsInvalid() const
Gets whether or not this socket is invalid, indicating an error during creation.
const Integer SE_AlreadyConnected
The socket is already connected. Additional connections are not supported.
static Integer GetLastError()
Gets the last error that occured on a socket.
Definition: socket.cpp:285
Integer Send(const void *Buffer, const Integer BufSize, const Integer Flags)
Sends data to the connected remote host.
const Integer SE_Unknown
An unknown error occured. This is for when our errors error.
Definition: socket.cpp:60
virtual ~Socket()
Class destructor.
Definition: socket.cpp:151
static void ThrowError(const int ErrorCode)
Throws an exception containing the message for a specific error code.
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
Integer GetSendBufferSize() const
Gets the size of the buffer for sending packets.
Definition: socket.cpp:248
Boole Connect(const SystemAddress &Address)
Connects this socket to a remote host connected to the network.
static Integer Deinitialize()
Stops the socket subsystem.
Definition: socket.cpp:308
Boole GetDebugInformation() const
Gets whether or not additional debugging information should be collected during socket operations...
Definition: socket.cpp:230
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.
void SetReuseAddress(const Boole Reuse)
Sets whether or not local addresses can be re-used for socket binding.
Definition: socket.cpp:196
Boole GetReuseAddress() const
Gets whether or not local addresses can be re-used for socket binding.
Definition: socket.cpp:202
const Integer SE_NetworkDown
The operation encountered a dead network. This could be because of a failure of the network system...
Integer GetNumBytesAvailable() const
Gets the number of bytes currently available to be read from the receive buffer.
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.
static Integer Initialize()
Starts the socket subsystem.
Definition: socket.cpp:297
Socket()
Class constructor.
Definition: socket.cpp:147
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.
Integer GetNumBytesAvailable() const
Gets the number of bytes currently available to be read from the receive buffer.
Definition: socket.cpp:163
Boole Bind(const UInt16 Port)
Binds this socket only to a port, accepting transmissions from any interface.
static void ThrowLastError()
Throws an exception containing the message from the last socket error.
Definition: socket.cpp:291
const Integer SE_NetworkNotReady
The OS modules needed for networking are unavailable.
Boole Shutdown(const Network::SocketShutdown How)
Disables some or all I/O on the socket.
Definition: socket.cpp:190
uint32_t UInt32
An 32-bit unsigned integer.
Definition: datatypes.h:126
Integer Receive(void *Buffer, const Integer BufSize, const Integer Flags)
Receives data from the connected remote host.
Integer Send(const void *Buffer, const UInt32 BufSize) const
Sends raw data out the socket to it's configured peer.
Definition: socket.cpp:181
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.
void SetReceiveBufferSize(const Integer Size)
Sets the size of the buffer for receiving packets.
Definition: socket.cpp:260
const Integer SE_ConnectionRefused
The connection was refused. The remote host doesn't like you. Probably because you smell funny...
Integer ReceivePeek(void *Buffer, const UInt32 BufSize) const
Reads raw data recieved on this socket from it's configured peer, but doesn't remove that data from t...
Definition: socket.cpp:187
Boole SetBlocking(const Boole Block)
Sets whether or not this socket will sleep on I/O calls.
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.
void SetDontRoute(const Boole Route)
Sets whether or not packets should be sent directly to other nodes on the network if possible...
Definition: socket.cpp:210
const Integer SE_InvalidAddr
The address data provided was faulty or invalid.
static int GetLastError()
Gets the last error that occured on a socket.
Boole GetBlocking() const
Gets whether or not this socket will sleep on I/O calls.
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.
Boole SetBlocking(const Boole Block)
Sets whether or not this socket will sleep on I/O calls.
Definition: socket.cpp:157
Boole GetDontRoute() const
Gets whether or not packets should be sent directly to other nodes on the network if possible...
Definition: socket.cpp:216
const Integer SE_AlreadyInProgress
The socket is non-blocking and an operation is already in progress.
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...
Boole GetBlocking() const
Gets whether or not this socket will sleep on I/O calls.
Definition: socket.cpp:160
static void ThrowError(const Integer ErrorCode)
Throws an exception containing the message for a specific error code.
Definition: socket.cpp:288
void SetDebugInformation(const Boole Debug)
Sets whether or not additional debugging information should be collected during socket operations...
Definition: socket.cpp:224
void SetSendBufferSize(const Integer Size)
Sets the size of the buffer for sending packets.
Definition: socket.cpp:238
SocketShutdown
This is a small enum used for socket shutdown parameters.
Integer GetReceiveBufferSize() const
Gets the size of the buffer for receiving packets.
Definition: socket.cpp:270
const Integer SE_SocketShutdown
The socket has already been shut down and operations cannot be performed on it.
PlatformSocket * _GetPlatformSocket() const
Gets a pointer to the internal socket.
Definition: socket.cpp:317
const Integer SE_ConnectionAborted
The connection was aborted by software on the local host.
Boole Bind(const UInt16 Port)
Binds this socket only to a port, accepting transmissions from any interface.
Definition: socket.cpp:172
A simple class that stores a complete set of information for establishing connections.
Definition: systemaddress.h:53
Boole SetSocketOption(const Integer Level, const Integer OptID, const char *Value, const AddrLen ValueLen)
Set a low level socket parameter.
Boole Connect(const SystemAddress &Address)
Connects this socket to a remote host connected to the network.
Definition: socket.cpp:178
const Integer SE_PFNotSupported
The system does not have the specified protocol family installed or configured. This is mostly interc...