# 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

File | common/interface/socket.h
Public functions | CreateTCPSocketProvider CreateTLSSocketProvider CreateUDPSocketProvider CreateLocalSocketProvider
Classes | ISocketProvider ISocketContext ISocket USocket
Data types | shutdownreason_t qostraffictype_t
Examples | ISocket - server ISocket - client

# 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, bool * createdByServer = NULL, const char ** remoteAddress = NULL, const char ** serverName = NULL);
        virtual void SetQoS(qostraffictype_t type) {};
        virtual void GetLocalAddress(char * localAddr, unsigned size, word * localPort) {};
        virtual void GetRemoteAddress(char * remoteAddr, unsigned size, word * remotePort) {};
    };

### 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.
  bool * createdByServer | Returns true if this is a socket created by a listening server socket.
  const char ** remoteAddress | Set to the remote address like 172.16.14.14:123 or [ff06:0:0:0:0:0:0:c3]:123.
  const char ** serverName | The server name handed inside the Connect function.

SetQoS

  Sets a QoS traffic type.

  #### Parameters

  qostraffictype_t type | The QoS traffic type.

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.

GetLocalAddress

  Gets the local interface address and port of the socket.

  #### Parameters

  char * localAddr | The buffer to write the address to. Must not be nullptr!
  unsigned size | The buffer size of localAddr.
  word * localPort | A word pointer which will hold the local port afterwards.

  #### Remarks

  For UDP sockets, GetLocalAddress will first contain meaningful data after a SocketRecvFromResult was called.

GetRemoteAddress

  Gets the remote address and port of the socket.

  #### Parameters

  char * remoteAddr | The buffer to write the address to. Must not be nullptr!
  unsigned size | The buffer size of remoteAddr.
  word * remotePort | A word pointer which will hold the remote port afterwards.

  #### Remarks

  GetRemoteAddress is not implemented for UDP sockets. You get the remote address and port inside the SocketRecvFromResult callback instead.

## 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.

## qostraffictype_t

### Overview

The data type qostraffictype_t will be passed to ISocket::SetQoS().

#### Values

QOS_BEST_EFFORT | best effort delivery
QOS_AUDIO_VIDEO | audio and video
QOS_VOICE | voice

# 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;
    }