| 1 | /* |
| 2 | Copyright (c) 2012, Broadcom Europe Ltd |
| 3 | All rights reserved. |
| 4 | |
| 5 | Redistribution and use in source and binary forms, with or without |
| 6 | modification, are permitted provided that the following conditions are met: |
| 7 | * Redistributions of source code must retain the above copyright |
| 8 | notice, this list of conditions and the following disclaimer. |
| 9 | * Redistributions in binary form must reproduce the above copyright |
| 10 | notice, this list of conditions and the following disclaimer in the |
| 11 | documentation and/or other materials provided with the distribution. |
| 12 | * Neither the name of the copyright holder nor the |
| 13 | names of its contributors may be used to endorse or promote products |
| 14 | derived from this software without specific prior written permission. |
| 15 | |
| 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY |
| 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 26 | */ |
| 27 | |
| 28 | #ifndef VC_NET_SOCKETS_H |
| 29 | #define VC_NET_SOCKETS_H |
| 30 | |
| 31 | /** \file net_sockets.h |
| 32 | * Abstraction layer for socket-style network communication, to enable porting |
| 33 | * between platforms. |
| 34 | * |
| 35 | * Does not support IPv6 multicast. |
| 36 | */ |
| 37 | |
| 38 | #include "containers/containers_types.h" |
| 39 | |
| 40 | #ifdef __cplusplus |
| 41 | extern "C" { |
| 42 | #endif |
| 43 | |
| 44 | /** Status codes that can occur in a socket instance. */ |
| 45 | typedef enum { |
| 46 | VC_CONTAINER_NET_SUCCESS = 0, /**< No error */ |
| 47 | VC_CONTAINER_NET_ERROR_GENERAL, /**< An unrecognised error has occurred */ |
| 48 | VC_CONTAINER_NET_ERROR_INVALID_SOCKET, /**< Invalid socket passed to function */ |
| 49 | VC_CONTAINER_NET_ERROR_NOT_ALLOWED, /**< The operation requested is not allowed */ |
| 50 | VC_CONTAINER_NET_ERROR_INVALID_PARAMETER, /**< An invalid parameter was passed in */ |
| 51 | VC_CONTAINER_NET_ERROR_NO_MEMORY, /**< Failure due to lack of memory */ |
| 52 | VC_CONTAINER_NET_ERROR_ACCESS_DENIED, /**< Permission denied */ |
| 53 | VC_CONTAINER_NET_ERROR_TOO_BIG, /**< Too many handles already open */ |
| 54 | VC_CONTAINER_NET_ERROR_WOULD_BLOCK, /**< Asynchronous operation would block */ |
| 55 | VC_CONTAINER_NET_ERROR_IN_PROGRESS, /**< An operation is already in progress on this socket */ |
| 56 | VC_CONTAINER_NET_ERROR_IN_USE, /**< The address/port is already in use */ |
| 57 | VC_CONTAINER_NET_ERROR_NETWORK, /**< Network is unavailable */ |
| 58 | VC_CONTAINER_NET_ERROR_CONNECTION_LOST, /**< The connection has been lost, closed by network, etc. */ |
| 59 | VC_CONTAINER_NET_ERROR_NOT_CONNECTED, /**< The socket is not connected */ |
| 60 | VC_CONTAINER_NET_ERROR_TIMED_OUT, /**< Operation timed out */ |
| 61 | VC_CONTAINER_NET_ERROR_CONNECTION_REFUSED, /**< Connection was refused by target */ |
| 62 | VC_CONTAINER_NET_ERROR_HOST_NOT_FOUND, /**< Target address could not be resolved */ |
| 63 | VC_CONTAINER_NET_ERROR_TRY_AGAIN, /**< A temporary failure occurred that may clear */ |
| 64 | } vc_container_net_status_t; |
| 65 | |
| 66 | /** Operations that can be applied to sockets */ |
| 67 | typedef enum { |
| 68 | /** Set the buffer size used on the socket |
| 69 | * arg1: uint32_t - New buffer size in bytes */ |
| 70 | VC_CONTAINER_NET_CONTROL_SET_READ_BUFFER_SIZE = 1, |
| 71 | /** Set the timeout to be used on read operations |
| 72 | * arg1: uint32_t - New timeout in milliseconds, or INFINITE_TIMEOUT_MS */ |
| 73 | VC_CONTAINER_NET_CONTROL_SET_READ_TIMEOUT_MS, |
| 74 | } vc_container_net_control_t; |
| 75 | |
| 76 | /** Container Input / Output Context. |
| 77 | * This is an opaque structure that defines the context for a socket instance. |
| 78 | * The details of the structure are contained within the platform implementation. */ |
| 79 | typedef struct vc_container_net_tag VC_CONTAINER_NET_T; |
| 80 | |
| 81 | /** \name Socket open flags |
| 82 | * The following flags can be used when opening a network socket. */ |
| 83 | /* @{ */ |
| 84 | typedef uint32_t vc_container_net_open_flags_t; |
| 85 | /** Connected stream socket, rather than connectionless datagram socket */ |
| 86 | #define VC_CONTAINER_NET_OPEN_FLAG_STREAM 1 |
| 87 | /** Force use of IPv4 addressing */ |
| 88 | #define VC_CONTAINER_NET_OPEN_FLAG_FORCE_IP4 2 |
| 89 | /** Force use of IPv6 addressing */ |
| 90 | #define VC_CONTAINER_NET_OPEN_FLAG_FORCE_IP6 6 |
| 91 | /** Use IPv4 broadcast address for datagram delivery */ |
| 92 | #define VC_CONTAINER_NET_OPEN_FLAG_IP4_BROADCAST 8 |
| 93 | /* @} */ |
| 94 | |
| 95 | /** Mask of bits used in forcing address type */ |
| 96 | #define VC_CONTAINER_NET_OPEN_FLAG_FORCE_MASK 6 |
| 97 | |
| 98 | /** Blocks until data is available, or an error occurs. |
| 99 | * Used with the VC_CONTAINER_NET_CONTROL_SET_READ_TIMEOUT_MS control operation. */ |
| 100 | #define INFINITE_TIMEOUT_MS 0xFFFFFFFFUL |
| 101 | |
| 102 | |
| 103 | /** Opens a network socket instance. |
| 104 | * The network address can be a host name, dotted IP4, hex IP6 address or NULL. Passing NULL |
| 105 | * signifies the socket is either to be used as a datagram receiver or a stream server, |
| 106 | * depending on the flags. |
| 107 | * \ref VC_CONTAINER_NET_OPEN_FLAG_STREAM will open the socket for connected streaming. The default |
| 108 | * is to use connectionless datagrams. |
| 109 | * \ref VC_CONTAINER_NET_OPEN_FLAG_FORCE_IP4 will force the use of IPv4 addressing or fail to open |
| 110 | * the socket. The default is to pick the first available. |
| 111 | * \ref VC_CONTAINER_NET_OPEN_FLAG_FORCE_IP6 will force the use of IPv6 addressing or fail to open |
| 112 | * the socket. The default is to pick the first available. |
| 113 | * \ref VC_CONTAINER_NET_OPEN_FLAG_IP4_BROADCAST will use IPv4 broadcast addressing for a datagram |
| 114 | * sender. Use with an IPv6 address, stream socket or datagram receiver will raise an error. |
| 115 | * If the p_status parameter is not NULL, the status code will be written to it to indicate the |
| 116 | * reason for failure, or VC_CONTAINER_NET_SUCCESS on success. |
| 117 | * Sockets shall be bound and connected as necessary. Stream server sockets shall further need |
| 118 | * to have vc_container_net_listen and vc_container_net_accept called on them before data can be transferred. |
| 119 | * |
| 120 | * \param address Network address or NULL. |
| 121 | * \param port Network port or well-known name. This is the local port for receivers/servers. |
| 122 | * \param flags Flags controlling socket type. |
| 123 | * \param p_status Optional pointer to variable to receive status of operation. |
| 124 | * \return The socket instance or NULL on error. */ |
| 125 | VC_CONTAINER_NET_T *vc_container_net_open( const char *address, const char *port, |
| 126 | vc_container_net_open_flags_t flags, vc_container_net_status_t *p_status ); |
| 127 | |
| 128 | /** Closes a network socket instance. |
| 129 | * The p_ctx pointer must not be used after it has been closed. |
| 130 | * |
| 131 | * \param p_ctx The socket instance to close. |
| 132 | * \return The status code for closing the socket. */ |
| 133 | vc_container_net_status_t vc_container_net_close( VC_CONTAINER_NET_T *p_ctx ); |
| 134 | |
| 135 | /** Query the latest status of the socket. |
| 136 | * |
| 137 | * \param p_ctx The socket instance. |
| 138 | * \return The status of the socket. */ |
| 139 | vc_container_net_status_t vc_container_net_status( VC_CONTAINER_NET_T *p_ctx ); |
| 140 | |
| 141 | /** Read data from the socket. |
| 142 | * The function will read up to the requested number of bytes into the buffer. |
| 143 | * If there is no data immediately available to read, the function will block |
| 144 | * until data arrives, an error occurs or the timeout is reached (if set). |
| 145 | * When the function returns zero, the socket may have been closed, an error |
| 146 | * may have occurred, a zero length datagram received, or the timeout reached. |
| 147 | * Check vc_container_net_status() to differentiate. |
| 148 | * Attempting to read on a datagram sender socket will trigger an error. |
| 149 | * |
| 150 | * \param p_ctx The socket instance. |
| 151 | * \param buffer The buffer into which bytes will be read. |
| 152 | * \param size The maximum number of bytes to read. |
| 153 | * \return The number of bytes actually read. */ |
| 154 | size_t vc_container_net_read( VC_CONTAINER_NET_T *p_ctx, void *buffer, size_t size ); |
| 155 | |
| 156 | /** Write data to the socket. |
| 157 | * If the socket cannot send the requested number of bytes in one go, the function |
| 158 | * will return a value smaller than size. |
| 159 | * Attempting to write on a datagram receiver socket will trigger an error. |
| 160 | * |
| 161 | * \param p_ctx The socket instance. |
| 162 | * \param buffer The buffer from which bytes will be written. |
| 163 | * \param size The maximum number of bytes to write. |
| 164 | * \return The number of bytes actually written. */ |
| 165 | size_t vc_container_net_write( VC_CONTAINER_NET_T *p_ctx, const void *buffer, size_t size ); |
| 166 | |
| 167 | /** Start a stream server socket listening for connections from clients. |
| 168 | * Attempting to use this on anything other than a stream server socket shall |
| 169 | * trigger an error. |
| 170 | * |
| 171 | * \param p_ctx The socket instance. |
| 172 | * \param maximum_connections The maximum number of queued connections to allow. |
| 173 | * \return The status of the socket. */ |
| 174 | vc_container_net_status_t vc_container_net_listen( VC_CONTAINER_NET_T *p_ctx, uint32_t maximum_connections ); |
| 175 | |
| 176 | /** Accept a client connection on a listening stream server socket. |
| 177 | * Attempting to use this on anything other than a listening stream server socket |
| 178 | * shall trigger an error. |
| 179 | * When a client connection is made, the new instance representing it is returned |
| 180 | * via pp_client_ctx. |
| 181 | * |
| 182 | * \param p_server ctx The server socket instance. |
| 183 | * \param pp_client_ctx The address where the pointer to the new client's socket |
| 184 | * instance is written. |
| 185 | * \return The status of the socket. */ |
| 186 | vc_container_net_status_t vc_container_net_accept( VC_CONTAINER_NET_T *p_server_ctx, VC_CONTAINER_NET_T **pp_client_ctx ); |
| 187 | |
| 188 | /** Non-blocking check for data being available to read. |
| 189 | * If an error occurs, the function will return false and the error can be |
| 190 | * obtained using socket_status(). |
| 191 | * |
| 192 | * \param p_ctx The socket instance. |
| 193 | * \return True if there is data available to read immediately. */ |
| 194 | bool vc_container_net_is_data_available( VC_CONTAINER_NET_T *p_ctx ); |
| 195 | |
| 196 | /** Returns the maximum size of a datagram in bytes, for sending or receiving. |
| 197 | * The limit for reading from or writing to stream sockets will generally be |
| 198 | * greater than this value, although the call can also be made on such sockets. |
| 199 | * |
| 200 | * \param p_ctx The socket instance. |
| 201 | * \return The maximum size of a datagram in bytes. */ |
| 202 | size_t vc_container_net_maximum_datagram_size( VC_CONTAINER_NET_T *p_ctx ); |
| 203 | |
| 204 | /** Get the DNS name or IP address of a stream server client, if connected. |
| 205 | * The length of the name will be limited by name_len, taking into account a |
| 206 | * terminating NUL character. |
| 207 | * Calling this function on a non-stream server instance, or one that is not |
| 208 | * connected to a client, will result in an error status. |
| 209 | * |
| 210 | * \param p_ctx The socket instance. |
| 211 | * \param name Pointer where the name should be written. |
| 212 | * \param name_len Maximum number of characters to write to name. |
| 213 | * \return The status of the socket. */ |
| 214 | vc_container_net_status_t vc_container_net_get_client_name( VC_CONTAINER_NET_T *p_ctx, char *name, size_t name_len ); |
| 215 | |
| 216 | /** Get the port of a stream server client, if connected. |
| 217 | * The port is written to the address in host order. |
| 218 | * Calling this function on a non-stream server instance, or one that is not |
| 219 | * connected to a client, will result in an error status. |
| 220 | * |
| 221 | * \param p_ctx The socket instance. |
| 222 | * \param port Pointer where the port should be written. |
| 223 | * \return The status of the socket. */ |
| 224 | vc_container_net_status_t vc_container_net_get_client_port( VC_CONTAINER_NET_T *p_ctx , unsigned short *port ); |
| 225 | |
| 226 | /** Perform a control operation on the socket. |
| 227 | * See vc_container_net_control_t for more details. |
| 228 | * |
| 229 | * \param p_ctx The socket instance. |
| 230 | * \param operation The control operation to perform. |
| 231 | * \param args Variable list of additional arguments to the operation. |
| 232 | * \return The status of the socket. */ |
| 233 | vc_container_net_status_t vc_container_net_control( VC_CONTAINER_NET_T *p_ctx, vc_container_net_control_t operation, va_list args); |
| 234 | |
| 235 | /** Convert a 32-bit unsigned value from network order (big endian) to host order. |
| 236 | * |
| 237 | * \param value The value to be converted. |
| 238 | * \return The converted value. */ |
| 239 | uint32_t vc_container_net_to_host( uint32_t value ); |
| 240 | |
| 241 | /** Convert a 32-bit unsigned value from host order to network order (big endian). |
| 242 | * |
| 243 | * \param value The value to be converted. |
| 244 | * \return The converted value. */ |
| 245 | uint32_t vc_container_net_from_host( uint32_t value ); |
| 246 | |
| 247 | /** Convert a 16-bit unsigned value from network order (big endian) to host order. |
| 248 | * |
| 249 | * \param value The value to be converted. |
| 250 | * \return The converted value. */ |
| 251 | uint16_t vc_container_net_to_host_16( uint16_t value ); |
| 252 | |
| 253 | /** Convert a 16-bit unsigned value from host order to network order (big endian). |
| 254 | * |
| 255 | * \param value The value to be converted. |
| 256 | * \return The converted value. */ |
| 257 | uint16_t vc_container_net_from_host_16( uint16_t value ); |
| 258 | |
| 259 | #ifdef __cplusplus |
| 260 | } |
| 261 | #endif |
| 262 | |
| 263 | #endif /* VC_NET_SOCKETS_H */ |
| 264 | |