Socket implementation
The socket interface is used to create socket for communication. There are four different types of sockets supported by the socket
interfaces: normal TCP sockets, TLS sockets (which internally encapsulates a TCP socket), UDP sockets and finally local sockets,
used for inter process communication. Each created ISocket instance can be used as server and client socket, depending on what
will be called first: ISocket::Bind() or ISocket::Connect(). After calling one of theese functions, the mode the socket is defined and
can not be changed anymore.
To create an ISocket instance, at first an instance of ISocketProvider must be created. This need to be done by calling one of the
Create*SocketProvider. This defines the type of ISocketProvider as well as the type of ISocket that will be created. An ISocketProvider
can be used to create multiple ISocket instances and can be deleted, if now longer be used. An created ISocket doesn't depend on the
ISocketProvider used to created it.
Generally, each type of socket will be handled in the same way by ISocketProvider and ISocket, with two exceptions:
-
ISocket::SendTo() / USocket::SocketRecvFromResult(): Because of the nature of UDP sockets, the address to send data to
need to be given. Also the address data received from will be told. Because of that, the interface has special functions for
UDP sockets. While calling ISocket::SendTo() on other types of sockets simply will have no effect, USocket::SocketRecvFromResult()
will never be called from an other type of ISocket than UDP.
-
ISocketContext: ISocketProvider::CreateSocket() will also accept an ISocketContext instance. This onyl will be used by
TLS sockets for additional informations about encryption and certificates to use.
File information
Functions
Functions to initialize
extern "C" ISocketProvider * CreateTCPSocketProvider();
extern "C" ISocketProvider * CreateTLSSocketProvider(class ISocketProvider * tcpSocketProvider);
extern "C" ISocketProvider * CreateUDPSocketProvider();
extern "C" ISocketProvider * CreateLocalSocketProvider();
Overview
These functions will create an ISockerProvider instance. What kind of socket provider they will return, depends on the function called. As the name
tells, the TCP version is for a TCP socket provider, the TLS function for a TLS socket, UDP for a UDP socket and finally LocalSocket will create a
socket provider for local sockets. The last one will be used for inter process communication between the apps.
A type of a created socket cannot be changed, except for TCP sockets which can be upgraded to a TLS socket.
CreateTCPSocketProvider
CreateTLSSocketProvider
CreateUDPSocketProvider
CreateLocalSocketProvider
-
Parameters (CreateTLSSocketProvider only)
class ISocketProvider * tcpSocketProvider | A socket provider instance to create a TCP socket used by the TLS socket object.. |
Return value
The ISocketProvider instance. That instance can be freed as soon as it no longer is used by calling the C++ delete operator.
Remarks
(For CreateTLSSocketProvider only): If a TLS socket provider only will be used to upgrade a TCP sockets, the tcpSocketProvider parameter cann be nullptr.
Classes
ISocketProvider
class ISocketProvider {
public:
virtual ~ISocketProvider() {};
virtual ISocketContext * CreateSocketContext(class IInstanceLog * const log);
virtual ISocket * CreateSocket(class IIoMux * const iomux, USocket * const user, class IInstanceLog * const log, bool useIPv6, class ISocketContext * socketContext = nullptr);
virtual ISocket * UpgradeToTLSSocket(class ISocket * fromTCPSocket, IIoMux * const iomux, USocket * const user, IInstanceLog * const log, bool initServerSide = false, class ISocketContext * socketContext = nullptr);
};
Overview
The socket provider is used to create an instance of ISocket or ISocketContext. While the ISocketContext is the same for each type of socket provider, the type of
ISocket created depends on the type of the ISocketProvider itself. See above for more informations.
Public functions
CreateSocketContext
-
Creates an ISocketContext instance. ISocketContext will be used to give additional informations to an ISocket. So it must be setup correctly after creation and
before passing to create an ISocket instance.
Parameters
class IInstanceLog * const log | The IInstanceLog instance used for loging purposes. |
Return value
The ISocketContext instance that can be used to pass it to ISocketProvider::CreateSocket(). It must be freed by the C++ operator delete, if no longer be used.
Remarks
Note that ISocket depends on an assigned ISocketContext. So an assigned ISocketContext must not be deleted before deleting the owing ISocket instance!
CreateSocket
-
Creates an instance of ISocket. The type of the socket (e. G. TCP, TLS, ...) depends on the type of the ISocketProvider and thus on the Create*SocketProvider()
function called.
Parameters
class IIoMux * const iomux | The IIoMux instance the socket will be registered to. |
class USocket * const user | The USocket instance that will be receive the callbacks of ISocket. |
class IInstanceLog * const log | The IInstanceLog instance used for loging purposes. |
bool useIPv6 | If set to true, the ISocket will be prepared for IPv6 usage instead of the default IPv4. |
class ISocketContext * const socketContext | (Default: nullptr) The ISocketContext instance to pass additional information to the socket. |
Return value
The ISocket instance to use for socket communication. If no longer used, the instance need to be freed by calling the C++ delete operator.
UpgradeToTSLSocket
-
Takes the given TCP socket instance and upgrades it to an TLS socket. Depending on the value of initServerSide, the returned ISocket will directly start the TLS handshake
or wait for the handshake to be started. As soon as the handshake had been completed, a callback to the given USocket instance will inform the application.
Parameters
class ISocket * fromTCPSocket | The TCPSocket to upgrade. The socket must already be connected successfully. |
class IIoMux * const iomux | The IIoMux instance the socket will be registered to. |
class USocket * const user | The USocket instance that will be receive the callbacks of the upgraded ISocket. |
class IInstanceLog * const log | The IInstanceLog instance used for loging purposes. |
bool initServerSide | (Default: false) If ture, the TSL socket will wailt for the other side to start the handshake, else the handshake will be initiated by the TLS socket itself. |
class ISocketContext * const socketContext | (Default: nullptr) The ISocketContext instance to pass additional information to the socket. |
Return value
The ISocket instance to use for socket communication. If no longer used, the instance need to be freed by calling the C++ delete operator.
Callbacks
After everything had been set up and the handshake had been completed, SocketUpgradeToTLSComplete() of the given USocket instance will be called.
Remarks
The returned ISocket object takes resposibility for the given TCP socket. That means, the user for the TCP socket will be changed and it also will be deleted, as soon as the
application deletes the returned ISocket object. The best idea is, that an application will completly forget about the TCP socket object passed to UpgradeToTLSSocket().
Passing a TLS socket object to fromTCPSocket will raise an exception. Only pass TCP socket objects. However, even if not recommented, in theory it also will work with UD sockets,
as long as the other side also knows how to talk TLS.
ISocketContext
class ISocketContext {
public:
virtual ~ISocketContext() {};
virtual void EnableDTLS(bool useSrtp);
virtual void SetServerCertificate(const byte * cert, size_t certLen, const char * hostName = nullptr);
virtual void SetClientCertificate(const byte * cert, size_t certLen, const char * hostName = nullptr);
virtual const byte * GetCertificateFingerprint(size_t * length);
virtual void DisableClientCertificate();
virtual void SetALPNProcotols(const char * const * alpnList) {};
};
Overview
An ISocketContext can be used to handle certificates and other socket related configuration. Because that configuration will be necessary during the creation if ISocket,
an ISocketContext instance must be setup properly before passing it to ISocketProvider::CreateSocket()
After the creation of an ISocket, the ISocketContext instance is connected with the ISocket instance, so it must not be deleted until the ISocket instance had beend deleted first.
Remarks
An ISocketContext insatance can be shared with multiple ISockets (which must be taken care of when deleting ISocketContext). Because of the types of informations hold, it currently
can only be used for TLS sockets.
Public functions
EnableDTLS
-
Enables DTLS encryption. Srtp = true --> Benutzt DTLS für Srtp
Parameters
bool useSrtp | If true, the DTLS class will be prepared to be used for secure real-time transport protocol (e. g. for video) |
SetServerCertificate
-
Defines the certificate to use for ISocket server functionality.
Parameters
const byte * cert | The buffer to the certificate data. |
size_t certLen | The length of the certificate. |
const char * hostName | Reserved for later use - see remarks. |
Remarks
Currently, the hostName functionality is not implemented, so you just override the default server certificate.
Please not that if you set a new server certificate, all currently established conntections will still use the old certificate. The new set certificate only will be used by new connections.
SetClientCertificate
-
Defines the certificate to use for ISocket client functionality.
Parameters
const byte * cert | The buffer to the certificate data. |
size_t certLen | The length of the certificate. |
const char * hostName | Reserved for later use - see remarks. |
Remarks
Currently, the hostName functionality is not implemented, so you just override the default server certificate.
Please not that if you set a new server certificate, all currently established conntections will still use the old certificate. The new set certificate only will be used by new connections.
DisableClientCertificate
-
Disables sending of a client certificate in TLS requests.
SetALPNProcotols
-
Sets a list of supported ALPN protocols, which are sent within the TLS handshake.
Parameters
const char * const * alpnList | An array of protocols. The last array item must be a nullptr! |
Remarks
A sample array would be this:
static const constexpr char* ALPN_HTTP1_0 = "http/1.0";
static const constexpr char* ALPN_HTTP1_1 = "http/1.1";
static const constexpr char* ALPN_HTTP2 = "h2";
static const constexpr char* ALPN_END_OF_LIST = nullptr;
static const char* alpnList[] = {
ALPN_HTTP1_0,
ALPN_HTTP1_1,
ALPN_HTTP2,
ALPN_END_OF_LIST
};
ISocket
class ISocket {
public:
virtual ~ISocket() {};
virtual void Connect(const char * address, const char * serverName = NULL);
virtual void Bind(const char * localAddr = nullptr, word localPort = 0);
virtual void Listen();
virtual void Accept(class USocket * remoteUser);
virtual void Shutdown();
virtual void Send(const void * buf, size_t len);
virtual void SendTo(const void * buf, size_t len, IPaddr dstAddr, word dstPort) {};
virtual void Recv(void * buf, size_t len, bool recvPartial = false);
virtual void SetUser(class USocket * const user);
};
Overview
The ISocket interface is used for socket communication. After the creation of an ISocket by using an ISocketProvider instance, the usage of the ISocket instance
starts by calling Connect() or Bind(). All of the functions will lead to an asynchronous callback of the USocket user instance, passed to ISocketProvider::CreateSocket().
Logging
To enable logging for ISocket, the flag LOG_TCP (for TCP sockets), LOG_TLS (for TLS sockets), LOG_UDP (for UDP sockets) or LOG_LDS (for local sockets) must be set in the managers
diagnostic settings.
Remarks
An ISocket instance can be used for either server or socket side of the connection, depending what function had been called. After calling Connect(), the ISocket
instance will be in client mode, while a call to Bind() will enable the server mode. Calling a function of the other mode (e. g. calling Listen() or Bind()
after calling Connect() and setting the ISocket instance to client mode) will lead to an assert.
Public functions
Bind (server mode)
-
This function enables the server mode of ISocket and binds it to the given address. After receiving the USocket::BindResult() callback, Listen() must be called to receive
incomming connection requests from clients.
Parameters
const char * localAddr |
(Default nullptr) A String that holds an IPv4 or IPv6 address (for TCP and TLS sockets, also depending on
the useIPv6 flag passed for creation) or address name (for local sockets, normaly a file name).
If nullptr is given, the operating system bind the socket to all interfaces available (TCP, TLS and UDP socket only)
|
word localPort |
(Default 0) The port the socket should listen to after binding. (TCP and TLS sockets only). If 0 is passed, the
operating system will pick a free port.
|
Callbacks
On success, USocket::BindResult() will be called.
If an error occurres, USocket::SocketShutdown() will be called. Details of that error can be found inside the log, if logging for that type of socket is activated. Reason can be one
of the following values:
SOCKET_ADDRESS_INVALID | The format of the given address is invalid. |
SOCKET_OPEN_FAILED | Opening the socket failed because of an error. See log for details. |
SOCKET_BIND_FAILED | An error occured during the bind process. See the log for details. |
Remarks
After calling Bind(), a call to Connect(), Send() or Recv() will end up with an assert.
Only for local sockets under Linux: The rights of file given to use for bind will be set to read/write for each users, otherwise other appas can not access the socket because of the
apps sandboxing.
Listen (server mode)
-
After a successfull bind, Listen() must be called to start listening to the address / port combination of Bind(). Only after calling Listen() the ISocket instance
will receive and handle connect requests.
Callbacks
If an error occurres, USocket::SocketShutdown() will be called with SOCKET_LISTEN_FAILED as reason. Details of that error can be found inside the log, if logging for
that type of socket is activated.
On success, USocket will only be informed about an incoming connect request. In that case, USocket::ListenResult() will be called.
Remarks
Listen only must be called once. But it will lead to couple of USocket::ListenResult() callbacks for each incomming connection request.
Accept (server mode)
-
Need to be called to accept an incomming connection request. This will accept the incomming request, create internally an ISocket and passes it to USocket::AcceptComplete().
So the USocket instance passed to Accept() is responsible to release the created ISocket instance when no longer needed. See USocket::AcceptComplete() for details.
To deniy the request, nullptr need to be passed to Accept().
Remarks
Note that Accept() must be called from inside USocket::ListenResult()!
Parameters
class USocket * remoteUser |
The user for the new ISocket, that will be created when accepting the request. Accept() will call
AcceptComplete() of the given user. If remoteUser is nullptr, the request will be denied.
|
Callbacks
If an error occurres, USocket::SocketShutdown() will be called with SOCKET_ACCEPT_FAILED as reason. Details of that error can be found inside the log, if logging for
that type of socket is activated.
On success, USocket::AcceptComplete() will be called with the new ISocket instance of the connection as parameter. Note that the USocket instance given to Accept() is
responsible for releasing the inside Accept() created ISocket instance.
Connect (client mode)
-
This function enables the client mode of the ISocket instance and starts to establish a connection to the given address. When the connection had been established,
the assigned USocket instance will be informed.
Remarks
Note that after calling Connect(), a call to Bind(), Listen() and Accept() will lead to an assert.
Parameters
const char * address |
The address to connect to. It must be an IPv4 or IPv6 address as string. An optional port can be given
seperated by colon (e. G. "192.168.1.100:4242"). For IPv6 addresses, an the adress itself need to be put
inside '[' ']' if a port need to be passed (e. G. [::ffff:c0a8:164]:80)
|
const char * serverName = NULL |
The server name to connect to, e.g. 'www.testserver.com'. The server name is used in the server_name extension of TLS connections inside the ClientHello.
|
Callbacks
On success, ISocket will call USocket::SocketConnectComplete().
If an error occurres, USocket::SocketShutdown() will be called. Details of that error can be found inside the log, if logging for that type of socket is activated. Reason can be one
of the following values:
SOCKET_ADDRESS_INVALID | The format of the given address is invalid. |
SOCKET_OPEN_FAILED | Opening the socket failed because of an error. See log for details. |
SOCKET_CONNECT_FAILED | An error occured during the connect process. See the log for details. |
SOCKET_CONNECT_REJECTED | The connection request had been rejected by the host. |
SetUser
-
Sets the given user as active one to receive callbacks, replacing the one passed during socket creation.
Parameters
USocket * const user | The user to set, must not be nullptr. |
Remarks
ISocket will not check, if the given user is nullptr or not. However, the developer also should take about not passing an object that already had been deleted.
Send (client mode)
-
Used to send data to the connected server. Send() can be called directly after calling Connect() and bevore receiving the SocketConnectComplete() callback. In that case,
the data to send will be cached. But it is highly recommended to start sending data after the connection had been established as well as send the next part, after receiving
the SendComplete() callback. Doing this helps a lot to have a healthy flow control.
Parameters
const void * buf | The buffer with the data to send. Must not be nullptr! |
size_t len | The number of bytes to send. That means, that the size of the buffer should be at least the same as the value passed to len. |
Callbacks
On success, USocket::SocketSendResult() will be called when, ISocket has sent the data.
The only case when Send() failes is, when the socket is closing, so there is no special send related error here.
SendTo (client mode)
-
Used to send data to a given address for an UDP socket. Like Send(), the data will be cached if it not can be send immidiatelly.
Parameters
const void * buf | The buffer with the data to send. Must not be nullptr! |
size_t len | The number of bytes to send. That means, that the size of the buffer should be at least the same as the value passed to len. |
IPaddr dstAddr | Destination address to send to. |
word dstPort | Destination port to send to. |
Callbacks
On success, USocket::SocketSendResult() will be called when, ISocket has sent the data.
The only case when Send() failes is, when the socket is closing, so there is no special send related error here.
Remarks
SendTo() is only available for UDP sockets. Every other socket will just ignore a call to of that function.
Recv (client mode)
-
Tells the ISocket instance to receive data. The SocketRecvResult() callback will be called, as soon as data had been read from the socket.
Parameters
const void * buf | The buffer to write the received data to. Must not be nullptr! |
size_t len |
The number of bytes to receive from the socket. The SocketRecvResult() will only be called, if the given amount of data had been
read (except if recvPartitial is set to true). The given buffer must be at least big enough to store len bytes to it.
|
bool recvPartitial | (Default false)If set to true, ISocket will call SocketRecvResult() as soon as posibile. That means, that everything between 1 and len bytes had been read. |
Callbacks
On success, USocket::SocketRecvResult() with the buffer given to Recv() and the number of bytes read.
The only case when Recv() failes is, when the socket is closing, so there is no special send related error here.
Remarks
Warning: If using the default non partitial Recv() (recvPartitial set to false), it must be guaranteed, that there are at least len number of bytes available to read from the socket.
If not, the ISocket instance will never call USocket::SocketRecvResult(), because it will wait for the given amount of data to arrive.
Shutdown
-
Closes the socket. For an ISocket in client mode, all cached data will be send first, because the socket will be closed. However, new calls to Send() or Recv() after
calling Shutdown() will be ignored.
Callbacks
After the socket had been closed, USocket::SocketShutdown() will be called with reason SOCKET_SHUTDOWN_NORMAL.
USocket
class USocket {
public:
virtual ~USocket() {}
virtual void SocketConnectComplete(ISocket * const socket) {};
virtual void SocketBindResult(ISocket * const socket, const char * localAddr, word localPort) {};
virtual void SocketListenResult(ISocket * const socket, const char * remoteAddr, word remotePort) {};
virtual void SocketAcceptComplete(ISocket * const socket) {};
virtual void SocketShutdown(ISocket * const socket, shutdownreason_t reason);
virtual void SocketSendResult(ISocket * const socket) {};
virtual void SocketRecvResult(ISocket * const socket, void * buf, size_t len) {};
virtual void SocketRecvFromResult(ISocket * const socket, void * buf, size_t len, IPaddr srcAddr, word srcPort) {};
virtual void SocketRecvCanceled(ISocket * const socket, void * buf);
virtual void SocketUpgradeToTLSComplete(ISocket * const socket) {}
virtual bool SocketAcceptSelectedALPNProtocol(ISocket * const socket, const char * protocol) { return true; };
};
Overview
USocket class is used to receive callbacks from an ISocket instance. So an app need to subclass USocket and pass an instance of that subclass to ISocketProvider::CreateSocket().
That subclass also has to override each callback that is needed for what the ISocket is going to used. One USocket instance can be given to multiple ISocket instanced. Because of
that, the ISocket instance that calls a USocket callback will always be passed as parameter.
Remarks
Except SocketShutdown(), which must be implemented, all other functions have a default implementation. So the developer needs to take care to realy override the necessary functions.
Public functions
SocketConnectComplete
-
Will be called after an ISocket instance sucessfully established a connection to the given address.
Parameters
ISocket * const socket | The calling ISocket instance. |
SocketBindResult
-
Will be called after an ISochet instance had been successfully bound to an address. Remember that ISocket::Listen() still must be called, before the socket can
receive connection requests. So SocketBindResult() would be the right place to do so.
Parameters
ISocket * const socket | The calling ISocket instance. |
const char * localAddr | The address the socket had been bound to. Normaly the same value as passed to ISocket::Bind(). |
word localPort | The port the socket had been bound to. Normaly the same as passed to ISocket::Bind() or, in case that 0 had been passed, the port the OS had been selected. |
Remarks
If ISocket::Bind() had been called with nullptr as address (to bind the socket to all available interfaces), localAddr will be "0.0.0.0".
For local sockets, localPort always will be 0.
SocketListenResult
-
After calling ISocket::Listen(), each incoming connection request to the socket will lead to a USocket::SocketListenResult(). There the application must decide,
whether the connection will be accepted or denied. This will be done by calling ISocket::Accept() with an USocket instance (to accept) or with nullptr (to deny).
Parameters
ISocket * const socket | The ISocket instance that received an incomming connection request. |
const char * remoteAddress | The address of the client that whants to connect to the socket. |
word remotePort | The port of the client that wants to connect to the socket. |
Remarks
ISocket::Accept must be called inside USocket::SocketListenResult().
SocketAcceptComplete
-
Will be called after USocket::ListenResult() calls ISocket::Accept() with an USocket instance. So ISocket will call USocket::SocketAcceptComplete() of the instance,
passed to ISocket::Accept() inside USocket::SocketListenResult().
Parameters
ISocket * const socket |
The calling ISocket instance. Unlike the other callback functions, the ISocket instance passed here is a new created one that now had been connected to the client,
that requested the connection. So USocket is now responsible for this ISocket instance.
|
Remarks
It is important to understand, that USocket::SocketListenResult() will be called from an ISocket instance, that acts in server mode. But the ISocket instance
passed to USocket::SocektAcceptComplete() is a new created instance that acts like a client mode ISocket. So ISocket::Send() and ISocket::Recv() can be called,
but not Connect() (because it already is connected). See the documentation of ISocket for more informations.
The USocket instance that received this callback is responsible for the ISocket instance passed to the callback function. So it should be stored in a local
variable and freed if no longer needed.
SocketShutdown
-
Will be called after the socket had been closed. It is guaranteed, that all cached data had been send and no more receiving will be done. Also no other callback will
be called any more. So the ISocket instance passed can be safely deleted here.
Parameters
ISocket * const socket | The calling ISocket instance. Because the socket is closed, the given instance can be deleted here. |
shutdownreason_t reason | The reason why the socket had been closed. See data type shutdownreason_t for more informations. |
SocketSendResult
-
Will be called after ISocket::Send() had sent the given data or after the data had been cached and sent after that. Even if ISocket::Send() can send the data directly,
it is guaranteed that USocket::SocketSendResult() will never ever be called before returning from ISocket::Send(). It will be a good idea to use USocket::SocketSendResult()
to send the next data package. Doing this gives a nice flow controll to the application.
Parameters
ISocket * const socket | The calling ISocket instance. |
SocketRecvResult
-
Will be called, after the application calls ISocket::Recv() and after data had been received.
Parameters
ISocket * const socket | The calling ISocket instance. |
void * buf | The buffer that holds the received data. It is the same as passed to ISocket::Recv(). |
size_t len |
The number of bytes read. If ISocket::Recv() is called with recvPartitial true, len can be anything between 1 and the number of bytes passed
to ISocket::Recv(). If ISocket::Recv() is called with recvPartitial fase, it is guaranteed, that len is the same as passed to ISocket::Recv() before.
|
SocketRecvFromResult
-
The same as Recv(), with the difference that the origin of the data will be passed, too. Only for UDP sockets.
Parameters
ISocket * const socket | The calling ISocket instance. |
void * buf | The buffer that holds the received data. It is the same as passed to ISocket::Recv(). |
size_t len |
The number of bytes read. If ISocket::Recv() is called with recvPartitial true, len can be anything between 1 and the number of bytes passed
to ISocket::Recv(). If ISocket::Recv() is called with recvPartitial fase, it is guaranteed, that len is the same as passed to ISocket::Recv() before.
|
IPaddr srcAddr | Source address from where it was received. |
word srcPort | Source port from where it was received. |
Remarks
This callback will only be called from UDP ISocket instances.
SocketRecvCanceled
-
Will be called after calling ISocket::RecvCancel() and after canceling had been done. An application must implement that callback to free the buffer passed to Recv() (if
not freed elsewhere)
Parameters
ISocket * const socket |
The calling ISocket instance.
|
void * buf |
The pointer to the buffer passed to the last Recv() call.
|
SocketUpgradeToTLSComplete
-
When calling ISocketProvider::UpgradeToTSLSocket() to upgrade an TCP socket for using TLS (e. g. for StartTLS), this function will be called after
everything is set up and the TLS handshake had been successfully completed. From now on, the connection communicates in an encrypted way.
Parameters
ISocket * const socket |
The calling ISocket instance. Unlike the other callback functions, the ISocket instance passed here is a new created one and the same as returned by
ISocketProvider::UpgradeToTLSSocket().
|
SocketAcceptSelectedALPNProtocol
-
If an ALPN list is provided by the given ISocketContext, this function is called with the accepted protocol.
Parameters
ISocket * const socket |
The calling ISocket instance.
|
const char * protocol |
The selected protocol.
|
Return value
A boolean. Return true if you support the given protocol, otherwise false, which will terminate the connection.
Data types
shutdownreason_t
Overview
The data type shutdownreason_t will be passed to USocket::SocketShutdown() to descr ibe the reason, why the socket had been closed.
Values
SOCKET_SHUTDOWN_NORMAL | The socket had been closed because of a call to ISocket::Shutdown(). |
SOCKET_SHUTDOWN_BY_PEER | The socket had been closed by the other side of the connection. |
SOCKET_LOST | the connection got lost. This could have various reasons: the other side crashed, the physical connection got lost, ... |
SOCKET_ADDRESS_INVALID | The given address for ISocket::Connect() or ISocket::Bind() is invalid. |
SOCKET_OPEN_FAILED | Opening the socket failed because of an error. See log for details. |
SOCKET_CONNECT_FAILED | An error occured during the connect process. See the log for details. |
SOCKET_CONNECT_REJECTED | The connection request had been rejected by the host. |
SOCKET_BIND_FAILED | An error occured during the bind process. See the log for details. |
SOCKET_LISTEN_FAILED | A call to ISocket::Listen() failed because of an error. See the log for details. |
SOCKET_ACCEPT_FAILED | A call to ISocket::Accept() had been failed because of an error. See tje log for details. |
SOCKET_TLS_HANDSHAKE_FAILED | (Only TLS sockets) The TLS handshake failed because of an error. See the log for details. |
Code Example
ISocket - server
// App with ISocket in server mode
app::app(class IIoMux * iomux)
: iomux(iomux)
{
ISocketProvider * provider = CreateTCPSocketProvider();
this->serverSocket = provider->Create(iomux, this, false);
delete provider;
this->serverSocket->Bind();
}
void app::SocketBindResult(ISocket * const socket, const char * localAddr, word localPort)
{
this->serverSocket->Listen();
}
void app::SocketListenResult(ISocket * const socket, const char * remoteAddr, word remotePort)
{
// Deny local connections...
if (strcmp(remoteAddr, "127.0.0.1") == 0)
this->serverSocket->Accept(nullptr);
else
this->serverSocket->Accept(new remoteUser());
}
void app::SocketShutdown(ISocket * const socket, shutdownreason_t reason)
{
// If true, an error occured during a call to Bind() and SocketBindResult()
if (this->serverSocket == nullptr)
delete socket;
else {
delete this->serverSocket;
this->serverSocket = nullptr;
}
this->iomux->Terminate();
}
ISocket - client
// remoteUser is subclassed from USocket
void remoteUser::SocketAcceptComplete(ISocket * const socket)
{
this->remoteSocket = socket;
this->remoteSocket->Recv(buffer, 1024);
this->remoteSocket->Send("Hello world", 11);
}
void remoteUser::SocketSendResult(ISocket * const socket)
{
printf("Data had been sent\n");
}
void remoteUser::SocketRecvResult(ISocket * const socket, void * buf, size_t len)
{
printf("Received data\n");
debug->HexDump(buf, len);
this->remoteSocket->Recv(buffer, 1024);
}
void remoteUser::SocketShutdown(ISocket * const socket, shutdownreason_t reason)
{
delete socket;
delete this;
}