From 0e21f730d45cd6cec17b25062981ff4ac63de9f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Ma=C5=82ecki?= Date: Tue, 4 Jun 2019 12:53:31 +0200 Subject: [PATCH 1/8] Implemented. Changed the code reported as handshake failure. --- srtcore/api.cpp | 23 +++++- srtcore/api.h | 3 +- srtcore/common.cpp | 27 +++++++ srtcore/core.cpp | 161 ++++++++++++++++++++++++++++++++---------- srtcore/core.h | 4 +- srtcore/handshake.cpp | 31 +++++++- srtcore/handshake.h | 32 ++++++++- srtcore/queue.cpp | 36 ++++------ srtcore/srt.h | 27 +++++++ srtcore/srt_c_api.cpp | 4 ++ testing/testmedia.cpp | 12 +++- testing/testmedia.hpp | 2 +- 12 files changed, 290 insertions(+), 72 deletions(-) diff --git a/srtcore/api.cpp b/srtcore/api.cpp index 87706beb6..e1efddad0 100644 --- a/srtcore/api.cpp +++ b/srtcore/api.cpp @@ -329,10 +329,13 @@ SRTSOCKET CUDTUnited::newSocket(int af, int) return ns->m_SocketID; } -int CUDTUnited::newConnection(const SRTSOCKET listen, const sockaddr* peer, CHandShake* hs, const CPacket& hspkt) +int CUDTUnited::newConnection(const SRTSOCKET listen, const sockaddr* peer, CHandShake* hs, const CPacket& hspkt, + ref_t r_error) { CUDTSocket* ns = NULL; + *r_error = SRT_REJ_IPE; + // Can't manage this error through an exception because this is // running in the listener loop. CUDTSocket* ls = locate(listen); @@ -376,6 +379,7 @@ int CUDTUnited::newConnection(const SRTSOCKET listen, const sockaddr* peer, CHan // exceeding backlog, refuse the connection request if (ls->m_pQueuedSockets->size() >= ls->m_uiBackLog) { + *r_error = SRT_REJ_BACKLOG; LOGC(mglog.Error, log << "newConnection: listen backlog=" << ls->m_uiBackLog << " EXCEEDED"); return -1; } @@ -401,6 +405,7 @@ int CUDTUnited::newConnection(const SRTSOCKET listen, const sockaddr* peer, CHan } catch (...) { + *r_error = SRT_REJ_RESOURCE; delete ns; LOGC(mglog.Error, log << "IPE: newConnection: unexpected exception (probably std::bad_alloc)"); return -1; @@ -419,6 +424,10 @@ int CUDTUnited::newConnection(const SRTSOCKET listen, const sockaddr* peer, CHan int error = 0; + // Set the error code for all prospective problems below. + // It won't be interpreted when result was successful. + *r_error = SRT_REJ_RESOURCE; + // These can throw exception only when the memory allocation failed. // CUDT::connect() translates exception into CUDTException. // CUDT::open() may only throw original std::bad_alloc from new. @@ -491,7 +500,12 @@ int CUDTUnited::newConnection(const SRTSOCKET listen, const sockaddr* peer, CHan if (error > 0) { #if ENABLE_LOGGING - static const char* why [] = {"?", "ACCEPT ERROR", "IPE when mapping a socket", "IPE when inserting a socket" }; + static const char* why [] = { + "UNKNOWN ERROR", + "SYSTEM RESOURCE ERROR", + "IPE when mapping a socket", + "IPE when inserting a socket" + }; LOGC(mglog.Error, log << CONID(ns->m_SocketID) << "newConnection: connection rejected due to: " << why[error]); #endif SRTSOCKET id = ns->m_SocketID; @@ -3156,4 +3170,9 @@ SRT_API std::string getstreamid(SRTSOCKET u) return CUDT::getstreamid(u); } +SRT_REJECT_REASON getrejectreason(SRTSOCKET u) +{ + return CUDT::rejectReason(u); +} + } // namespace UDT diff --git a/srtcore/api.h b/srtcore/api.h index 328abdb22..52dc2e5aa 100644 --- a/srtcore/api.h +++ b/srtcore/api.h @@ -153,7 +153,8 @@ friend class CRendezvousQueue; /// @param [in,out] hs handshake information from peer side (in), negotiated value (out); /// @return If the new connection is successfully created: 1 success, 0 already exist, -1 error. - int newConnection(const SRTSOCKET listen, const sockaddr* peer, CHandShake* hs, const CPacket& hspkt); + int newConnection(const SRTSOCKET listen, const sockaddr* peer, CHandShake* hs, const CPacket& hspkt, + ref_t r_error); /// look up the UDT entity according to its ID. /// @param [in] u the UDT socket ID. diff --git a/srtcore/common.cpp b/srtcore/common.cpp index 67d132ad1..d21288806 100644 --- a/srtcore/common.cpp +++ b/srtcore/common.cpp @@ -839,6 +839,33 @@ std::string TransmissionEventStr(ETransmissionEvent ev) return vals[ev]; } +const char* srt_rejectreason_msg [] = { + "Unknown or erroneous", + "Error in system calls", + "Peer rejected connection", + "Resource allocation failure", + "Rogue peer or incorrect parameters", + "Listener's backlog exceeded", + "Internal Program Error", + "Socket is being closed", + "Peer version too old", + "Rendezvous-mode cookie collision", + "Incorrect passphrase", + "Strictly-encrypted condition not met", + "MessageAPI/StreamAPI collision", + "Congestion controller type collision", + "Packet Filter type collision" +}; + +const char* srt_rejectreason_str(SRT_REJECT_REASON rid) +{ + int id = rid & ~SRT_REJ_PEERREP; // disregard peer reported + static const size_t ra_size = Size(srt_rejectreason_msg); + if (size_t(id) >= ra_size) + return srt_rejectreason_msg[0]; + return srt_rejectreason_msg[id]; +} + // Some logging imps #if ENABLE_LOGGING diff --git a/srtcore/core.cpp b/srtcore/core.cpp index 6ffd39e59..c44e7b707 100644 --- a/srtcore/core.cpp +++ b/srtcore/core.cpp @@ -196,6 +196,7 @@ void CUDT::construct() m_bShutdown = false; m_bBroken = false; m_bPeerHealth = true; + m_RejectReason = SRT_REJ_UNKNOWN; m_ullLingerExpiration = 0; m_llLastReqTime = 0; @@ -1694,6 +1695,7 @@ bool CUDT::createSrtHandshake(ref_t r_pkt, ref_t r_hs, // Sanity check, applies to HSv5 only cases. if (srths_cmd == SRT_CMD_HSREQ && m_SrtHsSide == HSD_RESPONDER) { + m_RejectReason = SRT_REJ_IPE; LOGC(mglog.Fatal, log << "IPE: SRT_CMD_HSREQ was requested to be sent in HSv5 by an INITIATOR side!"); return false; // should cause rejection } @@ -1784,6 +1786,7 @@ bool CUDT::createSrtHandshake(ref_t r_pkt, ref_t r_hs, if ( m_sStreamName.size() >= size_limit ) { + m_RejectReason = SRT_REJ_ROGUE; LOGC(mglog.Error, log << "createSrtHandshake: stream id too long, limited to " << (size_limit-1) << " bytes"); return false; } @@ -1878,6 +1881,7 @@ bool CUDT::createSrtHandshake(ref_t r_pkt, ref_t r_hs, if ( !have_any_keys ) { + m_RejectReason = SRT_REJ_IPE; LOGC(mglog.Error, log << "createSrtHandshake: IPE: all keys have expired, no KM to send."); return false; } @@ -1905,6 +1909,7 @@ bool CUDT::createSrtHandshake(ref_t r_pkt, ref_t r_hs, { if (!kmdata) { + m_RejectReason = SRT_REJ_IPE; LOGC(mglog.Fatal, log << "createSrtHandshake: IPE: srtkm_cmd=SRT_CMD_KMRSP and no kmdata!"); return false; } @@ -1921,6 +1926,7 @@ bool CUDT::createSrtHandshake(ref_t r_pkt, ref_t r_hs, } else { + m_RejectReason = SRT_REJ_IPE; LOGC(mglog.Fatal, log << "createSrtHandshake: IPE: wrong value of srtkm_cmd: " << srtkm_cmd); return false; } @@ -2101,6 +2107,7 @@ int CUDT::processSrtMsg_HSREQ(const uint32_t* srtdata, size_t len, uint32_t ts, if (len < SRT_CMD_HSREQ_MINSZ) { + m_RejectReason = SRT_REJ_ROGUE; /* Packet smaller than minimum compatible packet size */ LOGF(mglog.Error, "HSREQ/rcv: cmd=%d(HSREQ) len=%" PRIzu " invalid", SRT_CMD_HSREQ, len); return SRT_CMD_NONE; @@ -2117,6 +2124,7 @@ int CUDT::processSrtMsg_HSREQ(const uint32_t* srtdata, size_t len, uint32_t ts, { if ( m_lPeerSrtVersion >= SRT_VERSION_FEAT_HSv5 ) { + m_RejectReason = SRT_REJ_ROGUE; LOGC(mglog.Error, log << "HSREQ/rcv: With HSv4 version >= " << SrtVersionString(SRT_VERSION_FEAT_HSv5) << " is not acceptable."); return SRT_CMD_REJECT; @@ -2126,6 +2134,7 @@ int CUDT::processSrtMsg_HSREQ(const uint32_t* srtdata, size_t len, uint32_t ts, { if ( m_lPeerSrtVersion < SRT_VERSION_FEAT_HSv5 ) { + m_RejectReason = SRT_REJ_ROGUE; LOGC(mglog.Error, log << "HSREQ/rcv: With HSv5 version must be >= " << SrtVersionString(SRT_VERSION_FEAT_HSv5) << " ."); return SRT_CMD_REJECT; @@ -2135,13 +2144,14 @@ int CUDT::processSrtMsg_HSREQ(const uint32_t* srtdata, size_t len, uint32_t ts, // Check also if the version satisfies the minimum required version if ( m_lPeerSrtVersion < m_lMinimumPeerSrtVersion ) { + m_RejectReason = SRT_REJ_VERSION; LOGC(mglog.Error, log << "HSREQ/rcv: Peer version: " << SrtVersionString(m_lPeerSrtVersion) - << " is too old for requested: " << SrtVersionString(m_lMinimumPeerSrtVersion) << " - REJECTING"); + << " is too old for requested: " << SrtVersionString(m_lMinimumPeerSrtVersion) << " - REJECTING"); return SRT_CMD_REJECT; } HLOGC(mglog.Debug, log << "HSREQ/rcv: PEER Version: " - << SrtVersionString(m_lPeerSrtVersion) + << SrtVersionString(m_lPeerSrtVersion) << " Flags: " << peer_srt_options << "(" << SrtFlagString(peer_srt_options) << ")"); @@ -2152,6 +2162,7 @@ int CUDT::processSrtMsg_HSREQ(const uint32_t* srtdata, size_t len, uint32_t ts, bool peer_message_api = !IsSet(peer_srt_options, SRT_OPT_STREAM); if ( peer_message_api != m_bMessageAPI ) { + m_RejectReason = SRT_REJ_MESSAGEAPI; LOGC(mglog.Error, log << "HSREQ/rcv: Agent uses " << (m_bMessageAPI ? "MESSAGE" : "STREAM") << " API, but the Peer declares " << (peer_message_api ? "MESSAGE" : "STREAM") << " API. Not compatible transmission type, rejecting."); @@ -2165,6 +2176,7 @@ int CUDT::processSrtMsg_HSREQ(const uint32_t* srtdata, size_t len, uint32_t ts, // as the latency flags aren't set. if ( IsSet(peer_srt_options, SRT_OPT_TSBPDSND) || IsSet(peer_srt_options, SRT_OPT_TSBPDRCV) ) { + m_RejectReason = SRT_REJ_ROGUE; LOGC(mglog.Error, log << "HSREQ/rcv: Peer sent only VERSION + FLAGS HSREQ, but TSBPD flags are set. Rejecting."); return SRT_CMD_REJECT; } @@ -2407,6 +2419,7 @@ bool CUDT::interpretSrtHandshake(const CHandShake& hs, const CPacket& hspkt, uin // The HSv4 sends the AGREEMENT handshake message with version=0, do not misinterpret it. if ( m_ConnRes.m_iVersion > HS_VERSION_UDT4 && hs.m_iVersion == 0 ) { + m_RejectReason = SRT_REJ_PEER; LOGC(mglog.Error, log << "HS VERSION = 0, meaning the handshake has been rejected."); return false; } @@ -2417,6 +2430,7 @@ bool CUDT::interpretSrtHandshake(const CHandShake& hs, const CPacket& hspkt, uin // Anyway, check if the handshake contains any extra data. if ( hspkt.getLength() <= CHandShake::m_iContentSize ) { + m_RejectReason = SRT_REJ_ROGUE; // This would mean that the handshake was at least HSv5, but somehow no extras were added. // Dismiss it then, however this has to be logged. LOGC(mglog.Error, log << "HS VERSION=" << hs.m_iVersion << " but no handshake extension found!"); @@ -2427,6 +2441,7 @@ bool CUDT::interpretSrtHandshake(const CHandShake& hs, const CPacket& hspkt, uin int ext_flags = SrtHSRequest::SRT_HSTYPE_HSFLAGS::unwrap(hs.m_iType); if ( ext_flags == 0 ) { + m_RejectReason = SRT_REJ_ROGUE; LOGC(mglog.Error, log << "HS VERSION=" << hs.m_iVersion << " but no handshake extension flags are set!"); return false; } @@ -2457,6 +2472,7 @@ bool CUDT::interpretSrtHandshake(const CHandShake& hs, const CPacket& hspkt, uin // the proper function. if ( blocklen < SRT_HS__SIZE ) { + m_RejectReason = SRT_REJ_ROGUE; LOGC(mglog.Error, log << "HS-ext HSREQ found but invalid size: " << bytelen << " (expected: " << SRT_HS__SIZE << ")"); return false; // don't interpret @@ -2466,6 +2482,7 @@ bool CUDT::interpretSrtHandshake(const CHandShake& hs, const CPacket& hspkt, uin // Interpreted? Then it should be responded with SRT_CMD_HSRSP. if ( rescmd != SRT_CMD_HSRSP ) { + // m_RejectReason already set LOGC(mglog.Error, log << "interpretSrtHandshake: process HSREQ returned unexpected value " << rescmd); return false; } @@ -2478,6 +2495,7 @@ bool CUDT::interpretSrtHandshake(const CHandShake& hs, const CPacket& hspkt, uin // the proper function. if ( blocklen < SRT_HS__SIZE ) { + m_RejectReason = SRT_REJ_ROGUE; LOGC(mglog.Error, log << "HS-ext HSRSP found but invalid size: " << bytelen << " (expected: " << SRT_HS__SIZE << ")"); @@ -2489,6 +2507,8 @@ bool CUDT::interpretSrtHandshake(const CHandShake& hs, const CPacket& hspkt, uin // (nothing to be responded for HSRSP, unless there was some kinda problem) if ( rescmd != SRT_CMD_NONE ) { + // Just formally; the current code doesn't seem to return anything else. + m_RejectReason = SRT_REJ_ROGUE; LOGC(mglog.Error, log << "interpretSrtHandshake: process HSRSP returned unexpected value " << rescmd); return false; } @@ -2497,6 +2517,7 @@ bool CUDT::interpretSrtHandshake(const CHandShake& hs, const CPacket& hspkt, uin } else if ( cmd == SRT_CMD_NONE ) { + m_RejectReason = SRT_REJ_ROGUE; LOGC(mglog.Error, log << "interpretSrtHandshake: no HSREQ/HSRSP block found in the handshake msg!"); // This means that there can be no more processing done by FindExtensionBlock(). // And we haven't found what we need - otherwise one of the above cases would pass @@ -2531,6 +2552,7 @@ bool CUDT::interpretSrtHandshake(const CHandShake& hs, const CPacket& hspkt, uin { if (m_bOPT_StrictEncryption) { + m_RejectReason = SRT_REJ_STRICTENC; LOGC(mglog.Error, log << "HS KMREQ: Peer declares encryption, but agent does not - rejecting per strict requirement"); return false; } @@ -2557,6 +2579,7 @@ bool CUDT::interpretSrtHandshake(const CHandShake& hs, const CPacket& hspkt, uin { if ( !out_data || !out_len ) { + m_RejectReason = SRT_REJ_IPE; LOGC(mglog.Fatal, log << "IPE: HS/KMREQ extracted without passing target buffer!"); return false; } @@ -2564,6 +2587,14 @@ bool CUDT::interpretSrtHandshake(const CHandShake& hs, const CPacket& hspkt, uin int res = m_pCryptoControl->processSrtMsg_KMREQ(begin+1, bytelen, out_data, Ref(*out_len), HS_VERSION_SRT1); if ( res != SRT_CMD_KMRSP ) { + if (m_pCryptoControl->m_RcvKmState == SRT_KM_S_BADSECRET) + { + m_RejectReason = SRT_REJ_BADSECRET; + } + else + { + m_RejectReason = SRT_REJ_STRICTENC; + } // Something went wrong. HLOGC(mglog.Debug, log << "interpretSrtHandshake: KMREQ processing failed - returned " << res); return false; @@ -2574,6 +2605,7 @@ bool CUDT::interpretSrtHandshake(const CHandShake& hs, const CPacket& hspkt, uin // This is inacceptable in case of strict encryption. if (m_bOPT_StrictEncryption) { + m_RejectReason = SRT_REJ_STRICTENC; LOGC(mglog.Error, log << "interpretSrtHandshake: KMREQ result abnornal - rejecting per strict encryption"); return false; } @@ -2585,6 +2617,7 @@ bool CUDT::interpretSrtHandshake(const CHandShake& hs, const CPacket& hspkt, uin int res = m_pCryptoControl->processSrtMsg_KMRSP(begin+1, bytelen, HS_VERSION_SRT1); if (m_bOPT_StrictEncryption && res == -1) { + m_RejectReason = SRT_REJ_STRICTENC; LOGC(mglog.Error, log << "KMRSP failed - rejecting connection as per strict encryption."); return false; } @@ -2592,6 +2625,7 @@ bool CUDT::interpretSrtHandshake(const CHandShake& hs, const CPacket& hspkt, uin } else if ( cmd == SRT_CMD_NONE ) { + m_RejectReason = SRT_REJ_ROGUE; LOGC(mglog.Error, log << "HS KMREQ expected - none found!"); return false; } @@ -2610,6 +2644,7 @@ bool CUDT::interpretSrtHandshake(const CHandShake& hs, const CPacket& hspkt, uin if (m_bOPT_StrictEncryption) { + m_RejectReason = SRT_REJ_STRICTENC; LOGC(mglog.Error, log << "HS KMREQ: Peer declares encryption, but agent didn't enable it at compile time - rejecting per strict requirement"); return false; } @@ -2667,6 +2702,7 @@ bool CUDT::interpretSrtHandshake(const CHandShake& hs, const CPacket& hspkt, uin { if (have_congctl) { + m_RejectReason = SRT_REJ_ROGUE; LOGC(mglog.Error, log << "CONGCTL BLOCK REPEATED!"); return false; } @@ -2686,6 +2722,7 @@ bool CUDT::interpretSrtHandshake(const CHandShake& hs, const CPacket& hspkt, uin // sm cannot be empty, but the agent's sm can be empty meaning live. if (sm != agsm) { + m_RejectReason = SRT_REJ_CONGESTION; LOGC(mglog.Error, log << "PEER'S CONGCTL '" << sm << "' does not match AGENT'S CONGCTL '" << agsm << "'"); return false; } @@ -2713,6 +2750,7 @@ bool CUDT::interpretSrtHandshake(const CHandShake& hs, const CPacket& hspkt, uin { if (m_bOPT_StrictEncryption) { + m_RejectReason = SRT_REJ_STRICTENC; LOGC(mglog.Error, log << "HS EXT: Agent declares encryption, but Peer does not - rejecting connection per strict requirement."); return false; } @@ -2730,6 +2768,7 @@ bool CUDT::interpretSrtHandshake(const CHandShake& hs, const CPacket& hspkt, uin // If agent has set some nondefault congctl, then congctl is expected from the peer. if (agsm != "live" && !have_congctl) { + m_RejectReason = SRT_REJ_CONGESTION; LOGC(mglog.Error, log << "HS EXT: Agent uses '" << agsm << "' congctl, but peer DID NOT DECLARE congctl (assuming 'live')."); return false; } @@ -3077,8 +3116,11 @@ void CUDT::startConnect(const sockaddr* serv_addr, int32_t forced_isn) { if (m_bClosing) // if the socket is closed before connection... e = CUDTException(MJ_SETUP); // XXX NO MN ? - else if (m_ConnRes.m_iReqType == URQ_ERROR_REJECT) // connection request rejected + else if (m_ConnRes.m_iReqType > URQ_FAILURE_TYPES) // connection request rejected + { + m_RejectReason = RejectReasonForURQ(m_ConnRes.m_iReqType); e = CUDTException(MJ_SETUP, MN_REJECTED, 0); + } else if ((!m_bRendezvous) && (m_ConnRes.m_iISN != m_iISN)) // secuity check e = CUDTException(MJ_SETUP, MN_SECURITY, 0); } @@ -3153,14 +3195,16 @@ bool CUDT::processAsyncConnectRequest(EReadStatus rst, EConnectStatus cst, const if (cst != CONN_CONTINUE) { + // processRendezvous already set the reject reason LOGC(mglog.Error, log << "processAsyncConnectRequest: REJECT reported from processRendezvous, not processing further."); status = false; } } else if (cst == CONN_REJECT) { - LOGC(mglog.Error, log << "processAsyncConnectRequest: REJECT reported from HS processing, not processing further."); - return false; + // m_RejectReason already set at worker_ProcessAddressedPacket. + LOGC(mglog.Error, log << "processAsyncConnectRequest: REJECT reported from HS processing, not processing further."); + return false; } else { @@ -3262,11 +3306,12 @@ EConnectStatus CUDT::processRendezvous(ref_t reqpkt, const CPacket& res // a very rare case of creating identical cookies. if (m_SrtHsSide == HSD_DRAW) { + m_RejectReason = SRT_REJ_RDVCOOKIE; LOGC(mglog.Error, log << "COOKIE CONTEST UNRESOLVED: can't assign connection roles, please wait another minute."); return CONN_REJECT; } - UDTRequestType rsp_type = URQ_ERROR_INVALID; // just to track uninitialized errors + UDTRequestType rsp_type = URQ_FAILURE_TYPES; // just to track uninitialized errors // We can assume that the Handshake packet received here as 'response' // is already serialized in m_ConnRes. Check extra flags that are meaningful @@ -3278,6 +3323,7 @@ EConnectStatus CUDT::processRendezvous(ref_t reqpkt, const CPacket& res rendezvousSwitchState(Ref(rsp_type), Ref(needs_extension), Ref(needs_hsrsp)); if (rsp_type > URQ_FAILURE_TYPES) { + m_RejectReason = RejectReasonForURQ(rsp_type); HLOGC(mglog.Debug, log << "processRendezvous: rejecting due to switch-state response: " << RequestTypeStr(rsp_type)); return CONN_REJECT; } @@ -3291,18 +3337,13 @@ EConnectStatus CUDT::processRendezvous(ref_t reqpkt, const CPacket& res m_ConnReq.m_iReqType = rsp_type; m_ConnReq.m_extension = needs_extension; - if (rsp_type > URQ_FAILURE_TYPES) - { - HLOGC(mglog.Debug, log << "processRendezvous: rejecting due to switch-state response: " << RequestTypeStr(rsp_type)); - return CONN_REJECT; - } - // This must be done before prepareConnectionObjects(). applyResponseSettings(); // This must be done before interpreting and creating HSv5 extensions. if ( !prepareConnectionObjects(m_ConnRes, m_SrtHsSide, 0)) { + // m_RejectReason already handled HLOGC(mglog.Debug, log << "processRendezvous: rejecting due to problems in prepareConnectionObjects."); return CONN_REJECT; } @@ -3319,6 +3360,7 @@ EConnectStatus CUDT::processRendezvous(ref_t reqpkt, const CPacket& res m_llLastReqTime = 0; if (response.getLength() == size_t(-1)) { + m_RejectReason = SRT_REJ_IPE; LOGC(mglog.Fatal, log << "IPE: rst=RST_OK, but the packet has set -1 length - REJECTING (REQ-TIME: LOW)"); return CONN_REJECT; } @@ -3366,6 +3408,7 @@ EConnectStatus CUDT::processRendezvous(ref_t reqpkt, const CPacket& res // SECURING: should not happen in HSv5 // SECURED: should have received the recorded KMX correctly (getKmMsg_size(0) > 0) { + m_RejectReason = SRT_REJ_IPE; // Remaining situations: // - password only on this site: shouldn't be considered to be sent to a no-password site LOGC(mglog.Error, log << "processRendezvous: IPE: PERIODIC HS: NO KMREQ RECORDED KMSTATE: RCV=" @@ -3436,7 +3479,8 @@ EConnectStatus CUDT::processRendezvous(ref_t reqpkt, const CPacket& res HLOGC(mglog.Debug, log << "processRendezvous: INITIATOR, will send AGREEMENT - interpreting HSRSP extension"); if ( !interpretSrtHandshake(m_ConnRes, response, 0, 0) ) { - m_ConnReq.m_iReqType = URQ_ERROR_REJECT; + // m_RejectReason is already set, so set the reqtype accordingly + m_ConnReq.m_iReqType = URQFailure(m_RejectReason); } } // This should be false, make a kinda assert here. @@ -3477,6 +3521,7 @@ EConnectStatus CUDT::processRendezvous(ref_t reqpkt, const CPacket& res int cst = postConnect(response, true, 0, synchro); if ( cst == CONN_REJECT ) { + // m_RejectReason already set HLOGC(mglog.Debug, log << "processRendezvous: rejecting due to problems in postConnect."); return CONN_REJECT; } @@ -3500,6 +3545,7 @@ EConnectStatus CUDT::processRendezvous(ref_t reqpkt, const CPacket& res // then createSrtHandshake below will create only empty AGREEMENT message. if ( !createSrtHandshake(reqpkt, Ref(m_ConnReq), SRT_CMD_HSREQ, SRT_CMD_KMREQ, 0, 0)) { + // m_RejectReason already set LOGC(mglog.Error, log << "createSrtHandshake failed (IPE?), connection rejected. REQ-TIME: LOW"); m_llLastReqTime = 0; return CONN_REJECT; @@ -3609,6 +3655,7 @@ EConnectStatus CUDT::processConnectResponse(const CPacket& response, CUDTExcepti if ( !response.isControl(UMSG_HANDSHAKE) ) { + m_RejectReason = SRT_REJ_ROGUE; LOGC(mglog.Error, log << CONID() << "processConnectResponse: received non-addresed packet not UMSG_HANDSHAKE: " << MessageTypeStr(response.getType(), response.getExtendedType())); return CONN_REJECT; @@ -3616,6 +3663,7 @@ EConnectStatus CUDT::processConnectResponse(const CPacket& response, CUDTExcepti if ( m_ConnRes.load_from(response.m_pcData, response.getLength()) == -1 ) { + m_RejectReason = SRT_REJ_ROGUE; // Handshake data were too small to reach the Handshake structure. Reject. LOGC(mglog.Error, log << CONID() << "processConnectResponse: HANDSHAKE data buffer too small - possible blueboxing. Rejecting."); return CONN_REJECT; @@ -3624,6 +3672,7 @@ EConnectStatus CUDT::processConnectResponse(const CPacket& response, CUDTExcepti HLOGC(mglog.Debug, log << CONID() << "processConnectResponse: HS RECEIVED: " << m_ConnRes.show()); if ( m_ConnRes.m_iReqType > URQ_FAILURE_TYPES ) { + m_RejectReason = RejectReasonForURQ(m_ConnRes.m_iReqType); return CONN_REJECT; } @@ -3631,6 +3680,7 @@ EConnectStatus CUDT::processConnectResponse(const CPacket& response, CUDTExcepti { // Yes, we do abort to prevent buffer overrun. Set your MSS correctly // and you'll avoid problems. + m_RejectReason = SRT_REJ_ROGUE; LOGC(mglog.Fatal, log << "MSS size " << m_iMSS << "exceeds MTU size!"); return CONN_REJECT; } @@ -3645,6 +3695,7 @@ EConnectStatus CUDT::processConnectResponse(const CPacket& response, CUDTExcepti // SANITY CHECK: A rendezvous socket should reject any caller requests (it's not a listener) if (m_ConnRes.m_iReqType == URQ_INDUCTION) { + m_RejectReason = SRT_REJ_ROGUE; LOGC(mglog.Error, log << CONID() << "processConnectResponse: Rendezvous-point received INDUCTION handshake (expected WAVEAHAND). Rejecting."); return CONN_REJECT; } @@ -3674,10 +3725,16 @@ EConnectStatus CUDT::processConnectResponse(const CPacket& response, CUDTExcepti // For HSv5, make the cookie contest and basing on this decide, which party // should provide the HSREQ/KMREQ attachment. - createCrypter(hsd, false /* unidirectional */); + // the request time must be updated so that the next handshake can be sent out immediately. + if (!createCrypter(hsd, false /* unidirectional */)) + { + m_RejectReason = SRT_REJ_RESOURCE; + m_ConnReq.m_iReqType = URQFailure(SRT_REJ_RESOURCE); + m_llLastReqTime = 0; + return CONN_REJECT; + } m_ConnReq.m_iReqType = URQ_CONCLUSION; - // the request time must be updated so that the next handshake can be sent out immediately. m_llLastReqTime = 0; return CONN_CONTINUE; } @@ -3732,8 +3789,11 @@ EConnectStatus CUDT::processConnectResponse(const CPacket& response, CUDTExcepti hsd = HSD_INITIATOR; } m_llLastReqTime = 0; - createCrypter(hsd, bidirectional); - + if (!createCrypter(hsd, bidirectional)) + { + m_RejectReason = SRT_REJ_RESOURCE; + return CONN_REJECT; + } // NOTE: This setup sets URQ_CONCLUSION and appropriate data in the handshake structure. // The full handshake to be sent will be filled back in the caller function -- CUDT::startConnect(). return CONN_CONTINUE; @@ -3804,7 +3864,7 @@ EConnectStatus CUDT::postConnect(const CPacket& response, bool rendezvous, CUDTE *eout = CUDTException(MJ_SETUP, MN_REJECTED, 0); } } - if ( !ok ) + if ( !ok ) // m_RejectReason already set return CONN_REJECT; } @@ -4057,7 +4117,7 @@ void CUDT::rendezvousSwitchState(ref_t rsptype, ref_t need LOGC(mglog.Error, log << "RENDEZVOUS COOKIE DRAW! Cannot resolve to a valid state."); // Fallback for cookie draw m_RdvState = CHandShake::RDV_INVALID; - *rsptype = URQ_ERROR_REJECT; + *rsptype = URQFailure(SRT_REJ_RDVCOOKIE); return; } @@ -4239,7 +4299,7 @@ void CUDT::rendezvousSwitchState(ref_t rsptype, ref_t need HLOGC(mglog.Debug, log << "rendezvousSwitchState: INVALID STATE TRANSITION, result: INVALID"); // All others are treated as errors m_RdvState = CHandShake::RDV_WAVING; - *rsptype = URQ_ERROR_INVALID; + *rsptype = URQFailure(SRT_REJ_ROGUE); } /* @@ -4446,11 +4506,15 @@ bool CUDT::prepareConnectionObjects(const CHandShake& hs, HandshakeSide hsd, CUD { *eout = CUDTException(MJ_SYSTEMRES, MN_MEMORY, 0); } + m_RejectReason = SRT_REJ_RESOURCE; return false; } if (!createCrypter(hsd, bidirectional)) // Make sure CC is created (lazy) + { + m_RejectReason = SRT_REJ_RESOURCE; return false; + } return true; } @@ -4525,7 +4589,7 @@ void CUDT::acceptAndRespond(const sockaddr* peer, CHandShake* hs, const CPacket& // // Respond with the rejection message and exit with exception // so that the caller will know that this new socket should be deleted. - hs->m_iReqType = URQ_ERROR_REJECT; + hs->m_iReqType = URQFailure(m_RejectReason); throw CUDTException(MJ_SETUP, MN_REJECTED, 0); } // Since now you can use m_pCryptoControl @@ -4554,7 +4618,7 @@ void CUDT::acceptAndRespond(const sockaddr* peer, CHandShake* hs, const CPacket& // Respond with the rejection message and return false from // this function so that the caller will know that this new // socket should be deleted. - hs->m_iReqType = URQ_ERROR_REJECT; + hs->m_iReqType = URQFailure(m_RejectReason); throw CUDTException(MJ_SETUP, MN_REJECTED, 0); } @@ -7136,7 +7200,8 @@ void CUDT::processCtrl(CPacket& ctrlpkt) if ( !have_hsreq ) { initdata.m_iVersion = 0; - initdata.m_iReqType = URQ_ERROR_INVALID; + m_RejectReason = SRT_REJ_ROGUE; + initdata.m_iReqType = URQFailure(m_RejectReason); } else { @@ -8301,7 +8366,7 @@ int32_t CUDT::bake(const sockaddr* addr, int32_t current_cookie, int correction) // // XXX Make this function return EConnectStatus enum type (extend if needed), // and this will be directly passed to the caller. -int CUDT::processConnectRequest(const sockaddr* addr, CPacket& packet) +SRT_REJECT_REASON CUDT::processConnectRequest(const sockaddr* addr, CPacket& packet) { // XXX ASSUMPTIONS: // [[using assert(packet.m_iID == 0)]] @@ -8310,8 +8375,9 @@ int CUDT::processConnectRequest(const sockaddr* addr, CPacket& packet) if (m_bClosing) { + m_RejectReason = SRT_REJ_CLOSE; HLOGC(mglog.Debug, log << "processConnectRequest: ... NOT. Rejecting because closing."); - return int(URQ_ERROR_REJECT); + return m_RejectReason; } /* @@ -8321,8 +8387,9 @@ int CUDT::processConnectRequest(const sockaddr* addr, CPacket& packet) */ if (m_bBroken) { + m_RejectReason = SRT_REJ_CLOSE; HLOGC(mglog.Debug, log << "processConnectRequest: ... NOT. Rejecting because broken."); - return int(URQ_ERROR_REJECT); + return m_RejectReason; } size_t exp_len = CHandShake::m_iContentSize; // When CHandShake::m_iContentSize is used in log, the file fails to link! @@ -8334,8 +8401,9 @@ int CUDT::processConnectRequest(const sockaddr* addr, CPacket& packet) // more data, depending on what's inside. if (packet.getLength() < exp_len) { + m_RejectReason = SRT_REJ_ROGUE; HLOGC(mglog.Debug, log << "processConnectRequest: ... NOT. Wrong size: " << packet.getLength() << " (expected: " << exp_len << ")"); - return int(URQ_ERROR_INVALID); + return m_RejectReason; } // Dunno why the original UDT4 code only MUCH LATER was checking if the packet was UMSG_HANDSHAKE. @@ -8343,8 +8411,9 @@ int CUDT::processConnectRequest(const sockaddr* addr, CPacket& packet) // sure that the packet contains the handshake at all! if ( !packet.isControl(UMSG_HANDSHAKE) ) { + m_RejectReason = SRT_REJ_ROGUE; LOGC(mglog.Error, log << "processConnectRequest: the packet received as handshake is not a handshake message"); - return int(URQ_ERROR_INVALID); + return m_RejectReason; } CHandShake hs; @@ -8402,7 +8471,7 @@ int CUDT::processConnectRequest(const sockaddr* addr, CPacket& packet) hs.store_to(packet.m_pcData, Ref(size)); packet.m_iTimeStamp = int(CTimer::getTime() - m_stats.startTime); m_pSndQueue->sendto(addr, packet); - return URQ_INDUCTION; + return SRT_REJ_UNKNOWN; // EXCEPTION: this is a "no-error" code. } // Otherwise this should be REQUEST:CONCLUSION. @@ -8417,8 +8486,9 @@ int CUDT::processConnectRequest(const sockaddr* addr, CPacket& packet) if (hs.m_iCookie != cookie_val) { + m_RejectReason = SRT_REJ_RDVCOOKIE; HLOGC(mglog.Debug, log << "processConnectRequest: ...wrong cookie " << hex << cookie_val << ". Ignoring."); - return int(URQ_CONCLUSION); // Don't look at me, I just change integers to symbols! + return m_RejectReason; } HLOGC(mglog.Debug, log << "processConnectRequest: ... correct (FIXED) cookie. Proceeding."); @@ -8454,20 +8524,24 @@ int CUDT::processConnectRequest(const sockaddr* addr, CPacket& packet) // Note that in HSv5 hs.m_iType contains extension flags. if (hs.m_iType != UDT_DGRAM) + { + m_RejectReason = SRT_REJ_ROGUE; accepted_hs = false; + } } else { // Unsupported version // (NOTE: This includes "version=0" which is a rejection flag). + m_RejectReason = SRT_REJ_VERSION; accepted_hs = false; } if (!accepted_hs) { - HLOGC(mglog.Debug, log << "processConnectRequest: version/type mismatch. Sending URQ_ERROR_REJECT."); + HLOGC(mglog.Debug, log << "processConnectRequest: version/type mismatch. Sending REJECT code:" << m_RejectReason); // mismatch, reject the request - hs.m_iReqType = URQ_ERROR_REJECT; + hs.m_iReqType = URQFailure(m_RejectReason); size_t size = CHandShake::m_iContentSize; hs.store_to(packet.m_pcData, Ref(size)); packet.m_iID = id; @@ -8476,14 +8550,20 @@ int CUDT::processConnectRequest(const sockaddr* addr, CPacket& packet) } else { - int result = s_UDTUnited.newConnection(m_SocketID, addr, &hs, packet); + SRT_REJECT_REASON error = SRT_REJ_UNKNOWN; + int result = s_UDTUnited.newConnection(m_SocketID, addr, &hs, packet, Ref(error)); + + // This is listener - m_RejectReason need not be set + // because listener has no functionality of giving the app + // insight into rejected callers. + // ---> // (global.) CUDTUnited::updateListenerMux // (new Socket.) CUDT::acceptAndRespond if (result == -1) { - hs.m_iReqType = URQ_ERROR_REJECT; - LOGF(mglog.Error, "UU:newConnection: rsp(REJECT): %d", URQ_ERROR_REJECT); + hs.m_iReqType = URQFailure(error); + LOGF(mglog.Error, "UU:newConnection: rsp(REJECT): %d", hs.m_iReqType); } // CONFUSION WARNING! @@ -8530,7 +8610,7 @@ int CUDT::processConnectRequest(const sockaddr* addr, CPacket& packet) } LOGC(mglog.Note, log << "listen ret: " << hs.m_iReqType << " - " << RequestTypeStr(hs.m_iReqType)); - return hs.m_iReqType; + return RejectReasonForURQ(hs.m_iReqType); } void CUDT::addLossRecord(std::vector& lr, int32_t lo, int32_t hi) @@ -8877,3 +8957,12 @@ int CUDT::getsndbuffer(SRTSOCKET u, size_t* blocks, size_t* bytes) return std::abs(timespan); } + +SRT_REJECT_REASON CUDT::rejectReason(SRTSOCKET u) +{ + CUDTSocket* s = s_UDTUnited.locate(u); + if (!s || !s->m_pUDT) + return SRT_REJ_UNKNOWN; + + return s->m_pUDT->m_RejectReason; +} diff --git a/srtcore/core.h b/srtcore/core.h index 9a85dfbf9..6ca8fc799 100644 --- a/srtcore/core.h +++ b/srtcore/core.h @@ -206,6 +206,7 @@ class CUDT static bool setstreamid(SRTSOCKET u, const std::string& sid); static std::string getstreamid(SRTSOCKET u); static int getsndbuffer(SRTSOCKET u, size_t* blocks, size_t* bytes); + static SRT_REJECT_REASON rejectReason(SRTSOCKET s); static int setError(const CUDTException& e) { @@ -593,6 +594,7 @@ class CUDT volatile bool m_bShutdown; // If the peer side has shutdown the connection volatile bool m_bBroken; // If the connection has been broken volatile bool m_bPeerHealth; // If the peer status is normal + volatile SRT_REJECT_REASON m_RejectReason; bool m_bOpened; // If the UDT entity has been opened int m_iBrokenCounter; // a counter (number of GC checks) to let the GC tag this socket as disconnected @@ -714,7 +716,7 @@ class CUDT int packData(CPacket& packet, uint64_t& ts); int processData(CUnit* unit); void processClose(); - int processConnectRequest(const sockaddr* addr, CPacket& packet); + SRT_REJECT_REASON processConnectRequest(const sockaddr* addr, CPacket& packet); static void addLossRecord(std::vector& lossrecord, int32_t lo, int32_t hi); int32_t bake(const sockaddr* addr, int32_t previous_cookie = 0, int correction = 0); diff --git a/srtcore/handshake.cpp b/srtcore/handshake.cpp index fe0d253e0..22d5d233e 100644 --- a/srtcore/handshake.cpp +++ b/srtcore/handshake.cpp @@ -117,17 +117,42 @@ int CHandShake::load_from(const char* buf, size_t size) } #ifdef ENABLE_LOGGING + +const char* srt_rejectreason_name [] = { + "UNKNOWN", + "SYSTEM", + "PEER", + "RESOURCE", + "ROGUE", + "BACKLOG", + "IPE", + "CLOSE", + "VERSION", + "RDVCOOKIE", + "BADSECRET", + "STRICTENC", + "MESSAGEAPI", + "CONGESTION", + "FILTER", +}; + std::string RequestTypeStr(UDTRequestType rq) { + if (rq >= URQ_FAILURE_TYPES) + { + SRT_REJECT_REASON rej = RejectReasonForURQ(rq); + int id = rej & ~SRT_REJ_PEERREP; + bool peer = rej & SRT_REJ_PEERREP; + return std::string("ERROR:") + srt_rejectreason_name[id] + + (peer ? "(peer)":""); + } + switch ( rq ) { case URQ_INDUCTION: return "induction"; case URQ_WAVEAHAND: return "waveahand"; case URQ_CONCLUSION: return "conclusion"; case URQ_AGREEMENT: return "agreement"; - case URQ_ERROR_INVALID: return "ERROR:invalid"; - case URQ_ERROR_REJECT: return "ERROR:reject"; - case URQ_DONE: return "done(HSv5RDV)"; default: return "INVALID"; } diff --git a/srtcore/handshake.h b/srtcore/handshake.h index fed5012cc..907409b26 100644 --- a/srtcore/handshake.h +++ b/srtcore/handshake.h @@ -213,11 +213,39 @@ enum UDTRequestType // Errors reported by the peer, also used as useless error codes // in handshake processing functions. URQ_FAILURE_TYPES = 1000, - URQ_ERROR_REJECT = 1002, - URQ_ERROR_INVALID = 1004 + + // Repeated codes from SRT_REJ_* here for convenience and + // compiler warning prevention, but they should not be used directly. + URQ_REJ_SYSTEM, // broken due to system function error + URQ_REJ_PEER, // connection was rejected by peer + URQ_REJ_RESOURCE, // internal problem with resource allocation + URQ_REJ_ROGUE, // incorrect data in handshake messages + URQ_REJ_IPE, // internal program error + URQ_REJ_CLOSE, // socket is closing + URQ_REJ_VERSION, // peer is older version than agent's minimum set + URQ_REJ_RDVCOOKIE, // rendezvous cookie collision + URQ_REJ_BADSECRET, // wrong password + URQ_REJ_STRICTENC, // illegal setup for strictly-encrypted + URQ_REJ_MESSAGEAPI, // streamapi/messageapi collision + URQ_REJ_CONGESTION, // incompatible congestion-controller type + URQ_REJ_FILTER // incompatible packet filter }; +inline UDTRequestType URQFailure(SRT_REJECT_REASON reason) +{ + return UDTRequestType(URQ_FAILURE_TYPES + int(reason)); +} +inline SRT_REJECT_REASON RejectReasonForURQ(UDTRequestType req) +{ + if (req < URQ_FAILURE_TYPES || req - URQ_FAILURE_TYPES >= SRT_REJ__SIZE) + return SRT_REJ_UNKNOWN; + return SRT_REJECT_REASON( (req - URQ_FAILURE_TYPES) | SRT_REJ_PEERREP); +} + +// DEPRECATED values. Use URQFailure(SRT_REJECT_REASON). +const UDTRequestType URQ_ERROR_REJECT SRT_ATR_DEPRECATED = (UDTRequestType)1002; // == 1000 + SRT_REJ_PEER +const UDTRequestType URQ_ERROR_INVALID SRT_ATR_DEPRECATED = (UDTRequestType)1004; // == 1000 + SRT_REJ_ROGUE // XXX Change all uses of that field to UDTRequestType when possible #if ENABLE_LOGGING diff --git a/srtcore/queue.cpp b/srtcore/queue.cpp index 31644d53c..7eae05fda 100644 --- a/srtcore/queue.cpp +++ b/srtcore/queue.cpp @@ -1010,6 +1010,8 @@ void CRendezvousQueue::updateConnStatus(EReadStatus rst, EConnectStatus cst, con // before calling this function), and it checks for the data presence. if (!i->m_pUDT->processAsyncConnectRequest(rst, cst, response, i->m_pPeerAddr)) { + // cst == CONN_REJECT can only be result of worker_ProcessAddressedPacket and + // its already set in this case. LOGC(mglog.Error, log << "RendezvousQueue: processAsyncConnectRequest FAILED. Setting TTL as EXPIRED."); i->m_pUDT->sendCtrl(UMSG_SHUTDOWN); i->m_ullTTL = 0; // Make it expire right now, will be picked up at the next iteration @@ -1149,6 +1151,7 @@ void* CRcvQueue::worker(void* param) // - an enqueued rendezvous socket // - a socket connected to a peer cst = self->worker_ProcessAddressedPacket(id, unit, &sa); + // CAN RETURN CONN_REJECT, but m_RejectReason is already set } HLOGC(mglog.Debug, log << self->CONID() << "worker: result for the unit: " << ConnectStatusStr(cst)); if (cst == CONN_AGAIN) @@ -1311,7 +1314,7 @@ EConnectStatus CRcvQueue::worker_ProcessConnectionRequest(CUnit* unit, const soc // that another thread could have closed the socket at // the same time and inject a bug between checking the // pointer for NULL and using it. - int listener_ret = 0; + SRT_REJECT_REASON listener_ret = SRT_REJ_UNKNOWN; bool have_listener = false; { CGuard cg(m_LSLock); @@ -1319,28 +1322,12 @@ EConnectStatus CRcvQueue::worker_ProcessConnectionRequest(CUnit* unit, const soc { LOGC(mglog.Note, log << "PASSING request from: " << SockaddrToString(addr) << " to agent:" << m_pListener->socketID()); listener_ret = m_pListener->processConnectRequest(addr, unit->m_Packet); - // XXX This returns some very significant return value, which - // is completely ignored here. - // Actually this is the only place in the code where this - // function is being called, so it's hard to say what the - // returned value had to serve for. - - // The tricky part is that this is something done "under the hood"; - // if any problem occurs during this process, then this will simply - // drop the connection request. The only user process that is connected - // to it is accept() call (or connect() in case of rendezvous), but - // the system cannot return an error from accept() just because some - // user was attempting to connect, but formulated the connection - // request incorrectly. - - // The only thing that could be done in case when the "listen" call - // fails, is to probably send a short information packet (once; it's - // not so important to make it reach the target) that the connection - // has been rejected due to incorrectly formulated request. However - // just in order to send anything in response, the actual sender must - // be properly known, and this isn't the case of incorrectly formulated - // connection request. So, we can only say sorry to ourselves and - // do nothing. + + // This function does return a code, but it's hard to say as to whether + // anything can be done about it. In case when it's stated possible, the + // listener will try to send some rejection response to the caller, but + // that's already done inside this function. So it's only used for + // displaying the error in logs. have_listener = true; } @@ -1354,7 +1341,7 @@ EConnectStatus CRcvQueue::worker_ProcessConnectionRequest(CUnit* unit, const soc { LOGC(mglog.Note, log << CONID() << "Listener managed the connection request from: " << SockaddrToString(addr) << " result:" << RequestTypeStr(UDTRequestType(listener_ret))); - return (listener_ret >= URQ_FAILURE_TYPES ? CONN_REJECT : CONN_CONTINUE); + return listener_ret == SRT_REJ_UNKNOWN ? CONN_CONTINUE : CONN_REJECT; } // If there's no listener waiting for the packet, just store it into the queue. @@ -1385,6 +1372,7 @@ EConnectStatus CRcvQueue::worker_ProcessAddressedPacket(int32_t id, CUnit* unit, if (!u->m_bConnected || u->m_bBroken || u->m_bClosing) { + u->m_RejectReason = SRT_REJ_CLOSE; // The socket is currently in the process of being disconnected // or destroyed. Ignore. // XXX send UMSG_SHUTDOWN in this case? diff --git a/srtcore/srt.h b/srtcore/srt.h index f9e7586d3..7ba6c174a 100644 --- a/srtcore/srt.h +++ b/srtcore/srt.h @@ -451,6 +451,29 @@ static const SRT_ERRNO SRT_EISDGRAM SRT_ATR_DEPRECATED = (SRT_ERRNO) MN(NOTSUP, #undef MJ #undef MN +enum SRT_REJECT_REASON +{ + SRT_REJ_UNKNOWN, // initial set when in progress + SRT_REJ_SYSTEM, // broken due to system function error + SRT_REJ_PEER, // connection was rejected by peer + SRT_REJ_RESOURCE, // internal problem with resource allocation + SRT_REJ_ROGUE, // incorrect data in handshake messages + SRT_REJ_BACKLOG, // listener's backlog exceeded + SRT_REJ_IPE, // internal program error + SRT_REJ_CLOSE, // socket is closing + SRT_REJ_VERSION, // peer is older version than agent's minimum set + SRT_REJ_RDVCOOKIE, // rendezvous cookie collision + SRT_REJ_BADSECRET, // wrong password + SRT_REJ_STRICTENC, // illegal setup for strictly-encrypted + SRT_REJ_MESSAGEAPI, // streamapi/messageapi collision + SRT_REJ_CONGESTION, // incompatible congestion-controller type + SRT_REJ_FILTER, // incompatible packet filter + + SRT_REJ__SIZE, + + SRT_REJ_PEERREP = 0x100 +}; + // Logging API - specialization for SRT. // Define logging functional areas for log selection. @@ -647,6 +670,10 @@ SRT_API void srt_setlogflags(int flags); SRT_API int srt_getsndbuffer(SRTSOCKET sock, size_t* blocks, size_t* bytes); +SRT_API enum SRT_REJECT_REASON srt_getrejectreason(SRTSOCKET sock); +SRT_API extern const char* srt_rejectreason_msg []; +const char* srt_rejectreason_str(enum SRT_REJECT_REASON id); + #ifdef __cplusplus } #endif diff --git a/srtcore/srt_c_api.cpp b/srtcore/srt_c_api.cpp index ffcef4cab..b6da9229c 100644 --- a/srtcore/srt_c_api.cpp +++ b/srtcore/srt_c_api.cpp @@ -317,5 +317,9 @@ int srt_getsndbuffer(SRTSOCKET sock, size_t* blocks, size_t* bytes) return CUDT::getsndbuffer(sock, blocks, bytes); } +enum SRT_REJECT_REASON srt_getrejectreason(SRTSOCKET sock) +{ + return CUDT::rejectReason(sock); +} } diff --git a/testing/testmedia.cpp b/testing/testmedia.cpp index a2b42d088..fe5f7ef77 100644 --- a/testing/testmedia.cpp +++ b/testing/testmedia.cpp @@ -595,8 +595,9 @@ void SrtCommon::ConnectClient(string host, int port) int stat = srt_connect(m_sock, psa, sizeof sa); if ( stat == SRT_ERROR ) { + SRT_REJECT_REASON reason = srt_getrejectreason(m_sock); srt_close(m_sock); - Error(UDT::getlasterror(), "UDT::connect"); + Error(UDT::getlasterror(), "srt_connect", reason); } // Wait for REAL connected state if nonblocking mode @@ -626,10 +627,17 @@ void SrtCommon::ConnectClient(string host, int port) Error(UDT::getlasterror(), "ConfigurePost"); } -void SrtCommon::Error(UDT::ERRORINFO& udtError, string src) +void SrtCommon::Error(UDT::ERRORINFO& udtError, string src, SRT_REJECT_REASON reason) { int udtResult = udtError.getErrorCode(); string message = udtError.getErrorMessage(); + if (udtResult == SRT_ECONNREJ) + { + message += ": "; + message += srt_rejectreason_str(reason); + if (reason & SRT_REJ_PEERREP) + message += " (peer)"; + } if ( Verbose::on ) Verb() << "FAILURE\n" << src << ": [" << udtResult << "] " << message; else diff --git a/testing/testmedia.hpp b/testing/testmedia.hpp index 06ab44abc..09138a7db 100644 --- a/testing/testmedia.hpp +++ b/testing/testmedia.hpp @@ -66,7 +66,7 @@ class SrtCommon protected: - void Error(UDT::ERRORINFO& udtError, string src); + void Error(UDT::ERRORINFO& udtError, string src, SRT_REJECT_REASON reason = SRT_REJ_UNKNOWN); void Init(string host, int port, map par, SRT_EPOLL_OPT dir); int AddPoller(SRTSOCKET socket, int modes); virtual int ConfigurePost(SRTSOCKET sock); From 748ba0e31afad852474bc2760e8417957263ca46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Ma=C5=82ecki?= Date: Tue, 4 Jun 2019 13:51:01 +0200 Subject: [PATCH 2/8] Fixed incorrectly reported rejection code --- srtcore/api.cpp | 2 ++ srtcore/core.cpp | 20 ++++++++++---------- srtcore/handshake.h | 1 + 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/srtcore/api.cpp b/srtcore/api.cpp index e1efddad0..ee3348bd6 100644 --- a/srtcore/api.cpp +++ b/srtcore/api.cpp @@ -454,6 +454,8 @@ int CUDTUnited::newConnection(const SRTSOCKET listen, const sockaddr* peer, CHan } catch (...) { + // Extract the error that was set in this new failed entity. + *r_error = ns->m_pUDT->m_RejectReason; error = 1; goto ERR_ROLLBACK; } diff --git a/srtcore/core.cpp b/srtcore/core.cpp index c44e7b707..eb49e6626 100644 --- a/srtcore/core.cpp +++ b/srtcore/core.cpp @@ -2587,16 +2587,9 @@ bool CUDT::interpretSrtHandshake(const CHandShake& hs, const CPacket& hspkt, uin int res = m_pCryptoControl->processSrtMsg_KMREQ(begin+1, bytelen, out_data, Ref(*out_len), HS_VERSION_SRT1); if ( res != SRT_CMD_KMRSP ) { - if (m_pCryptoControl->m_RcvKmState == SRT_KM_S_BADSECRET) - { - m_RejectReason = SRT_REJ_BADSECRET; - } - else - { - m_RejectReason = SRT_REJ_STRICTENC; - } + m_RejectReason = SRT_REJ_IPE; // Something went wrong. - HLOGC(mglog.Debug, log << "interpretSrtHandshake: KMREQ processing failed - returned " << res); + HLOGC(mglog.Debug, log << "interpretSrtHandshake: IPE/EPE KMREQ processing failed - returned " << res); return false; } if (*out_len == 1) @@ -2605,7 +2598,14 @@ bool CUDT::interpretSrtHandshake(const CHandShake& hs, const CPacket& hspkt, uin // This is inacceptable in case of strict encryption. if (m_bOPT_StrictEncryption) { - m_RejectReason = SRT_REJ_STRICTENC; + if (m_pCryptoControl->m_RcvKmState == SRT_KM_S_BADSECRET) + { + m_RejectReason = SRT_REJ_BADSECRET; + } + else + { + m_RejectReason = SRT_REJ_STRICTENC; + } LOGC(mglog.Error, log << "interpretSrtHandshake: KMREQ result abnornal - rejecting per strict encryption"); return false; } diff --git a/srtcore/handshake.h b/srtcore/handshake.h index 907409b26..ff90ff404 100644 --- a/srtcore/handshake.h +++ b/srtcore/handshake.h @@ -220,6 +220,7 @@ enum UDTRequestType URQ_REJ_PEER, // connection was rejected by peer URQ_REJ_RESOURCE, // internal problem with resource allocation URQ_REJ_ROGUE, // incorrect data in handshake messages + URQ_REJ_BACKLOG, // backlog exceeded URQ_REJ_IPE, // internal program error URQ_REJ_CLOSE, // socket is closing URQ_REJ_VERSION, // peer is older version than agent's minimum set From 1592ad6284bd2b13c279421c0e5c577284092059 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Ma=C5=82ecki?= Date: Mon, 5 Aug 2019 13:09:33 +0200 Subject: [PATCH 3/8] Renamed REJ_STRICTENC and its msgstr. Removed PEERREP flag. --- srtcore/common.cpp | 4 ++-- srtcore/core.cpp | 10 +++++----- srtcore/handshake.cpp | 6 ++---- srtcore/handshake.h | 2 +- srtcore/srt.h | 4 +--- testing/testmedia.cpp | 2 -- 6 files changed, 11 insertions(+), 17 deletions(-) diff --git a/srtcore/common.cpp b/srtcore/common.cpp index 12b216c15..a9e0a0b2d 100644 --- a/srtcore/common.cpp +++ b/srtcore/common.cpp @@ -846,7 +846,7 @@ const char* srt_rejectreason_msg [] = { "Peer version too old", "Rendezvous-mode cookie collision", "Incorrect passphrase", - "Strictly-encrypted condition not met", + "Password required or unexpected", "MessageAPI/StreamAPI collision", "Congestion controller type collision", "Packet Filter type collision" @@ -854,7 +854,7 @@ const char* srt_rejectreason_msg [] = { const char* srt_rejectreason_str(SRT_REJECT_REASON rid) { - int id = rid & ~SRT_REJ_PEERREP; // disregard peer reported + int id = rid; static const size_t ra_size = Size(srt_rejectreason_msg); if (size_t(id) >= ra_size) return srt_rejectreason_msg[0]; diff --git a/srtcore/core.cpp b/srtcore/core.cpp index 4b8c09b09..31b6ba24d 100644 --- a/srtcore/core.cpp +++ b/srtcore/core.cpp @@ -2565,7 +2565,7 @@ bool CUDT::interpretSrtHandshake(const CHandShake& hs, const CPacket& hspkt, uin { if (m_bOPT_StrictEncryption) { - m_RejectReason = SRT_REJ_STRICTENC; + m_RejectReason = SRT_REJ_UNSECURE; LOGC(mglog.Error, log << "HS KMREQ: Peer declares encryption, but agent does not - rejecting per strict requirement"); return false; } @@ -2617,7 +2617,7 @@ bool CUDT::interpretSrtHandshake(const CHandShake& hs, const CPacket& hspkt, uin } else { - m_RejectReason = SRT_REJ_STRICTENC; + m_RejectReason = SRT_REJ_UNSECURE; } LOGC(mglog.Error, log << "interpretSrtHandshake: KMREQ result abnornal - rejecting per strict encryption"); return false; @@ -2630,7 +2630,7 @@ bool CUDT::interpretSrtHandshake(const CHandShake& hs, const CPacket& hspkt, uin int res = m_pCryptoControl->processSrtMsg_KMRSP(begin+1, bytelen, HS_VERSION_SRT1); if (m_bOPT_StrictEncryption && res == -1) { - m_RejectReason = SRT_REJ_STRICTENC; + m_RejectReason = SRT_REJ_UNSECURE; LOGC(mglog.Error, log << "KMRSP failed - rejecting connection as per strict encryption."); return false; } @@ -2657,7 +2657,7 @@ bool CUDT::interpretSrtHandshake(const CHandShake& hs, const CPacket& hspkt, uin if (m_bOPT_StrictEncryption) { - m_RejectReason = SRT_REJ_STRICTENC; + m_RejectReason = SRT_REJ_UNSECURE; LOGC(mglog.Error, log << "HS KMREQ: Peer declares encryption, but agent didn't enable it at compile time - rejecting per strict requirement"); return false; } @@ -2776,7 +2776,7 @@ bool CUDT::interpretSrtHandshake(const CHandShake& hs, const CPacket& hspkt, uin { if (m_bOPT_StrictEncryption) { - m_RejectReason = SRT_REJ_STRICTENC; + m_RejectReason = SRT_REJ_UNSECURE; LOGC(mglog.Error, log << "HS EXT: Agent declares encryption, but Peer does not - rejecting connection per strict requirement."); return false; } diff --git a/srtcore/handshake.cpp b/srtcore/handshake.cpp index 22d5d233e..cc5fb8643 100644 --- a/srtcore/handshake.cpp +++ b/srtcore/handshake.cpp @@ -141,10 +141,8 @@ std::string RequestTypeStr(UDTRequestType rq) if (rq >= URQ_FAILURE_TYPES) { SRT_REJECT_REASON rej = RejectReasonForURQ(rq); - int id = rej & ~SRT_REJ_PEERREP; - bool peer = rej & SRT_REJ_PEERREP; - return std::string("ERROR:") + srt_rejectreason_name[id] - + (peer ? "(peer)":""); + int id = rej; + return std::string("ERROR:") + srt_rejectreason_name[id]; } switch ( rq ) diff --git a/srtcore/handshake.h b/srtcore/handshake.h index ff90ff404..6968e8590 100644 --- a/srtcore/handshake.h +++ b/srtcore/handshake.h @@ -241,7 +241,7 @@ inline SRT_REJECT_REASON RejectReasonForURQ(UDTRequestType req) { if (req < URQ_FAILURE_TYPES || req - URQ_FAILURE_TYPES >= SRT_REJ__SIZE) return SRT_REJ_UNKNOWN; - return SRT_REJECT_REASON( (req - URQ_FAILURE_TYPES) | SRT_REJ_PEERREP); + return SRT_REJECT_REASON(req - URQ_FAILURE_TYPES); } // DEPRECATED values. Use URQFailure(SRT_REJECT_REASON). diff --git a/srtcore/srt.h b/srtcore/srt.h index 67a673354..6ffd62668 100644 --- a/srtcore/srt.h +++ b/srtcore/srt.h @@ -464,14 +464,12 @@ enum SRT_REJECT_REASON SRT_REJ_VERSION, // peer is older version than agent's minimum set SRT_REJ_RDVCOOKIE, // rendezvous cookie collision SRT_REJ_BADSECRET, // wrong password - SRT_REJ_STRICTENC, // illegal setup for strictly-encrypted + SRT_REJ_UNSECURE, // illegal setup for strictly-encrypted SRT_REJ_MESSAGEAPI, // streamapi/messageapi collision SRT_REJ_CONGESTION, // incompatible congestion-controller type SRT_REJ_FILTER, // incompatible packet filter SRT_REJ__SIZE, - - SRT_REJ_PEERREP = 0x100 }; // Logging API - specialization for SRT. diff --git a/testing/testmedia.cpp b/testing/testmedia.cpp index 17d5b46b7..1844f22a3 100755 --- a/testing/testmedia.cpp +++ b/testing/testmedia.cpp @@ -636,8 +636,6 @@ void SrtCommon::Error(UDT::ERRORINFO& udtError, string src, SRT_REJECT_REASON re { message += ": "; message += srt_rejectreason_str(reason); - if (reason & SRT_REJ_PEERREP) - message += " (peer)"; } if ( Verbose::on ) Verb() << "FAILURE\n" << src << ": [" << udtResult << "] " << message; From c98f64c519f673d71afce21ddf8eaadeeaf07175 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Ma=C5=82ecki?= Date: Mon, 5 Aug 2019 14:37:53 +0200 Subject: [PATCH 4/8] Removed trailing period from the error message --- srtcore/common.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/srtcore/common.cpp b/srtcore/common.cpp index a9e0a0b2d..6ca7225aa 100644 --- a/srtcore/common.cpp +++ b/srtcore/common.cpp @@ -599,11 +599,6 @@ const char* CUDTException::getErrorMessage() m_strMsg += ": " + SysStrError(m_iErrno); } - // period - #ifndef _WIN32 - m_strMsg += "."; - #endif - return m_strMsg.c_str(); } From e588af241bc3c9406b50b92c786f3a3e5634a830 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Ma=C5=82ecki?= Date: Mon, 5 Aug 2019 14:55:36 +0200 Subject: [PATCH 5/8] Renamed associated name --- srtcore/handshake.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srtcore/handshake.cpp b/srtcore/handshake.cpp index cc5fb8643..b156769e3 100644 --- a/srtcore/handshake.cpp +++ b/srtcore/handshake.cpp @@ -130,7 +130,7 @@ const char* srt_rejectreason_name [] = { "VERSION", "RDVCOOKIE", "BADSECRET", - "STRICTENC", + "UNSECURE", "MESSAGEAPI", "CONGESTION", "FILTER", From 4ce4638d58c50d7e931b13dea92befbdf02d3091 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Ma=C5=82ecki?= Date: Mon, 5 Aug 2019 15:08:59 +0200 Subject: [PATCH 6/8] Some improvements in logs --- srtcore/api.cpp | 2 +- srtcore/core.cpp | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/srtcore/api.cpp b/srtcore/api.cpp index b4b08fae1..d2bd6d087 100644 --- a/srtcore/api.cpp +++ b/srtcore/api.cpp @@ -512,7 +512,7 @@ int CUDTUnited::newConnection(const SRTSOCKET listen, const sockaddr* peer, CHan #if ENABLE_LOGGING static const char* why [] = { "UNKNOWN ERROR", - "SYSTEM RESOURCE ERROR", + "CONNECTION REJECTED", "IPE when mapping a socket", "IPE when inserting a socket" }; diff --git a/srtcore/core.cpp b/srtcore/core.cpp index 31b6ba24d..42dd54376 100644 --- a/srtcore/core.cpp +++ b/srtcore/core.cpp @@ -8582,7 +8582,8 @@ SRT_REJECT_REASON CUDT::processConnectRequest(const sockaddr* addr, CPacket& pac if (!accepted_hs) { - HLOGC(mglog.Debug, log << "processConnectRequest: version/type mismatch. Sending REJECT code:" << m_RejectReason); + HLOGC(mglog.Debug, log << "processConnectRequest: version/type mismatch. Sending REJECT code:" << m_RejectReason + << " MSG: " << srt_rejectreason_str(m_RejectReason)); // mismatch, reject the request hs.m_iReqType = URQFailure(m_RejectReason); size_t size = CHandShake::m_iContentSize; @@ -8606,7 +8607,7 @@ SRT_REJECT_REASON CUDT::processConnectRequest(const sockaddr* addr, CPacket& pac if (result == -1) { hs.m_iReqType = URQFailure(error); - LOGF(mglog.Error, "UU:newConnection: rsp(REJECT): %d", hs.m_iReqType); + LOGF(mglog.Error, "UU:newConnection: rsp(REJECT): %d - %s", hs.m_iReqType, srt_rejectreason_str(error)); } // CONFUSION WARNING! From 7c5231037a885e614c292c15d9d27952912e7a28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Ma=C5=82ecki?= Date: Mon, 5 Aug 2019 15:32:35 +0200 Subject: [PATCH 7/8] Added documentation. Minor fixes. --- docs/API-functions.md | 110 ++++++++++++++++++++++++++++++++++++++++++ srtcore/common.cpp | 2 +- srtcore/core.cpp | 4 +- srtcore/srt.h | 2 +- 4 files changed, 114 insertions(+), 4 deletions(-) diff --git a/docs/API-functions.md b/docs/API-functions.md index 772cbeb22..b67013637 100644 --- a/docs/API-functions.md +++ b/docs/API-functions.md @@ -427,6 +427,10 @@ rendezvous socket, but rendezvous sockets must be explicitly bound to a local interface prior to connecting. Non-rendezvous sockets (caller sockets) can be left without binding - the call to `srt_connect` will bind them automatically. * `SRT_ECONNSOCK`: Socket `u` is already connected + * `SRT_ECONNREJ`: Connection has been rejected + +In case when `SRT_ECONNREJ` error was reported, you can get the reason for +a rejected connection from `srt_getrejectreason`. ### srt_connect_debug @@ -874,6 +878,112 @@ void srt_clearlasterror(void); This function clears the last error. After this call, the `srt_getlasterror` will report a "successful" code. +### srt_getrejectreason + +``` +enum SRT_REJECT_REASON srt_getrejectreason(SRTSOCKET sock); +``` + +This function shall be called after a connecting function (such as `srt_connect`) +has returned an error, which's code was `SRT_ECONNREJ`. It allows to get a more +detailed rejection reason. This function returns a numeric code, which can be +translated into a message by `srt_rejectreason_str`. The following codes are +currently reported: + +#### SRT_REJ_UNKNOWN + +A fallback value for cases when there was no connection rejected. + +#### SRT_REJ_SYSTEM + +One of system function reported a failure. Usually this means some system +error or lack of system resources to complete the task. + +#### SRT_REJ_PEER + +The connection has been rejected by peer, but no further details are available. +This usually means that the peer doesn't support rejection reason reporting. + +#### SRT_REJ_RESOURCE + +A problem with resource allocation (usually memory). + +#### SRT_REJ_ROGUE + +The data sent by one party to another cannot be properly interpreted. This +should not happen during normal usage, unless it's a bug, or some weird +events are happening on the network. + +#### SRT_REJ_BACKLOG + +The listener's backlog has exceeded (there are many other callers waiting for +the opportunity of being connected and wait in the queue, which has reached +its limit). + +#### SRT_REJ_IPE + +Internal Program Error. This should not happen during normal usage and it +usually means a bug in the software (although this can be reported by both +local and foreign host). + +#### SRT_REJ_CLOSE + +The listener socket was able to receive your request, but at this moment it +is being closed. It's likely that your next attempt will result with timeout. + +#### SRT_REJ_VERSION + +Any party of the connection has set up minimum version that is required for +that connection, and the other party didn't satisfy this requirement. + +#### SRT_REJ_RDVCOOKIE + +Rendezvous cookie collision. This normally should never happen, or the +probability that this will really happen is negligible. However this can +be also a result of a misconfiguration that you are trying to make a +rendezvous connection where both parties try to bind to the same IP +address, or both are local addresses of the same host - in which case +the sent handshake packets are returning to the same host as if they +were sent by the peer, who is this party itself. When this happens, +this reject reason will be reported by every attempt. + +#### SRT_REJ_BADSECRET + +Both parties have defined a passprhase for connection and they differ. + +#### SRT_REJ_UNSECURE + +Only one connection party has set up a password. See also +`SRTO_STRICTENC` flag in API.md. + +#### SRT_REJ_MESSAGEAPI + +The value for `SRTO_MESSAGEAPI` flag is different on both connection +parties. + +#### SRT_REJ_CONGESTION + +The `SRTO_CONGESTION` option has been set up differently on both +connection parties. + +#### SRT_REJ_FILTER + +The `SRTO_FILTER` option has been set differently on both connection +parties (NOTE: this flag may not exist yet in this version). + + +### srt_rejectreason_str + +``` +const char* srt_rejectreason_str(enum SRT_REJECT_REASON id); +``` + +Returns a constant string for the reason of the connection rejected, +as per given code id. Alternatively you can use the `srt_rejectreason_msg` +array. This function additionally handles the case for unknown id by +reporting `SRT_REJ_UNKNOWN` in such case. + + Performance tracking -------------------- diff --git a/srtcore/common.cpp b/srtcore/common.cpp index 6ca7225aa..95925ae44 100644 --- a/srtcore/common.cpp +++ b/srtcore/common.cpp @@ -829,7 +829,7 @@ std::string TransmissionEventStr(ETransmissionEvent ev) return vals[ev]; } -const char* srt_rejectreason_msg [] = { +extern const char* const srt_rejectreason_msg [] = { "Unknown or erroneous", "Error in system calls", "Peer rejected connection", diff --git a/srtcore/core.cpp b/srtcore/core.cpp index 42dd54376..3bae9b233 100644 --- a/srtcore/core.cpp +++ b/srtcore/core.cpp @@ -2165,8 +2165,8 @@ int CUDT::processSrtMsg_HSREQ(const uint32_t* srtdata, size_t len, uint32_t ts, HLOGC(mglog.Debug, log << "HSREQ/rcv: PEER Version: " << SrtVersionString(m_lPeerSrtVersion) - << " Flags: " << peer_srt_options - << "(" << SrtFlagString(peer_srt_options) << ")"); + << " Flags: " << peer_srt_options + << "(" << SrtFlagString(peer_srt_options) << ")"); m_bPeerRexmitFlag = IsSet(peer_srt_options, SRT_OPT_REXMITFLG); HLOGF(mglog.Debug, "HSREQ/rcv: peer %s REXMIT flag", m_bPeerRexmitFlag ? "UNDERSTANDS" : "DOES NOT UNDERSTAND" ); diff --git a/srtcore/srt.h b/srtcore/srt.h index 6ffd62668..74268a6b6 100644 --- a/srtcore/srt.h +++ b/srtcore/srt.h @@ -671,7 +671,7 @@ SRT_API void srt_setlogflags(int flags); SRT_API int srt_getsndbuffer(SRTSOCKET sock, size_t* blocks, size_t* bytes); SRT_API enum SRT_REJECT_REASON srt_getrejectreason(SRTSOCKET sock); -SRT_API extern const char* srt_rejectreason_msg []; +SRT_API extern const char* const srt_rejectreason_msg []; const char* srt_rejectreason_str(enum SRT_REJECT_REASON id); #ifdef __cplusplus From fe3cf50142c40a8a64686de64c2b86a30e8398b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Ma=C5=82ecki?= Date: Mon, 5 Aug 2019 15:45:15 +0200 Subject: [PATCH 8/8] Updated protocol documentation. Smaller fixes --- docs/handshake.md | 6 ++++++ srtcore/handshake.h | 23 +++++------------------ srtcore/srt.h | 2 +- 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/docs/handshake.md b/docs/handshake.md index 0fd9fede0..48a69795b 100644 --- a/docs/handshake.md +++ b/docs/handshake.md @@ -427,6 +427,12 @@ indicates the handshake message type. Note that the **Rendezvous** process is different in HSv4 and HSv5, as the latter is based on a state machine. +In case when the connection process has failed when the party was about to +send the `URQ_CONCLUSION` handshake, this field will contain appropriate +error value. This value starts from 1000 (see `UDTRequestType` in `handshake.h`, +since `URQ_FAILURE_TYPES` symbol) added with the value of the rejection +reason (see `SRT_REJECT_REASON` in `srt.h`). + [Return to top of page](#srt-handshake) diff --git a/srtcore/handshake.h b/srtcore/handshake.h index 6968e8590..4354d4f12 100644 --- a/srtcore/handshake.h +++ b/srtcore/handshake.h @@ -212,24 +212,11 @@ enum UDTRequestType // Errors reported by the peer, also used as useless error codes // in handshake processing functions. - URQ_FAILURE_TYPES = 1000, - - // Repeated codes from SRT_REJ_* here for convenience and - // compiler warning prevention, but they should not be used directly. - URQ_REJ_SYSTEM, // broken due to system function error - URQ_REJ_PEER, // connection was rejected by peer - URQ_REJ_RESOURCE, // internal problem with resource allocation - URQ_REJ_ROGUE, // incorrect data in handshake messages - URQ_REJ_BACKLOG, // backlog exceeded - URQ_REJ_IPE, // internal program error - URQ_REJ_CLOSE, // socket is closing - URQ_REJ_VERSION, // peer is older version than agent's minimum set - URQ_REJ_RDVCOOKIE, // rendezvous cookie collision - URQ_REJ_BADSECRET, // wrong password - URQ_REJ_STRICTENC, // illegal setup for strictly-encrypted - URQ_REJ_MESSAGEAPI, // streamapi/messageapi collision - URQ_REJ_CONGESTION, // incompatible congestion-controller type - URQ_REJ_FILTER // incompatible packet filter + URQ_FAILURE_TYPES = 1000 + + // NOTE: codes above 1000 are reserved for failure codes for + // rejection reason, as per `SRT_REJECT_REASON` enum. DO NOT + // add any new values here. }; inline UDTRequestType URQFailure(SRT_REJECT_REASON reason) diff --git a/srtcore/srt.h b/srtcore/srt.h index 74268a6b6..8d314574b 100644 --- a/srtcore/srt.h +++ b/srtcore/srt.h @@ -464,7 +464,7 @@ enum SRT_REJECT_REASON SRT_REJ_VERSION, // peer is older version than agent's minimum set SRT_REJ_RDVCOOKIE, // rendezvous cookie collision SRT_REJ_BADSECRET, // wrong password - SRT_REJ_UNSECURE, // illegal setup for strictly-encrypted + SRT_REJ_UNSECURE, // password required or unexpected SRT_REJ_MESSAGEAPI, // streamapi/messageapi collision SRT_REJ_CONGESTION, // incompatible congestion-controller type SRT_REJ_FILTER, // incompatible packet filter