Finalized Error Handling functions

This commit is contained in:
2024-05-05 10:05:02 -04:00
parent bf573f92d9
commit 7f3d251d35
2 changed files with 288 additions and 235 deletions

View File

@@ -1,247 +1,37 @@
#pragma once
#include <cstdint>
using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
using s8 = int8_t;
using s16 = int16_t;
using s32 = int32_t;
using s64 = int64_t;
namespace Socket {
/// Generic Socket Error Handling Functions
// The following are general socket errors only. There may be other domain-specific error codes.
// Semantically, these error codes are meant for the developer of UdpSocket/TcpSocket (Me)
// TODO: translate error messages to be meaningful for the API consumer
// TODO: Drop std::string symbols and use errno code
// TODO: Align Sockets folder and namespace
void CheckErrors_recv(int errcode)
{
using error = SocketReceiveException;
if (errcode == EAGAIN || errcode == EWOULDBLOCK) throw error("The socket's file descriptor is marked O_NONBLOCK and no\n"
" data is waiting to be received; or MSG_OOB is set and no\n"
" out-of-band data is available and either the socket's file\n"
" descriptor is marked O_NONBLOCK or the socket does not\n"
" support blocking to await out-of-band data.");
if (errcode == EBADF) throw error("The socket argument is not a valid file descriptor.");
if (errcode == ECONNRESET) throw error("A connection was forcibly closed by a peer.");
if (errcode == EINTR) throw error("A signal interrupted recvfrom() before any data was available.");
if (errcode == EINVAL) throw error("The MSG_00B flag is set and no out-of-band data is available.");
if (errcode == ENOTCONN) throw error("A recieve is attempted on a connection-mode socket that is not connected.");
if (errcode == ENOTSOCK) throw error("The socket argument does not refer to a socket.");
void CheckErrors_recv(int errcode);
void CheckErrors_socket(int errcode);
void CheckErrors_accept(int errcode);
void CheckErrors_shutdown(int errcode);
void CheckErrors_close(int errcode);
void CheckErrors_bind(int errcode);
void CheckErrors_getsockname(int errcode);
void CheckErrors_connect(int errcode);
void CheckErrors_recvfrom(int errcode);
void CheckErrors_send(int errcode);
void CheckErrors_sendto(int errcode);
void CheckErrors_setsockopt(int errcode);
void CheckErrors_getaddrinfo(int errcode);
throw error(strerror(errcode));
}
void CheckErrors_socket(int errcode)
{
using error = SocketCreationException;
// This error list is not exhaustive, further errors may be generated by the underlying protocol modules.
if (errcode == EACCES) throw error("Permission to create a socket of the specified type and/or protocol is denied.");
if (errcode == EAFNOSUPPORT) throw error("The implementation does not support the specified address family.");
if (errcode == EINVAL) throw error("Unknown protocol, or protocol family not available.");
if (errcode == EMFILE) throw error("The per-process limit on the number of open file descriptors has been reached.");
if (errcode == ENFILE) throw error("The system-wide limit on the total number of open files has been reached.");
if (errcode == EPROTONOSUPPORT) throw error("The protocol type or the specified protocol is not supported within this domain.");
if (errcode == ENOBUFS || errcode == ENOMEM) throw error("Insufficient memory is available. The socket cannot be created until sufficient resources are freed.");
throw error(strerror(errcode));
}
void CheckErrors_accept(int errcode)
{
using error = SocketAcceptException;
if (errcode == EAGAIN ||
errcode == EWOULDBLOCK) throw error("The socket is marked nonblocking and no connections are present to be accepted. POSIX.1-2001 and POSIX.1-2008 allow either error to be returned for this case, and do not require these constants to have the same value, so a portable application should check for both possibilities.");
if (errcode == EBADF) throw error("sockfd is not an open file descriptor.");
if (errcode == ECONNABORTED) throw error("A connection has been aborted.");
if (errcode == EFAULT) throw error("The addr argument is not in a writable part of the user address space.");
if (errcode == EINTR) throw error("The system call was interrupted by a signal that was caught before a valid connection arrived; see signal(7).");
if (errcode == EINVAL) throw error("Socket is not listening for connections, or addrlen is invalid (e.g., is negative).");
if (errcode == EMFILE) throw error("The per-process limit on the number of open file descriptors has been reached.");
if (errcode == ENFILE) throw error("The system-wide limit on the total number of open files has been reached.");
if (errcode == ENOBUFS || errcode == ENOMEM) throw error("Not enough free memory. This often means that the memory\n"
"allocation is limited by the socket buffer limits, not by\n"
"the system memory."); // I RECOMMEND DOWNLOAD MORE RAM SIRS
if (errcode == ENOTSOCK) throw error("The file descriptor sockfd does not refer to a socket.");
if (errcode == EOPNOTSUPP) throw error("The referenced socket is not of type SOCK_STREAM.");
if (errcode == EPERM) throw error("Firewall rules forbid connection.");
if (errcode == EPROTO) throw error("Protocol error");
// In addition, network errors for the new socket and as defined for
// the protocol may be returned. Various Linux kernels can return
// other errors such as ENOSR, ESOCKTNOSUPPORT, EPROTONOSUPPORT,
// ETIMEDOUT. The value ERESTARTSYS may be seen during a trace.
throw error(strerror(errcode)); // No other error codes match, but something's still fucked up!
}
void CheckErrors_shutdown(int errcode)
{
using error = SocketCloseException;
// TODO: implement SocketShutdownException
if (errcode == EBADF) throw error("sockfd is not a valid file descriptor.");
if (errcode == EINVAL) throw error("An invalid value was specified in how (see bugs in manpage!!!)");
if (errcode == ENOTCONN) throw error("The specified socket is not connected.");
if (errcode == ENOTSOCK) throw error("The file descriptor sockfd does not refer to a socket.");
throw error(strerror(errcode)); // No other error codes match, but something's still fucked up!
}
void CheckErrors_close(int errcode)
{
using error = SocketCloseException;
if (errcode == EBADF) throw error("fd isn't a valid open file descriptor.");
if (errcode == EINTR) throw error("The close() call was interrupted by a signal; see signal(7)");
if (errcode == EIO) throw error("An I/O error occured.");
if (errcode == ENOSPC || errcode == EDQUOT) throw error("NFS Specific error, consult close() manpage");
throw error(strerror(errcode)); // No other error codes match, but something's still fucked up!
}
void CheckErrors_bind(int errcode)
{
using error = SocketBindingException;
if (errcode == EACCES) throw error("The address is protected, and the user is not the superuser.");
if (errcode == EADDRINUSE) throw error("The given address is already in use."); // Also See Internet Domain Sockets
if (errcode == EBADF) throw error("sockfd is not a valid file descriptor.");
if (errcode == EINVAL) throw error("The socket is already bound to an address.");
if (errcode == ENOTSOCK) throw error("The file descriptor sockfd does not refer to a socket.");
throw error(strerror(errcode)); // No other error codes match, but something's still fucked up!
}
void CheckErrors_getsockname(int errcode)
{
using error = SocketException;
if (errcode == EBADF) throw error("The argument sockfd is not a valid file descriptor.");
if (errcode == EFAULT) throw error("The addr argument points to memory not in a valid part of the process address space.");
if (errcode == EINVAL) throw error("addrlen is invalid (e.g., is negative");
if (errcode == ENOBUFS) throw error("Insufficient resources were available in the system to perform the operation.");
if (errcode == ENOTSOCK)throw error("The file descriptor sockfd does not refer to a socket.");
throw error(strerror(errcode)); // No other error codes match, but something's still fucked up!
}
void CheckErrors_connect(int errcode)
{
using error = SocketConnectException;
if (errcode == EACCES) throw error(" For UNIX domain sockets, which are identified by pathname:\n"
"Write permission is denied on the socket file, or search\n"
"permission is denied for one of the directories in the\n"
"path prefix"
" It can also be returned if an SELinux policy denied a\n"
"connection (for example, if there is a policy saying that\n"
"an HTTP proxy can only connect to ports associated with\n"
"HTTP servers, and the proxy tries to connect to a\n"
"different port).");
if (errcode == EPERM) throw error("The user tried to connect to a broadcast address without\n"
" having the socket broadcast flag enabled or the connection\n"
" request failed because of a local firewall rule.");
if (errcode == EADDRINUSE) throw error("Local address is already in use.");
if (errcode == EADDRNOTAVAIL) throw error("The socket referred to by sockfd\n"
" had not previously been bound to an address and, upon\n"
" attempting to bind it to an ephemeral port, it was\n"
" determined that all port numbers in the ephemeral port\n"
" range are currently in use.");
if (errcode == EAFNOSUPPORT) throw error("The passed address didn't have the correct address family in its sa_family field.");
if (errcode == EAGAIN) throw error("For nonblocking UNIX domain sockets, the socket is nonblocking, and the connection cannot be completed immediately. For other socket families, there are insufficient entries in the routing cache.");
if (errcode == EALREADY) throw error("The socket is nonblocking and a previous connection attempt has not yet been completed.");
if (errcode == EBADF) throw error("sockfd is not a valid open file descriptor");
if (errcode == ECONNREFUSED) throw error("A connect() on a stream socket found no one listening on the remote address.");
if (errcode == EFAULT) throw error("The socket structure address is outside the user's address space.");
if (errcode == EINPROGRESS) throw error("The socket is nonblocking and the connection cannot be completed immediately.");
if (errcode == EINTR) throw error("The system call was interrupted by a signal call that was caught.");
if (errcode == EISCONN) throw error("The socket is already connected.");
if (errcode == ENOTSOCK) throw error("The file descriptor sockfd does not refer to a socket.");
if (errcode == EPROTOTYPE) throw error("The socket type does not support the requested communications protocol. This error can occur, for example, on an attempt to connect a UNIX domain datagram socket to a stream socket.");
if (errcode == ETIMEDOUT) throw error("Timeout while attempting connection. The server may be too busy to accept new connections. Note that for IP sockets the timeout may be very long when syncookies are enabled on this server.");
throw error(strerror(errcode)); // No other error codes match, but something's still fucked up!
}
void CheckErrors_recvfrom(int errcode)
{
using error = SocketReceiveException;
if (errcode == EAGAIN || errcode == EWOULDBLOCK) throw error("The socket's file descriptor is marked O_NONBLOCK and no\n"
" data is waiting to be received; or MSG_OOB is set and no\n"
" out-of-band data is available and either the socket's file\n"
" descriptor is marked O_NONBLOCK or the socket does not\n"
" support blocking to await out-of-band data.");
if (errcode == EBADF) throw error("The socket argument is not a valid file descriptor.");
if (errcode == ECONNRESET) throw error("A connection was forcibly closed by a peer.");
if (errcode == EINTR) throw error("A signal interrupted recvfrom() before any data was available.");
if (errcode == EINVAL) throw error("The MSG_00B flag is set and no out-of-band data is available.");
if (errcode == ENOTCONN) throw error("A recieve is attempted on a connection-mode socket that is not connected.");
if (errcode == ENOTSOCK) throw error("The socket argument does not refer to a socket.");
if (errcode == EOPNOTSUPP) throw error("The specified flags are not supported for this socket type.");
if (errcode == ETIMEDOUT) throw error("The connection timed out during connection establishment, or due to a transmission timeout on active connection.");
if (errcode == EIO) throw error("An I/O error occurred while reading from or writing to the file system.");
if (errcode == ENOBUFS) throw error("Insufficient resources were available in the system to perform the operation.");
if (errcode == ENOMEM) throw error("Insufficient memory was available to fulfill the request.");
throw error(strerror(errcode)); // No other error codes match, but something's still fucked up!
}
void CheckErrors_send(int errcode)
{
// Checks for and raises any errors that can occur when attempting to call ::send on a generic socket.
using error = SocketSendException;
if (errcode == EACCES) throw error("An attempt was made to send a network/broadcast address as though it were a unicast address.");
if (errcode == EALREADY) throw error("Another Fast Open is in progress.");
if (errcode == EBADF) throw error("sockfd is not a valid open file descriptor.");
if (errcode == ECONNRESET) throw error("Connection reset by peer.");
if (errcode == EDESTADDRREQ) throw error("The socket is not in connection-mode, and no peer address is set.");
if (errcode == EFAULT) throw error("An invalid user space address was specified for an argument.");
if (errcode == EINTR) throw error("A signal occured before any data was transmitted; see signal(7).");
if (errcode == EINVAL) throw error("Invalid argument passed.");
if (errcode == EISCONN) throw error("The connection-mode socket was connected already but a recipient was specified. (Now either this error is returned, or the recipient specification is ignored.");
if (errcode == EMSGSIZE) throw error("The socket type requires that message be sent atomically, and the size of the message to be sent made this impossible.");
if (errcode == ENOBUFS) throw error("The output queue for a network interface was full. This generally indicates that the interface has stopped sending, but may be caused by transient congestion. (Normally, this does not occur in Linux. Packets are just silently dropped when a device queue overflows.)");
if (errcode == ENOMEM) throw error("No memory available.");
if (errcode == ENOTCONN) throw error("The socket is not connected, and no target has been given.");
if (errcode == ENOTSOCK) throw error("The file descriptor sockfd does not refer to a socket.");
if (errcode == EOPNOTSUPP) throw error("Some bit in the flags argument is inappropriate for the socket type.");
if (errcode == EPIPE) throw error("The local end has been shut down on a connection oriented socket. In this case, the process will also receive a SIGPIPE unless MSG_NOSIGNAL is set.");
if (errcode == EAGAIN ||
errcode == EWOULDBLOCK) throw error("The socket is marked nonblocking and the requested operation would block.");
throw error(strerror(errcode)); // No other error codes match, but something's still fucked up!
}
void CheckErrors_setsockopt(int errcode)
{
using error = SocketException;
if (errcode == EBADF) throw error("The socket argument is not a valid file descriptor.");
if (errcode == EDOM) throw error("The send and receive timeout values are too big to fit into the timeout fields in the socket structure.");
if (errcode == EINVAL) throw error("The specified option is invalid at the specified socket level or the socket has been shut down.");
if (errcode == EISCONN) throw error("The socket is already connected, and a specified option cannot be set while the socket is connected.");
if (errcode == ENOPROTOOPT) throw error("The option is not supported by the protocol");
if (errcode == ENOTSOCK) throw error("The socket argument does not refer to a socket.");
if (errcode == ENOMEM) throw error("There was insufficient memory available for the operation to complete.");
if (errcode == ENOBUFS) throw error("Insufficient resources are available in the system to complete the call.");
throw error(strerror(errcode)); // No other error codes match, but something's still fucked up!
}
void CheckErrors_getaddrinfo(int errcode)
{
using error = SocketException;
if (errcode == EAI_ADDRFAMILY) throw error("The specified network host does not have any network addresses in the requested address family.");
if (errcode == EAI_AGAIN) throw error("The name server returned a temporary failure indication. Try again later.");
if (errcode == EAI_BADFLAGS) throw error("hints.ai_flags contains invalid flags; or hints.ai_flags included AI_CANONNAME and name was NULL.");
if (errcode == EAI_FAIL) throw error("The name server returned a permanent failure indication.");
if (errcode == EAI_FAMILY) throw error("The requested address family is not supported.");
if (errcode == EAI_MEMORY) throw error("Out of memory.");
if (errcode == EAI_NODATA) throw error("The specified network host exists ,but does not have any network addresses defined.");
if (errcode == EAI_NONAME) throw error("The node or service is not known; or both node and service are NULL; or AI_NUMERICSERV was specified in hints.ai_flags and service was not a numeric port-number string.");
if (errcode == EAI_SERVICE) throw error("The requested service is not available for the requested socket type. It may be available through another socket type. For example, this error could occur if service was 'shell'.");
if (errcode == EAI_SOCKTYPE) throw error("The requested socket type is not supported. This could occur, for example, if hints.ai_socktype and hints.ai_protocol are inconsistent.");
if (errcode == EAI_SYSTEM) throw error("Other system error; errno is set to indicate the error");
}
}

