Implement Socket Error Handling
This commit is contained in:
@@ -3,94 +3,112 @@
|
||||
|
||||
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
|
||||
|
||||
void CheckErrors_socket(const std::string& errcode)
|
||||
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.");
|
||||
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(errcode);
|
||||
throw error(strerror(errcode));
|
||||
}
|
||||
|
||||
void CheckErrors_accept(const std::string& 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"
|
||||
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");
|
||||
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(errcode); // No other error codes match, but something's still fucked up!
|
||||
throw error(strerror(errcode)); // No other error codes match, but something's still fucked up!
|
||||
}
|
||||
|
||||
|
||||
void CheckErrors_shutdown(const std::string& errcode)
|
||||
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.");
|
||||
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(errcode); // No other error codes match, but something's still fucked up!
|
||||
throw error(strerror(errcode)); // No other error codes match, but something's still fucked up!
|
||||
}
|
||||
|
||||
void CheckErrors_close(const std::string& errcode)
|
||||
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");
|
||||
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(errcode); // No other error codes match, but something's still fucked up!
|
||||
throw error(strerror(errcode)); // No other error codes match, but something's still fucked up!
|
||||
}
|
||||
|
||||
void CheckErrors_bind(const std::string& errcode)
|
||||
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.");
|
||||
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(errcode); // No other error codes match, but something's still fucked up!
|
||||
throw error(strerror(errcode)); // No other error codes match, but something's still fucked up!
|
||||
}
|
||||
|
||||
void CheckErrors_getsockname(const std::string& errcode)
|
||||
@@ -209,4 +227,9 @@ namespace Socket {
|
||||
|
||||
throw error(errcode); // No other error codes match, but something's still fucked up!
|
||||
}
|
||||
|
||||
void CheckErrors_getaddrinfo(const std::string& errcode)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user