diff --git a/scripts/generate-error-types.tcl b/scripts/generate-error-types.tcl new file mode 100755 index 000000000..15c8c0fa2 --- /dev/null +++ b/scripts/generate-error-types.tcl @@ -0,0 +1,253 @@ +#!/usr/bin/tclsh +#* +#* SRT - Secure, Reliable, Transport +#* Copyright (c) 2020 Haivision Systems Inc. +#* +#* This Source Code Form is subject to the terms of the Mozilla Public +#* License, v. 2.0. If a copy of the MPL was not distributed with this +#* file, You can obtain one at http://mozilla.org/MPL/2.0/. +#* +#*/ +# +#***************************************************************************** +#written by +# Haivision Systems Inc. +#***************************************************************************** + +set code_major { + UNKNOWN -1 + SUCCESS 0 + SETUP 1 + CONNECTION 2 + SYSTEMRES 3 + FILESYSTEM 4 + NOTSUP 5 + AGAIN 6 + PEERERROR 7 +} + +set code_minor { + NONE 0 + TIMEOUT 1 + REJECTED 2 + NORES 3 + SECURITY 4 + CLOSED 5 + + + CONNLOST 1 + NOCONN 2 + + THREAD 1 + MEMORY 2 + OBJECT 3 + + SEEKGFAIL 1 + READFAIL 2 + SEEKPFAIL 3 + WRITEFAIL 4 + + ISBOUND 1 + ISCONNECTED 2 + INVAL 3 + SIDINVAL 4 + ISUNBOUND 5 + NOLISTEN 6 + ISRENDEZVOUS 7 + ISRENDUNBOUND 8 + INVALMSGAPI 9 + INVALBUFFERAPI 10 + BUSY 11 + XSIZE 12 + EIDINVAL 13 + EEMPTY 14 + + WRAVAIL 1 + RDAVAIL 2 + XMTIMEOUT 3 + CONGESTION 4 +} + + +set errortypes { + + SUCCESS "Success" { + NONE "" + } + + SETUP "Connection setup failure" { + NONE "" + TIMEOUT "connection timed out" + REJECTED "connection rejected" + NORES "unable to create/configure SRT socket" + SECURITY "aborted for security reasons" + CLOSED "socket closed during operation" + } + + CONNECTION "" { + NONE "" + CONNLOST "Connection was broken" + NOCONN "Connection does not exist" + } + + SYSTEMRES "System resource failure" { + NONE "" + THREAD "unable to create new threads" + MEMORY "unable to allocate buffers" + OBJECT "unable to allocate a system object" + } + + FILESYSTEM "File system failure" { + NONE "" + SEEKGFAIL "cannot seek read position" + READFAIL "failure in read" + SEEKPFAIL "cannot seek write position" + WRITEFAIL "failure in write" + } + + NOTSUP "Operation not supported" { + NONE "" + ISBOUND "Cannot do this operation on a BOUND socket" + ISCONNECTED "Cannot do this operation on a CONNECTED socket" + INVAL "Bad parameters" + SIDINVAL "Invalid socket ID" + ISUNBOUND "Cannot do this operation on an UNBOUND socket" + NOLISTEN "Socket is not in listening state" + ISRENDEZVOUS "Listen/accept is not supported in rendezous connection setup" + ISRENDUNBOUND "Cannot call connect on UNBOUND socket in rendezvous connection setup" + INVALMSGAPI "Incorrect use of Message API (sendmsg/recvmsg)." + INVALBUFFERAPI "Incorrect use of Buffer API (send/recv) or File API (sendfile/recvfile)." + BUSY "Another socket is already listening on the same port" + XSIZE "Message is too large to send (it must be less than the SRT send buffer size)" + EIDINVAL "Invalid epoll ID" + EEMPTY "All sockets removed from epoll, waiting would deadlock" + + } + + AGAIN "Non-blocking call failure" { + NONE "" + WRAVAIL "no buffer available for sending" + RDAVAIL "no data available for reading" + XMTIMEOUT "transmission timed out" + CONGESTION "early congestion notification" + } + + PEERERROR "The peer side has signaled an error" { + NONE "" + } + +} + +set main_array_item { +const char** strerror_array_major [] = { +$minor_array_list +}; + +} + +set major_size_item { +size_t strerror_array_sizes [] = { +$minor_array_sizes +}; +} + +set minor_array_item { +const char* strerror_msgs_$majorlc [] = { +$minor_message_items +}; + +} + +set strerror_function { + +const char* strerror_get_message(size_t major, size_t minor) +{ + static const char* const undefined = "UNDEFINED ERROR"; + + // Extract the major array + if (major >= sizeof(strerror_array_major)/sizeof(const char**)) + { + return undefined; + } + + const char** array = strerror_array_major[major]; + size_t size = strerror_array_sizes[major]; + + if (minor >= size) + { + return undefined; + } + + return array[minor]; +} + +} + +set globalheader { + /* + WARNING: Generated from ../scripts/generate-error-types.tcl + + DO NOT MODIFY. + + Copyright applies as per the generator script. + */ + +#include + +} + +proc Generate:imp {} { + + puts $::globalheader + + puts "namespace srt\n\{" + + # Generate major array + set majitem 0 + set minor_array_sizes "" + foreach {mt mm cont} $::errortypes { + + puts "// MJ_$mt '$mm'" + + # Generate minor array + set majorlc [string tolower $mt] + set minor_message_items "" + set minitem 0 + foreach {mnt mnm} $cont { + if {$mm == ""} { + set msg $mnm + } elseif {$mnm == ""} { + set msg $mm + } else { + set msg "$mm: $mnm" + } + append minor_message_items " \"$msg\", // MN_$mnt = $minitem\n" + incr minitem + } + append minor_message_items " \"\"" + puts [subst -nobackslashes -nocommands $::minor_array_item] + + append minor_array_list " strerror_msgs_$majorlc, // MJ_$mt = $majitem\n" + append minor_array_sizes " [expr {$minitem}],\n" + incr majitem + } + append minor_array_list " NULL\n" + append minor_array_sizes " 0\n" + + puts [subst -nobackslashes -nocommands $::main_array_item] + puts [subst -nobackslashes -nocommands $::major_size_item] + + puts "" + puts $::strerror_function + + puts "\} // namespace srt" +} + + +set defmode imp +if {[lindex $argv 0] != ""} { + set defmode [lindex $argv 0] +} + +Generate:$defmode + diff --git a/srtcore/common.cpp b/srtcore/common.cpp index 52c19dbfe..8a48a62cb 100644 --- a/srtcore/common.cpp +++ b/srtcore/common.cpp @@ -88,230 +88,18 @@ m_iMinor(minor) m_iErrno = err; } +namespace srt { +const char* strerror_get_message(size_t major, size_t minor); +} + const char* CUDTException::getErrorMessage() const ATR_NOTHROW { - return getErrorString().c_str(); + return srt::strerror_get_message(m_iMajor, m_iMinor); } -const string& CUDTException::getErrorString() const +string CUDTException::getErrorString() const { - // translate "Major:Minor" code into text message. - - switch (m_iMajor) - { - case MJ_SUCCESS: - m_strMsg = "Success"; - break; - - case MJ_SETUP: - m_strMsg = "Connection setup failure"; - - switch (m_iMinor) - { - case MN_TIMEOUT: - m_strMsg += ": connection time out"; - break; - - case MN_REJECTED: - m_strMsg += ": connection rejected"; - break; - - case MN_NORES: - m_strMsg += ": unable to create/configure SRT socket"; - break; - - case MN_SECURITY: - m_strMsg += ": abort for security reasons"; - break; - - case MN_CLOSED: - m_strMsg += ": socket closed during operation"; - break; - - default: - break; - } - - break; - - case MJ_CONNECTION: - switch (m_iMinor) - { - case MN_CONNLOST: - m_strMsg = "Connection was broken"; - break; - - case MN_NOCONN: - m_strMsg = "Connection does not exist"; - break; - - default: - break; - } - - break; - - case MJ_SYSTEMRES: - m_strMsg = "System resource failure"; - - switch (m_iMinor) - { - case MN_THREAD: - m_strMsg += ": unable to create new threads"; - break; - - case MN_MEMORY: - m_strMsg += ": unable to allocate buffers"; - break; - - - case MN_OBJECT: - m_strMsg += ": unable to allocate system object"; - break; - - default: - break; - } - - break; - - case MJ_FILESYSTEM: - m_strMsg = "File system failure"; - - switch (m_iMinor) - { - case MN_SEEKGFAIL: - m_strMsg += ": cannot seek read position"; - break; - - case MN_READFAIL: - m_strMsg += ": failure in read"; - break; - - case MN_SEEKPFAIL: - m_strMsg += ": cannot seek write position"; - break; - - case MN_WRITEFAIL: - m_strMsg += ": failure in write"; - break; - - default: - break; - } - - break; - - case MJ_NOTSUP: - m_strMsg = "Operation not supported"; - - switch (m_iMinor) - { - case MN_ISBOUND: - m_strMsg += ": Cannot do this operation on a BOUND socket"; - break; - - case MN_ISCONNECTED: - m_strMsg += ": Cannot do this operation on a CONNECTED socket"; - break; - - case MN_INVAL: - m_strMsg += ": Bad parameters"; - break; - - case MN_SIDINVAL: - m_strMsg += ": Invalid socket ID"; - break; - - case MN_ISUNBOUND: - m_strMsg += ": Cannot do this operation on an UNBOUND socket"; - break; - - case MN_NOLISTEN: - m_strMsg += ": Socket is not in listening state"; - break; - - case MN_ISRENDEZVOUS: - m_strMsg += ": Listen/accept is not supported in rendezous connection setup"; - break; - - case MN_ISRENDUNBOUND: - m_strMsg += ": Cannot call connect on UNBOUND socket in rendezvous connection setup"; - break; - - case MN_INVALMSGAPI: - m_strMsg += ": Incorrect use of Message API (sendmsg/recvmsg)."; - break; - - case MN_INVALBUFFERAPI: - m_strMsg += ": Incorrect use of Buffer API (send/recv) or File API (sendfile/recvfile)."; - break; - - case MN_BUSY: - m_strMsg += ": Another socket is already listening on the same port"; - break; - - case MN_XSIZE: - m_strMsg += ": Message is too large to send (it must be less than the SRT send buffer size)"; - break; - - case MN_EIDINVAL: - m_strMsg += ": Invalid epoll ID"; - break; - - case MN_EEMPTY: - m_strMsg += ": All sockets removed from epoll, waiting would deadlock"; - - default: - break; - } - - break; - - case MJ_AGAIN: - m_strMsg = "Non-blocking call failure"; - - switch (m_iMinor) - { - case MN_WRAVAIL: - m_strMsg += ": no buffer available for sending"; - break; - - case MN_RDAVAIL: - m_strMsg += ": no data available for reading"; - break; - - case MN_XMTIMEOUT: - m_strMsg += ": transmission timed out"; - break; - -#ifdef SRT_ENABLE_ECN - case MN_CONGESTION: - m_strMsg += ": early congestion notification"; - break; -#endif /* SRT_ENABLE_ECN */ - default: - break; - } - - break; - - case MJ_PEERERROR: - m_strMsg = "The peer side has signalled an error"; - - break; - - default: - m_strMsg = "Unknown error"; - } - - // Adding "errno" information - if ((MJ_SUCCESS != m_iMajor) && (0 < m_iErrno)) - { - m_strMsg += ": " + SysStrError(m_iErrno); - } - - return m_strMsg; + return getErrorMessage(); } #define UDT_XCODE(mj, mn) (int(mj)*1000)+int(mn) diff --git a/srtcore/common.h b/srtcore/common.h index f5d042f09..1386546e8 100644 --- a/srtcore/common.h +++ b/srtcore/common.h @@ -110,7 +110,7 @@ class CUDTException: public std::exception return getErrorMessage(); } - const std::string& getErrorString() const; + std::string getErrorString() const; /// Get the system errno for the exception. /// @return errno. diff --git a/srtcore/filelist.maf b/srtcore/filelist.maf index 74759f515..e6116cbb5 100644 --- a/srtcore/filelist.maf +++ b/srtcore/filelist.maf @@ -22,6 +22,7 @@ congctl.cpp srt_c_api.cpp window.cpp srt_compat.c +strerror_defs.cpp sync.cpp SOURCES - ENABLE_EXPERIMENTAL_BONDING diff --git a/srtcore/strerror_defs.cpp b/srtcore/strerror_defs.cpp new file mode 100644 index 000000000..ee32527bf --- /dev/null +++ b/srtcore/strerror_defs.cpp @@ -0,0 +1,165 @@ + + /* + WARNING: Generated from ../scripts/generate-error-types.tcl + + DO NOT MODIFY. + + Copyright applies as per the generator script. + */ + +#include + + +namespace srt +{ +// MJ_SUCCESS 'Success' + +const char* strerror_msgs_success [] = { + "Success", // MN_NONE = 0 + "" +}; + + +// MJ_SETUP 'Connection setup failure' + +const char* strerror_msgs_setup [] = { + "Connection setup failure", // MN_NONE = 0 + "Connection setup failure: connection timed out", // MN_TIMEOUT = 1 + "Connection setup failure: connection rejected", // MN_REJECTED = 2 + "Connection setup failure: unable to create/configure SRT socket", // MN_NORES = 3 + "Connection setup failure: aborted for security reasons", // MN_SECURITY = 4 + "Connection setup failure: socket closed during operation", // MN_CLOSED = 5 + "" +}; + + +// MJ_CONNECTION '' + +const char* strerror_msgs_connection [] = { + "", // MN_NONE = 0 + "Connection was broken", // MN_CONNLOST = 1 + "Connection does not exist", // MN_NOCONN = 2 + "" +}; + + +// MJ_SYSTEMRES 'System resource failure' + +const char* strerror_msgs_systemres [] = { + "System resource failure", // MN_NONE = 0 + "System resource failure: unable to create new threads", // MN_THREAD = 1 + "System resource failure: unable to allocate buffers", // MN_MEMORY = 2 + "System resource failure: unable to allocate a system object", // MN_OBJECT = 3 + "" +}; + + +// MJ_FILESYSTEM 'File system failure' + +const char* strerror_msgs_filesystem [] = { + "File system failure", // MN_NONE = 0 + "File system failure: cannot seek read position", // MN_SEEKGFAIL = 1 + "File system failure: failure in read", // MN_READFAIL = 2 + "File system failure: cannot seek write position", // MN_SEEKPFAIL = 3 + "File system failure: failure in write", // MN_WRITEFAIL = 4 + "" +}; + + +// MJ_NOTSUP 'Operation not supported' + +const char* strerror_msgs_notsup [] = { + "Operation not supported", // MN_NONE = 0 + "Operation not supported: Cannot do this operation on a BOUND socket", // MN_ISBOUND = 1 + "Operation not supported: Cannot do this operation on a CONNECTED socket", // MN_ISCONNECTED = 2 + "Operation not supported: Bad parameters", // MN_INVAL = 3 + "Operation not supported: Invalid socket ID", // MN_SIDINVAL = 4 + "Operation not supported: Cannot do this operation on an UNBOUND socket", // MN_ISUNBOUND = 5 + "Operation not supported: Socket is not in listening state", // MN_NOLISTEN = 6 + "Operation not supported: Listen/accept is not supported in rendezous connection setup", // MN_ISRENDEZVOUS = 7 + "Operation not supported: Cannot call connect on UNBOUND socket in rendezvous connection setup", // MN_ISRENDUNBOUND = 8 + "Operation not supported: Incorrect use of Message API (sendmsg/recvmsg).", // MN_INVALMSGAPI = 9 + "Operation not supported: Incorrect use of Buffer API (send/recv) or File API (sendfile/recvfile).", // MN_INVALBUFFERAPI = 10 + "Operation not supported: Another socket is already listening on the same port", // MN_BUSY = 11 + "Operation not supported: Message is too large to send (it must be less than the SRT send buffer size)", // MN_XSIZE = 12 + "Operation not supported: Invalid epoll ID", // MN_EIDINVAL = 13 + "Operation not supported: All sockets removed from epoll, waiting would deadlock", // MN_EEMPTY = 14 + "" +}; + + +// MJ_AGAIN 'Non-blocking call failure' + +const char* strerror_msgs_again [] = { + "Non-blocking call failure", // MN_NONE = 0 + "Non-blocking call failure: no buffer available for sending", // MN_WRAVAIL = 1 + "Non-blocking call failure: no data available for reading", // MN_RDAVAIL = 2 + "Non-blocking call failure: transmission timed out", // MN_XMTIMEOUT = 3 + "Non-blocking call failure: early congestion notification", // MN_CONGESTION = 4 + "" +}; + + +// MJ_PEERERROR 'The peer side has signaled an error' + +const char* strerror_msgs_peererror [] = { + "The peer side has signaled an error", // MN_NONE = 0 + "" +}; + + + +const char** strerror_array_major [] = { + strerror_msgs_success, // MJ_SUCCESS = 0 + strerror_msgs_setup, // MJ_SETUP = 1 + strerror_msgs_connection, // MJ_CONNECTION = 2 + strerror_msgs_systemres, // MJ_SYSTEMRES = 3 + strerror_msgs_filesystem, // MJ_FILESYSTEM = 4 + strerror_msgs_notsup, // MJ_NOTSUP = 5 + strerror_msgs_again, // MJ_AGAIN = 6 + strerror_msgs_peererror, // MJ_PEERERROR = 7 + NULL + +}; + + + +size_t strerror_array_sizes [] = { + 1, + 6, + 3, + 4, + 5, + 15, + 5, + 1, + 0 + +}; + + + + +const char* strerror_get_message(size_t major, size_t minor) +{ + static const char* const undefined = "UNDEFINED ERROR"; + + // Extract the major array + if (major >= sizeof(strerror_array_major)/sizeof(const char**)) + { + return undefined; + } + + const char** array = strerror_array_major[major]; + size_t size = strerror_array_sizes[major]; + + if (minor >= size) + { + return undefined; + } + + return array[minor]; +} + + +} // namespace srt