263
src/Sockets/Sockets.cpp Normal file
View File

@@ -0,0 +1,263 @@
#include <Sockets/Sockets.hpp>
#include <Sockets/Exceptions.hpp>
#include <cstring>
namespace Socket
{
void CheckErrors_recv(int errcode) {
using error = SocketReceiveException;
if (errcode == EAGAIN || errcode == EWOULDBLOCK) throw error("The socket's file descriptor is marked O_NONBLOCK and no\n"
" data is waiting to be received; or MSG_OOB is set and no\n"
" out-of-band data is available and either the socket's file\n"
" descriptor is marked O_NONBLOCK or the socket does not\n"
" support blocking to await out-of-band data.");
if (errcode == EBADF) throw error("The socket argument is not a valid file descriptor.");
if (errcode == ECONNRESET) throw error("A connection was forcibly closed by a peer.");
if (errcode == EINTR) throw error("A signal interrupted recvfrom() before any data was available.");
if (errcode == EINVAL) throw error("The MSG_00B flag is set and no out-of-band data is available.");
if (errcode == ENOTCONN) throw error("A recieve is attempted on a connection-mode socket that is not connected.");
if (errcode == ENOTSOCK) throw error("The socket argument does not refer to a socket.");
throw error(strerror(errcode));
}
void CheckErrors_socket(int errcode) {
using error = SocketCreationException;
// This error list is not exhaustive, further errors may be generated by the underlying protocol modules.
if (errcode == EACCES) throw error("Permission to create a socket of the specified type and/or protocol is denied.");
if (errcode == EAFNOSUPPORT) throw error("The implementation does not support the specified address family.");
if (errcode == EINVAL) throw error("Unknown protocol, or protocol family not available.");
if (errcode == EMFILE) throw error("The per-process limit on the number of open file descriptors has been reached.");
if (errcode == ENFILE) throw error("The system-wide limit on the total number of open files has been reached.");
if (errcode == EPROTONOSUPPORT) throw error("The protocol type or the specified protocol is not supported within this domain.");
if (errcode == ENOBUFS || errcode == ENOMEM) throw error("Insufficient memory is available. The socket cannot be created until sufficient resources are freed.");
throw error(strerror(errcode));
}
void CheckErrors_accept(int errcode) {
using error = SocketAcceptException;
if (errcode == EAGAIN ||
errcode == EWOULDBLOCK) throw error("The socket is marked nonblocking and no connections are present to be accepted. POSIX.1-2001 and POSIX.1-2008 allow either error to be returned for this case, and do not require these constants to have the same value, so a portable application should check for both possibilities.");
if (errcode == EBADF) throw error("sockfd is not an open file descriptor.");
if (errcode == ECONNABORTED) throw error("A connection has been aborted.");
if (errcode == EFAULT) throw error("The addr argument is not in a writable part of the user address space.");
if (errcode == EINTR) throw error("The system call was interrupted by a signal that was caught before a valid connection arrived; see signal(7).");
if (errcode == EINVAL) throw error("Socket is not listening for connections, or addrlen is invalid (e.g., is negative).");
if (errcode == EMFILE) throw error("The per-process limit on the number of open file descriptors has been reached.");
if (errcode == ENFILE) throw error("The system-wide limit on the total number of open files has been reached.");
if (errcode == ENOBUFS || errcode == ENOMEM) throw error("Not enough free memory. This often means that the memory\n"
"allocation is limited by the socket buffer limits, not by\n"
"the system memory."); // I RECOMMEND DOWNLOAD MORE RAM SIRS
if (errcode == ENOTSOCK) throw error("The file descriptor sockfd does not refer to a socket.");
if (errcode == EOPNOTSUPP) throw error("The referenced socket is not of type SOCK_STREAM.");
if (errcode == EPERM) throw error("Firewall rules forbid connection.");
if (errcode == EPROTO) throw error("Protocol error");
// In addition, network errors for the new socket and as defined for
// the protocol may be returned. Various Linux kernels can return
// other errors such as ENOSR, ESOCKTNOSUPPORT, EPROTONOSUPPORT,
// ETIMEDOUT. The value ERESTARTSYS may be seen during a trace.
throw error(strerror(errcode)); // No other error codes match, but something's still fucked up!
}
void CheckErrors_shutdown(int errcode) {
using error = SocketCloseException;
// TODO: implement SocketShutdownException
if (errcode == EBADF) throw error("sockfd is not a valid file descriptor.");
if (errcode == EINVAL) throw error("An invalid value was specified in how (see bugs in manpage!!!)");
if (errcode == ENOTCONN) throw error("The specified socket is not connected.");
if (errcode == ENOTSOCK) throw error("The file descriptor sockfd does not refer to a socket.");
throw error(strerror(errcode)); // No other error codes match, but something's still fucked up!
}
void CheckErrors_close(int errcode) {
using error = SocketCloseException;
if (errcode == EBADF) throw error("fd isn't a valid open file descriptor.");
if (errcode == EINTR) throw error("The close() call was interrupted by a signal; see signal(7)");
if (errcode == EIO) throw error("An I/O error occured.");
if (errcode == ENOSPC || errcode == EDQUOT) throw error("NFS Specific error, consult close() manpage");
throw error(strerror(errcode)); // No other error codes match, but something's still fucked up!
}
void CheckErrors_bind(int errcode) {
using error = SocketBindingException;
if (errcode == EACCES) throw error("The address is protected, and the user is not the superuser.");
if (errcode == EADDRINUSE) throw error("The given address is already in use."); // Also See Internet Domain Sockets
if (errcode == EBADF) throw error("sockfd is not a valid file descriptor.");
if (errcode == EINVAL) throw error("The socket is already bound to an address.");
if (errcode == ENOTSOCK) throw error("The file descriptor sockfd does not refer to a socket.");
throw error(strerror(errcode)); // No other error codes match, but something's still fucked up!
}
void CheckErrors_getsockname(int errcode) {
using error = SocketException;
if (errcode == EBADF) throw error("The argument sockfd is not a valid file descriptor.");
if (errcode == EFAULT) throw error("The addr argument points to memory not in a valid part of the process address space.");
if (errcode == EINVAL) throw error("addrlen is invalid (e.g., is negative");
if (errcode == ENOBUFS) throw error("Insufficient resources were available in the system to perform the operation.");
if (errcode == ENOTSOCK) throw error("The file descriptor sockfd does not refer to a socket.");
throw error(strerror(errcode)); // No other error codes match, but something's still fucked up!
}
void CheckErrors_connect(int errcode) {
using error = SocketConnectException;
if (errcode == EACCES) throw error(" For UNIX domain sockets, which are identified by pathname:\n"
"Write permission is denied on the socket file, or search\n"
"permission is denied for one of the directories in the\n"
"path prefix"
" It can also be returned if an SELinux policy denied a\n"
"connection (for example, if there is a policy saying that\n"
"an HTTP proxy can only connect to ports associated with\n"
"HTTP servers, and the proxy tries to connect to a\n"
"different port).");
if (errcode == EPERM) throw error("The user tried to connect to a broadcast address without\n"
" having the socket broadcast flag enabled or the connection\n"
" request failed because of a local firewall rule.");
if (errcode == EADDRINUSE) throw error("Local address is already in use.");
if (errcode == EADDRNOTAVAIL) throw error("The socket referred to by sockfd\n"
" had not previously been bound to an address and, upon\n"
" attempting to bind it to an ephemeral port, it was\n"
" determined that all port numbers in the ephemeral port\n"
" range are currently in use.");
if (errcode == EAFNOSUPPORT) throw error("The passed address didn't have the correct address family in its sa_family field.");
if (errcode == EAGAIN) throw error("For nonblocking UNIX domain sockets, the socket is nonblocking, and the connection cannot be completed immediately. For other socket families, there are insufficient entries in the routing cache.");
if (errcode == EALREADY) throw error("The socket is nonblocking and a previous connection attempt has not yet been completed.");
if (errcode == EBADF) throw error("sockfd is not a valid open file descriptor");
if (errcode == ECONNREFUSED) throw error("A connect() on a stream socket found no one listening on the remote address.");
if (errcode == EFAULT) throw error("The socket structure address is outside the user's address space.");
if (errcode == EINPROGRESS) throw error("The socket is nonblocking and the connection cannot be completed immediately.");
if (errcode == EINTR) throw error("The system call was interrupted by a signal call that was caught.");
if (errcode == EISCONN) throw error("The socket is already connected.");
if (errcode == ENOTSOCK) throw error("The file descriptor sockfd does not refer to a socket.");
if (errcode == EPROTOTYPE) throw error("The socket type does not support the requested communications protocol. This error can occur, for example, on an attempt to connect a UNIX domain datagram socket to a stream socket.");
if (errcode == ETIMEDOUT) throw error("Timeout while attempting connection. The server may be too busy to accept new connections. Note that for IP sockets the timeout may be very long when syncookies are enabled on this server.");
throw error(strerror(errcode)); // No other error codes match, but something's still fucked up!
}
void CheckErrors_recvfrom(int errcode) {
using error = SocketReceiveException;
if (errcode == EAGAIN || errcode == EWOULDBLOCK) throw error("The socket's file descriptor is marked O_NONBLOCK and no\n"
" data is waiting to be received; or MSG_OOB is set and no\n"
" out-of-band data is available and either the socket's file\n"
" descriptor is marked O_NONBLOCK or the socket does not\n"
" support blocking to await out-of-band data.");
if (errcode == EBADF) throw error("The socket argument is not a valid file descriptor.");
if (errcode == ECONNRESET) throw error("A connection was forcibly closed by a peer.");
if (errcode == EINTR) throw error("A signal interrupted recvfrom() before any data was available.");
if (errcode == EINVAL) throw error("The MSG_00B flag is set and no out-of-band data is available.");
if (errcode == ENOTCONN) throw error("A recieve is attempted on a connection-mode socket that is not connected.");
if (errcode == ENOTSOCK) throw error("The socket argument does not refer to a socket.");
if (errcode == EOPNOTSUPP) throw error("The specified flags are not supported for this socket type.");
if (errcode == ETIMEDOUT) throw error("The connection timed out during connection establishment, or due to a transmission timeout on active connection.");
if (errcode == EIO) throw error("An I/O error occurred while reading from or writing to the file system.");
if (errcode == ENOBUFS) throw error("Insufficient resources were available in the system to perform the operation.");
if (errcode == ENOMEM) throw error("Insufficient memory was available to fulfill the request.");
throw error(strerror(errcode)); // No other error codes match, but something's still fucked up!
}
void CheckErrors_send(int errcode) {
// Checks for and raises any errors that can occur when attempting to call ::send on a generic socket.
using error = SocketSendException;
if (errcode == EACCES) throw error("An attempt was made to send a network/broadcast address as though it were a unicast address.");
if (errcode == EALREADY) throw error("Another Fast Open is in progress.");
if (errcode == EBADF) throw error("sockfd is not a valid open file descriptor.");
if (errcode == ECONNRESET) throw error("Connection reset by peer.");
if (errcode == EDESTADDRREQ) throw error("The socket is not in connection-mode, and no peer address is set.");
if (errcode == EFAULT) throw error("An invalid user space address was specified for an argument.");
if (errcode == EINTR) throw error("A signal occured before any data was transmitted; see signal(7).");
if (errcode == EINVAL) throw error("Invalid argument passed.");
if (errcode == EISCONN) throw error("The connection-mode socket was connected already but a recipient was specified. (Now either this error is returned, or the recipient specification is ignored.");
if (errcode == EMSGSIZE) throw error("The socket type requires that message be sent atomically, and the size of the message to be sent made this impossible.");
if (errcode == ENOBUFS) throw error("The output queue for a network interface was full. This generally indicates that the interface has stopped sending, but may be caused by transient congestion. (Normally, this does not occur in Linux. Packets are just silently dropped when a device queue overflows.)");
if (errcode == ENOMEM) throw error("No memory available.");
if (errcode == ENOTCONN) throw error("The socket is not connected, and no target has been given.");
if (errcode == ENOTSOCK) throw error("The file descriptor sockfd does not refer to a socket.");
if (errcode == EOPNOTSUPP) throw error("Some bit in the flags argument is inappropriate for the socket type.");
if (errcode == EPIPE) throw error("The local end has been shut down on a connection oriented socket. In this case, the process will also receive a SIGPIPE unless MSG_NOSIGNAL is set.");
if (errcode == EAGAIN ||
errcode == EWOULDBLOCK) throw error("The socket is marked nonblocking and the requested operation would block.");
throw error(strerror(errcode)); // No other error codes match, but something's still fucked up!
}
void CheckErrors_setsockopt(int errcode) {
using error = SocketException;
if (errcode == EBADF) throw error("The socket argument is not a valid file descriptor.");
if (errcode == EDOM) throw error("The send and receive timeout values are too big to fit into the timeout fields in the socket structure.");
if (errcode == EINVAL) throw error("The specified option is invalid at the specified socket level or the socket has been shut down.");
if (errcode == EISCONN) throw error("The socket is already connected, and a specified option cannot be set while the socket is connected.");
if (errcode == ENOPROTOOPT) throw error("The option is not supported by the protocol");
if (errcode == ENOTSOCK) throw error("The socket argument does not refer to a socket.");
if (errcode == ENOMEM) throw error("There was insufficient memory available for the operation to complete.");
if (errcode == ENOBUFS) throw error("Insufficient resources are available in the system to complete the call.");
throw error(strerror(errcode)); // No other error codes match, but something's still fucked up!
}
void CheckErrors_getaddrinfo(int errcode) {
using error = SocketException;
if (errcode == EAI_ADDRFAMILY) throw error("The specified network host does not have any network addresses in the requested address family.");
if (errcode == EAI_AGAIN) throw error("The name server returned a temporary failure indication. Try again later.");
if (errcode == EAI_BADFLAGS) throw error("hints.ai_flags contains invalid flags; or hints.ai_flags included AI_CANONNAME and name was NULL.");
if (errcode == EAI_FAIL) throw error("The name server returned a permanent failure indication.");
if (errcode == EAI_FAMILY) throw error("The requested address family is not supported.");
if (errcode == EAI_MEMORY) throw error("Out of memory.");
if (errcode == EAI_NODATA) throw error("The specified network host exists ,but does not have any network addresses defined.");
if (errcode == EAI_NONAME) throw error("The node or service is not known; or both node and service are NULL; or AI_NUMERICSERV was specified in hints.ai_flags and service was not a numeric port-number string.");
if (errcode == EAI_SERVICE) throw error("The requested service is not available for the requested socket type. It may be available through another socket type. For example, this error could occur if service was 'shell'.");
if (errcode == EAI_SOCKTYPE) throw error("The requested socket type is not supported. This could occur, for example, if hints.ai_socktype and hints.ai_protocol are inconsistent.");
if (errcode == EAI_SYSTEM) throw error("Other system error; errno is set to indicate the error");
}
void CheckErrors_sendto(int errcode) {
using error = SocketSendException;
if (errcode == EAFNOSUPPORT) throw error("Addresses in the specified address family cannot be used with this socket.");
if (errcode == EAGAIN ||
errcode == EWOULDBLOCK) throw error("The socket's file descriptor is marked O_NONBLOCK and the requested operation would block.");
if (errcode == EBADF) throw error("The socket argument is not a valid file descriptor.");
if (errcode == ECONNRESET) throw error("A connection was forcibly closed by a peer.");
if (errcode == EINTR) throw error("A signal interrupted sendto() before any data was transmitted.");
if (errcode == EMSGSIZE) throw error("The message is too large to be sent all at once, as the socket requires.");
if (errcode == ENOTCONN) throw error("The socket is connection-mode but is not connected.");
if (errcode == ENOTSOCK) throw error("The socket argument does not refer to a socket.");
if (errcode == EOPNOTSUPP) throw error("The socket argument is associated with a socket that does not support one or more of the values set in flags.");
if (errcode == EPIPE) throw error("The socket is shut down for writing, or the socket is connection-mode and is no longer connected. In the latter case, and if the socket is of type SOCK_STREAM or SOCK_SEQPACKET and the MSG_NOSIGNAL flag is not set, the SIGPIPE signal is generated to the calling thread.");
if (errcode == EIO) throw error("An I/O error occurred while reading from or writing to the file system.");
if (errcode == ELOOP) throw error("A loop exists in symbolic links encountered during resolution of the pathname in the socket address.");
if (errcode == ENAMETOOLONG) throw error("The length of a component of a pathname is longer than {NAME_MAX}.");
if (errcode == ENOENT) throw error("A component of the pathname doesnot name an existing file or the pathname is an empty string.");
if (errcode == ENOTDIR) throw error("A component of the path prefix of the hostname in the socket address names an existing file that is neither a directory nor a symbolic link to a directory, or the pathname in the socket address contains at least one non-<slash> character and ends with one or more trailing <slash> characters and the last pathname component names an existing file that is neither a directory nor a symbolic link to a directory.");
if (errcode == EACCES) throw error("Search permission is denied for a component of the path prefix; or write access to the named socket is denied.");
if (errcode == EDESTADDRREQ) throw error("The socket is not connection-mode and does not have its peer address set, and no destination address was specified.");
if (errcode == EHOSTUNREACH) throw error("The destination host cannot be reached (probably because the host is down or a remote router cannot reach it).");
if (errcode == EINVAL) throw error("The dest_len argument is not a valid length for the address family.");
if (errcode == EISCONN) throw error("A destination address was specified and the socket is already connected.");
if (errcode == ENETDOWN) throw error("The local network interface used to reach the destination is down.");
if (errcode == ENETUNREACH) throw error("No route to the network is present.");
if (errcode == ENOBUFS) throw error("Insufficient resources were available in the system to perform the operation.");
if (errcode == ENOMEM) throw error("Insufficient memory was available to fulfill the request.");
if (errcode == ELOOP) throw error("More than {SYMLOOP_MAX} symbolic links were encountered during resolution of the pathname in the socket address.");
if (errcode == ENAMETOOLONG) throw error("The length of a pathname exceeds {PATH_MAX}, or pathname resolution of a symbolic link produced an intermediate result with a length that exceeds {PATH_MAX}.");
throw error(strerror(errcode)); // No other error codes match, but something's still fucked up!
}
}