diff --git a/apps/logsupport.cpp b/apps/logsupport.cpp index fbd70c47e..86deb1690 100644 --- a/apps/logsupport.cpp +++ b/apps/logsupport.cpp @@ -173,7 +173,7 @@ set SrtParseLogFA(string fa, set* punknown) void ParseLogFASpec(const vector& speclist, string& w_on, string& w_off) { - std::ostringstream son, soff; + srt::obufstream son, soff; for (auto& s: speclist) { diff --git a/apps/uriparser.cpp b/apps/uriparser.cpp index 6b8c80713..7425bca03 100644 --- a/apps/uriparser.cpp +++ b/apps/uriparser.cpp @@ -64,7 +64,7 @@ string UriParser::makeUri() prefix = m_proto + "://"; } - std::ostringstream out; + srt::obufstream out; out << prefix << m_host; if ((m_port == "" || m_port == "0") && m_expect == EXPECT_FILE) diff --git a/srtcore/api.cpp b/srtcore/api.cpp index ca26600d1..18234ab64 100644 --- a/srtcore/api.cpp +++ b/srtcore/api.cpp @@ -231,7 +231,7 @@ string srt::CUDTUnited::CONID(SRTSOCKET sock) if (sock == 0) return ""; - std::ostringstream os; + srt::obufstream os; os << "@" << sock << ":"; return os.str(); } @@ -1209,7 +1209,7 @@ int srt::CUDTUnited::connect(SRTSOCKET u, const sockaddr* srcname, const sockadd if (!srcname || !tarname || namelen < int(sizeof(sockaddr_in))) { LOGC(aclog.Error, - log << "connect(with source): invalid call: srcname=" << srcname << " tarname=" << tarname + log << "connect(with source): invalid call: srcname=" << (void*)srcname << " tarname=" << (void*)tarname << " namelen=" << namelen); throw CUDTException(MJ_NOTSUP, MN_INVAL); } @@ -1253,7 +1253,7 @@ int srt::CUDTUnited::connect(const SRTSOCKET u, const sockaddr* name, int namele { if (!name || namelen < int(sizeof(sockaddr_in))) { - LOGC(aclog.Error, log << "connect(): invalid call: name=" << name << " namelen=" << namelen); + LOGC(aclog.Error, log << "connect(): invalid call: name=" << (void*)name << " namelen=" << namelen); throw CUDTException(MJ_NOTSUP, MN_INVAL); } @@ -3249,7 +3249,7 @@ bool srt::CUDTUnited::updateListenerMux(CUDTSocket* s, const CUDTSocket* ls) CMultiplexer& m = i->second; #if ENABLE_HEAVY_LOGGING - ostringstream that_muxer; + srt::obufstream that_muxer; that_muxer << "id=" << m.m_iID << " port=" << m.m_iPort << " ip=" << (m.m_iIPversion == AF_INET ? "v4" : "v6"); #endif diff --git a/srtcore/channel.cpp b/srtcore/channel.cpp index 0a4e1e318..ca76182c3 100644 --- a/srtcore/channel.cpp +++ b/srtcore/channel.cpp @@ -1044,8 +1044,7 @@ srt::EReadStatus srt::CChannel::recvfrom(sockaddr_any& w_addr, CPacket& w_packet if (msg_flags != 0) { #if ENABLE_HEAVY_LOGGING - - std::ostringstream flg; + obufstream flg; #if !defined(_WIN32) @@ -1073,7 +1072,7 @@ srt::EReadStatus srt::CChannel::recvfrom(sockaddr_any& w_addr, CPacket& w_packet #endif HLOGC(krlog.Debug, - log << CONID() << "NET ERROR: packet size=" << recv_size << " msg_flags=0x" << hex << msg_flags + log << CONID() << "NET ERROR: packet size=" << recv_size << " msg_flags=0x" << sfmt(msg_flags, sfmc().hex()) << ", detected flags:" << flg.str()); #endif status = RST_AGAIN; diff --git a/srtcore/common.cpp b/srtcore/common.cpp index 6d747ecaa..5bc849248 100644 --- a/srtcore/common.cpp +++ b/srtcore/common.cpp @@ -277,15 +277,12 @@ void srt::CIPAddress::pton(sockaddr_any& w_addr, const uint32_t ip[4], const soc } else { - LOGC(inlog.Error, log << "pton: IPE or net error: can't determine IPv4 carryover format: " << std::hex - << peeraddr16[0] << ":" - << peeraddr16[1] << ":" - << peeraddr16[2] << ":" - << peeraddr16[3] << ":" - << peeraddr16[4] << ":" - << peeraddr16[5] << ":" - << peeraddr16[6] << ":" - << peeraddr16[7] << std::dec); + obufstream peeraddr_form; + peeraddr_form << sfmt(peeraddr16[0], "04x"); + for (int i = 1; i < 8; ++i) + peeraddr_form << ":" << sfmt(peeraddr16[i], "04x"); + + LOGC(inlog.Error, log << "pton: IPE or net error: can't determine IPv4 carryover format: " << peeraddr_form); *target_ipv4_addr = 0; if (peer.family() != AF_INET) { diff --git a/srtcore/common.h b/srtcore/common.h index 6a8912118..5c288d747 100644 --- a/srtcore/common.h +++ b/srtcore/common.h @@ -1437,7 +1437,7 @@ inline bool checkMappedIPv4(const sockaddr_in6& sa) inline std::string FormatLossArray(const std::vector< std::pair >& lra) { - std::ostringstream os; + obufstream os; os << "[ "; for (std::vector< std::pair >::const_iterator i = lra.begin(); i != lra.end(); ++i) diff --git a/srtcore/congctl.cpp b/srtcore/congctl.cpp index b9265c046..cd7d126f6 100644 --- a/srtcore/congctl.cpp +++ b/srtcore/congctl.cpp @@ -595,7 +595,7 @@ class FileCC : public SrtCongestionControlBase { m_dPktSndPeriod = m_dCWndSize / (m_parent->SRTT() + m_iRCInterval); HLOGC(cclog.Debug, log << "FileCC: CHKTIMER, SLOWSTART:OFF, sndperiod=" << m_dPktSndPeriod << "us AS wndsize/(RTT+RCIV) (wndsize=" - << setprecision(6) << m_dCWndSize << " RTT=" << m_parent->SRTT() << " RCIV=" << m_iRCInterval << ")"); + << sfmt(m_dCWndSize, ".6") << " RTT=" << m_parent->SRTT() << " RCIV=" << m_iRCInterval << ")"); } } else diff --git a/srtcore/core.cpp b/srtcore/core.cpp index 1612830e7..bb4c27c5d 100644 --- a/srtcore/core.cpp +++ b/srtcore/core.cpp @@ -92,6 +92,9 @@ using namespace srt_logging; const SRTSOCKET UDT::INVALID_SOCK = srt::CUDT::INVALID_SOCK; const int UDT::ERROR = srt::CUDT::ERROR; +static inline char fmt_onoff(bool val) { return val ? '+' : '-'; } +static inline const char* fmt_yesno(bool a) { return a ? "yes" : "no"; } + //#define SRT_CMD_HSREQ 1 /* SRT Handshake Request (sender) */ #define SRT_CMD_HSREQ_MINSZ 8 /* Minumum Compatible (1.x.x) packet size (bytes) */ #define SRT_CMD_HSREQ_SZ 12 /* Current version packet size */ @@ -1773,8 +1776,11 @@ bool srt::CUDT::createSrtHandshake( m_RejectReason = SRT_REJ_IPE; LOGC(cnlog.Error, log << CONID() << "createSrtHandshake: IPE: need to send KM, but CryptoControl does not exist." - << " Socket state: connected=" << boolalpha << m_bConnected << ", connecting=" << m_bConnecting - << ", broken=" << m_bBroken << ", closing=" << m_bClosing << "."); + << " Socket state: " + << fmt_onoff(m_bConnected) << "connected, " + << fmt_onoff(m_bConnecting) << "connecting, " + << fmt_onoff(m_bBroken) << "broken, " + << fmt_onoff(m_bClosing) << "closing."); return false; } @@ -2102,8 +2108,9 @@ int srt::CUDT::processSrtMsg_HSREQ(const uint32_t *srtdata, size_t bytelen, uint } LOGC(cnlog.Debug, log << "HSREQ/rcv: cmd=" << SRT_CMD_HSREQ << "(HSREQ) len=" << bytelen - << hex << " vers=0x" << srtdata[SRT_HS_VERSION] << " opts=0x" << srtdata[SRT_HS_FLAGS] - << dec << " delay=" << SRT_HS_LATENCY_RCV::unwrap(srtdata[SRT_HS_LATENCY])); + << " vers=0x" << sfmt(srtdata[SRT_HS_VERSION], "x") + << " opts=0x" << sfmt(srtdata[SRT_HS_FLAGS], "x") + << " delay=" << SRT_HS_LATENCY_RCV::unwrap(srtdata[SRT_HS_LATENCY])); m_uPeerSrtVersion = srtdata[SRT_HS_VERSION]; m_uPeerSrtFlags = srtdata[SRT_HS_FLAGS]; @@ -2337,8 +2344,8 @@ int srt::CUDT::processSrtMsg_HSRSP(const uint32_t *srtdata, size_t bytelen, uint m_uPeerSrtFlags = srtdata[SRT_HS_FLAGS]; HLOGC(cnlog.Debug, log << "HSRSP/rcv: Version: " << SrtVersionString(m_uPeerSrtVersion) - << " Flags: SND:" << setw(8) << setfill('0') << hex << m_uPeerSrtFlags - << setw(0) << " (" << SrtFlagString(m_uPeerSrtFlags) << ")"); + << " Flags: SND:" << sfmt(m_uPeerSrtFlags, "08x") + << " (" << SrtFlagString(m_uPeerSrtFlags) << ")"); // Basic version check if (m_uPeerSrtVersion < m_config.uMinimumPeerSrtVersion) { @@ -3140,7 +3147,7 @@ bool srt::CUDT::interpretGroup(const int32_t groupdata[], size_t data_size SRT_A HLOGC(cnlog.Debug, log << CONID() << "interpretGroup: STATE: HsSide=" << hs_side_name[m_SrtHsSide] << " HS MSG: " << MessageTypeStr(UMSG_EXT, hsreq_type_cmd) << " $" << grpid << " type=" << gtp - << " weight=" << link_weight << " flags=0x" << std::hex << link_flags); + << " weight=" << link_weight << " flags=0x" << sfmt(link_flags, sfmc().hex())); #endif // XXX Here are two separate possibilities: @@ -4101,8 +4108,12 @@ EConnectStatus srt::CUDT::craftKmResponse(uint32_t* aw_kmdata, size_t& w_kmdatas m_RejectReason = SRT_REJ_IPE; LOGC(cnlog.Error, log << CONID() << "IPE: craftKmResponse needs to send KM, but CryptoControl does not exist." - << " Socket state: connected=" << boolalpha << m_bConnected << ", connecting=" << m_bConnecting - << ", broken=" << m_bBroken << ", opened " << m_bOpened << ", closing=" << m_bClosing << "."); + << " Socket state: " + << fmt_onoff(m_bConnected) << "connected, " + << fmt_onoff(m_bConnecting) << "connecting, " + << fmt_onoff(m_bBroken) << "broken, " + << fmt_onoff(m_bOpened) << "opened, " + << fmt_onoff(m_bClosing) << "closing."); return CONN_REJECT; } // This is a periodic handshake update, so you need to extract the KM data from the @@ -4649,8 +4660,8 @@ EConnectStatus srt::CUDT::processConnectResponse(const CPacket& response, CUDTEx if (m_ConnRes.m_iReqType == URQ_INDUCTION) { HLOGC(cnlog.Debug, - log << CONID() << "processConnectResponse: REQ-TIME LOW; got INDUCTION HS response (cookie:" << hex - << m_ConnRes.m_iCookie << " version:" << dec << m_ConnRes.m_iVersion + log << CONID() << "processConnectResponse: REQ-TIME LOW; got INDUCTION HS response (cookie:" + << sfmt(m_ConnRes.m_iCookie, sfmc().hex()) << " version:" << m_ConnRes.m_iVersion << "), sending CONCLUSION HS with this cookie"); m_ConnReq.m_iCookie = m_ConnRes.m_iCookie; @@ -4757,7 +4768,8 @@ EConnectStatus srt::CUDT::postConnect(const CPacket* pResponse, bool rendezvous, // in rendezvous it's completed before calling this function. if (!rendezvous) { - HLOGC(cnlog.Debug, log << CONID() << boolalpha << "postConnect: packet:" << bool(pResponse) << " rendezvous:" << rendezvous); + HLOGC(cnlog.Debug, log << CONID() << "postConnect: packet:" + << fmt_yesno(pResponse) << " rendezvous:" << fmt_yesno(rendezvous)); // The "local storage depleted" case shouldn't happen here, but // this is a theoretical path that needs prevention. bool ok = pResponse; @@ -5460,14 +5472,14 @@ void * srt::CUDT::tsbpd(void* param) HLOGC(tslog.Debug, log << self->CONID() << "tsbpd: DROPSEQ: up to seqno %" << CSeqNo::decseq(info.seqno) << " (" << iDropCnt << " packets) playable at " << FormatTime(info.tsbpd_time) << " delayed " - << (timediff_us / 1000) << "." << std::setw(3) << std::setfill('0') << (timediff_us % 1000) << " ms"); + << (timediff_us / 1000) << "." << sfmt(timediff_us % 1000, "03") << " ms"); #endif string why; if (self->frequentLogAllowed(FREQLOGFA_RCV_DROPPED, tnow, (why))) { LOGC(brlog.Warn, log << self->CONID() << "RCV-DROPPED " << iDropCnt << " packet(s). Packet seqno %" << info.seqno - << " delayed for " << (timediff_us / 1000) << "." << std::setw(3) << std::setfill('0') - << (timediff_us % 1000) << " ms " << why); + << " delayed for " << (timediff_us / 1000) << "." + << sfmt(timediff_us % 1000, "03") << " ms " << why); } #if SRT_ENABLE_FREQUENT_LOG_TRACE else @@ -7149,7 +7161,7 @@ int srt::CUDT::receiveMessage(char* data, int len, SRT_MSGCTRL& w_mctrl, int by_ HLOGC(tslog.Debug, log << CONID() << "receiveMessage: fall asleep up to TS=" << FormatTime(exptime) - << " lock=" << (&m_RecvLock) << " cond=" << (&m_RecvDataCond)); + << " lock=" << ((void*)&m_RecvLock) << " cond=" << ((void*)&m_RecvDataCond)); if (!recv_cond.wait_until(exptime)) { @@ -7767,7 +7779,7 @@ bool srt::CUDT::updateCC(ETransmissionEvent evt, const EventVariant arg) HLOGC(rslog.Debug, log << CONID() << "updateCC: updated values from congctl: interval=" << FormatDuration(m_tdSendInterval) << " (cfg:" << m_CongCtl->pktSndPeriod_us() << "us) cgwindow=" - << std::setprecision(3) << cgwindow); + << sfmt(cgwindow, sfmc().precision(3))); #endif } @@ -8408,7 +8420,7 @@ void srt::CUDT::processCtrlAck(const CPacket &ctrlpkt, const steady_clock::time_ // included, but it also triggers for any other kind of invalid value. // This check MUST BE DONE before making any operation on this number. LOGC(inlog.Error, log << CONID() << "ACK: IPE/EPE: received invalid ACK value: " << ackdata_seqno - << " " << std::hex << ackdata_seqno << " (IGNORED)"); + << " " << sfmt(ackdata_seqno, "x") << " (IGNORED)"); return; } @@ -10002,12 +10014,11 @@ int srt::CUDT::checkLazySpawnTsbPdThread() HLOGP(qrlog.Debug, "Spawning Socket TSBPD thread"); #if ENABLE_HEAVY_LOGGING - std::ostringstream tns1, tns2; + obufstream buf; // Take the last 2 ciphers from the socket ID. - tns1 << setfill('0') << setw(2) << m_SocketID; - std::string s = tns1.str(); - tns2 << "SRT:TsbPd:@" << s.substr(s.size()-2, 2); - const string thname = tns2.str(); + string s = sfmts(m_SocketID, "02"); + buf << "SRT:TsbPd:@" << s.substr(s.size()-2, 2); + const string thname = buf.str(); #else const string thname = "SRT:TsbPd"; #endif @@ -11055,7 +11066,7 @@ int srt::CUDT::processConnectRequest(const sockaddr_any& addr, CPacket& packet) int32_t cookie_val = bake(addr); - HLOGC(cnlog.Debug, log << CONID() << "processConnectRequest: new cookie: " << hex << cookie_val); + HLOGC(cnlog.Debug, log << CONID() << "processConnectRequest: new cookie: " << sfmt(cookie_val, sfmc().hex())); // Remember the incoming destination address here and use it as a source // address when responding. It's not possible to record this address yet @@ -11135,7 +11146,7 @@ int srt::CUDT::processConnectRequest(const sockaddr_any& addr, CPacket& packet) if (hs.m_iCookie != cookie_val) { m_RejectReason = SRT_REJ_RDVCOOKIE; - HLOGC(cnlog.Debug, log << CONID() << "processConnectRequest: ...wrong cookie " << hex << cookie_val << ". Ignoring."); + HLOGC(cnlog.Debug, log << CONID() << "processConnectRequest: ...wrong cookie " << sfmt(cookie_val, sfmc().hex()) << ". Ignoring."); return m_RejectReason; } diff --git a/srtcore/fec.cpp b/srtcore/fec.cpp index fd762b88b..abbdd22aa 100644 --- a/srtcore/fec.cpp +++ b/srtcore/fec.cpp @@ -533,13 +533,14 @@ void FECFilterBuiltin::ClipPacket(Group& g, const CPacket& pkt) ClipData(g, length_net, kflg, timestamp_hw, pkt.data(), pkt.size()); - HLOGC(pflog.Debug, log << "FEC DATA PKT CLIP: " << hex - << "FLAGS=" << unsigned(kflg) << " LENGTH[ne]=" << (length_net) - << " TS[he]=" << timestamp_hw - << " CLIP STATE: FLAGS=" << unsigned(g.flag_clip) - << " LENGTH[ne]=" << g.length_clip - << " TS[he]=" << g.timestamp_clip - << " PL4=" << (*(uint32_t*)&g.payload_clip[0])); + HLOGC(pflog.Debug, log << "FEC DATA PKT CLIP: " + << "FLAGS=" << sfmt(kflg, sfmc().hex()) + << " LENGTH[ne]=" << sfmt(length_net, sfmc().hex()) + << " TS[he]=" << sfmt(timestamp_hw, sfmc().hex()) + << " CLIP STATE: FLAGS=" << sfmt(g.flag_clip, sfmc().hex()) + << " LENGTH[ne]=" << sfmt(g.length_clip, sfmc().hex()) + << " TS[he]=" << sfmt(g.timestamp_clip, sfmc().hex()) + << " PL4=" << sfmt(*(uint32_t*)&g.payload_clip[0], sfmc().hex())); } // Clipping a control packet does merely the same, just the packet has @@ -560,13 +561,14 @@ void FECFilterBuiltin::ClipControlPacket(Group& g, const CPacket& pkt) ClipData(g, *length_clip, *flag_clip, timestamp_hw, payload, payload_clip_len); - HLOGC(pflog.Debug, log << "FEC/CTL CLIP: " << hex - << "FLAGS=" << unsigned(*flag_clip) << " LENGTH[ne]=" << (*length_clip) - << " TS[he]=" << timestamp_hw - << " CLIP STATE: FLAGS=" << unsigned(g.flag_clip) - << " LENGTH[ne]=" << g.length_clip - << " TS[he]=" << g.timestamp_clip - << " PL4=" << (*(uint32_t*)&g.payload_clip[0])); + HLOGC(pflog.Debug, log << "FEC/CTL CLIP: " + << "FLAGS=" << sfmt(*flag_clip, sfmc().hex()) + << " LENGTH[ne]=" << sfmt(*length_clip, sfmc().hex()) + << " TS[he]=" << sfmt(timestamp_hw, sfmc().hex()) + << " CLIP STATE: FLAGS=" << sfmt(g.flag_clip, sfmc().hex()) + << " LENGTH[ne]=" << sfmt(g.length_clip, sfmc().hex()) + << " TS[he]=" << sfmt(g.timestamp_clip, sfmc().hex()) + << " PL4=" << sfmt(*(uint32_t*)&g.payload_clip[0], sfmc().hex())); } void FECFilterBuiltin::ClipRebuiltPacket(Group& g, Receive::PrivPacket& pkt) @@ -582,13 +584,14 @@ void FECFilterBuiltin::ClipRebuiltPacket(Group& g, Receive::PrivPacket& pkt) ClipData(g, length_net, kflg, timestamp_hw, pkt.buffer, pkt.length); - HLOGC(pflog.Debug, log << "FEC REBUILT DATA CLIP: " << hex - << "FLAGS=" << unsigned(kflg) << " LENGTH[ne]=" << (length_net) - << " TS[he]=" << timestamp_hw - << " CLIP STATE: FLAGS=" << unsigned(g.flag_clip) - << " LENGTH[ne]=" << g.length_clip - << " TS[he]=" << g.timestamp_clip - << " PL4=" << (*(uint32_t*)&g.payload_clip[0])); + HLOGC(pflog.Debug, log << "FEC REBUILT DATA CLIP: " + << "FLAGS=" << sfmt(kflg, sfmc().hex()) + << " LENGTH[ne]=" << sfmt(length_net, sfmc().hex()) + << " TS[he]=" << sfmt(timestamp_hw, sfmc().hex()) + << " CLIP STATE: FLAGS=" << sfmt(g.flag_clip, sfmc().hex()) + << " LENGTH[ne]=" << sfmt(g.length_clip, sfmc().hex()) + << " TS[he]=" << sfmt(g.timestamp_clip, sfmc().hex()) + << " PL4=" << sfmt(*(uint32_t*)&g.payload_clip[0], sfmc().hex())); } void FECFilterBuiltin::ClipData(Group& g, uint16_t length_net, uint8_t kflg, @@ -765,11 +768,11 @@ void FECFilterBuiltin::PackControl(const Group& g, signed char index, SrtPacket& HLOGC(pflog.Debug, log << "FEC: PackControl: hdr(" << (total_size - g.payload_clip.size()) << "): INDEX=" - << int(index) << " LENGTH[ne]=" << hex << g.length_clip - << " FLAGS=" << int(g.flag_clip) << " TS=" << g.timestamp_clip - << " PL(" << dec << g.payload_clip.size() << ")[0-4]=" << hex - << (*(uint32_t*)&g.payload_clip[0])); - + << int(index) << " LENGTH[ne]=" << sfmt(g.length_clip, sfmc().hex()) + << " FLAGS=" << sfmt(g.flag_clip, sfmc().hex()) + << " TS=" << sfmt(g.timestamp_clip, sfmc().hex()) + << " PL(" << g.payload_clip.size() << ")[0-4]=" + << sfmt(*(uint32_t*)&g.payload_clip[0], sfmc().hex())); } bool FECFilterBuiltin::receive(const CPacket& rpkt, loss_seqs_t& loss_seqs) @@ -1464,7 +1467,7 @@ void FECFilterBuiltin::RcvRebuild(Group& g, int32_t seqno, Group::Type tp) HLOGC(pflog.Debug, log << "FEC: REBUILT: %" << seqno << " msgno=" << MSGNO_SEQ::unwrap(p.hdr[SRT_PH_MSGNO]) << " flags=" << PacketMessageFlagStr(p.hdr[SRT_PH_MSGNO]) - << " TS=" << p.hdr[SRT_PH_TIMESTAMP] << " ID=" << dec << p.hdr[SRT_PH_ID] + << " TS=" << p.hdr[SRT_PH_TIMESTAMP] << " ID=" << p.hdr[SRT_PH_ID] << " size=" << length_hw << " !" << BufferStamp(p.buffer, p.length)); diff --git a/srtcore/group.cpp b/srtcore/group.cpp index 3e57ef5df..b036b1f2b 100644 --- a/srtcore/group.cpp +++ b/srtcore/group.cpp @@ -15,6 +15,8 @@ extern const int32_t SRT_DEF_VERSION; namespace srt { +static inline char fmt_onoff(bool val) { return val ? '+' : '-'; } + int32_t CUDTGroup::s_tokenGen = 0; // [[using locked(this->m_GroupLock)]]; @@ -2190,8 +2192,8 @@ int CUDTGroup::recv(char* buf, int len, SRT_MSGCTRL& w_mc) if (!m_bOpened || !m_bConnected) { LOGC(grlog.Error, - log << boolalpha << "grp/recv: $" << id() << ": ABANDONING: opened=" << m_bOpened - << " connected=" << m_bConnected); + log << "grp/recv: $" << id() << ": ABANDONING: opened" << fmt_onoff(m_bOpened) + << " connected" << fmt_onoff(m_bConnected)); throw CUDTException(MJ_CONNECTION, MN_NOCONN, 0); } diff --git a/srtcore/logging.cpp b/srtcore/logging.cpp index d0ba3fd4a..e76e6db9a 100644 --- a/srtcore/logging.cpp +++ b/srtcore/logging.cpp @@ -43,7 +43,7 @@ LogDispatcher::Proxy LogDispatcher::operator()() return Proxy(*this); } -void LogDispatcher::CreateLogLinePrefix(std::ostringstream& serr) +void LogDispatcher::CreateLogLinePrefix(srt::obufstream& serr) { using namespace std; using namespace srt; @@ -60,7 +60,7 @@ void LogDispatcher::CreateLogLinePrefix(std::ostringstream& serr) if (strftime(tmp_buf, sizeof(tmp_buf), "%X.", &tm)) { - serr << tmp_buf << setw(6) << setfill('0') << tv.tv_usec; + serr << tmp_buf << srt::sfmt(tv.tv_usec, "06"); } } diff --git a/srtcore/logging.h b/srtcore/logging.h index 2ec5f46aa..cefa5b7ce 100644 --- a/srtcore/logging.h +++ b/srtcore/logging.h @@ -20,7 +20,6 @@ written by #include #include #include -#include #include #ifdef _WIN32 #include "win/wintime.h" @@ -29,6 +28,8 @@ written by #include #endif +#include "srt_sfmt.h" + #include "srt.h" #include "utilities.h" #include "threadname.h" @@ -192,7 +193,7 @@ struct SRT_API LogDispatcher bool CheckEnabled(); - void CreateLogLinePrefix(std::ostringstream&); + void CreateLogLinePrefix(srt::obufstream&); void SendLogLine(const char* file, int line, const std::string& area, const std::string& sl); // log.Debug("This is the ", nth, " time"); <--- C++11 only. @@ -285,7 +286,7 @@ struct LogDispatcher::Proxy { LogDispatcher& that; - std::ostringstream os; + srt::obufstream os; // Cache the 'enabled' state in the beginning. If the logging // becomes enabled or disabled in the middle of the log, we don't @@ -336,12 +337,49 @@ struct LogDispatcher::Proxy return *this; } + // Special case for atomics, as passing them to snprintf() call + // requires unpacking the real underlying value. + template + Proxy& operator<<(const srt::sync::atomic& arg) + { + if (that_enabled) + { + os << arg.load(); + } + return *this; + } + + +#if HAVE_CXX11 + + void dispatch() {} + + template + void dispatch(const Arg1& a1, const Args&... others) + { + *this << a1; + dispatch(others...); + } + + // Special dispatching for atomics must be provided here. + // By some reason, "*this << a1" expression gets dispatched + // to the general version of operator<<, not the overload for + // atomic. Even though the compiler shows Arg1 type as atomic. + template + void dispatch(const srt::sync::atomic& a1, const Args&... others) + { + *this << a1.load(); + dispatch(others...); + } + +#endif + ~Proxy() { - if ( that_enabled ) + if (that_enabled) { - if ( (flags & SRT_LOGF_DISABLE_EOL) == 0 ) - os << std::endl; + if ((flags & SRT_LOGF_DISABLE_EOL) == 0) + os << srt::seol; that.SendLogLine(i_file, i_line, area, os.str()); } // Needed in destructor? @@ -435,28 +473,28 @@ inline bool LogDispatcher::CheckEnabled() //extern std::mutex Debug_mutex; -inline void PrintArgs(std::ostream&) {} +inline void PrintArgs(srt::obufstream&) {} template -inline void PrintArgs(std::ostream& serr, Arg1&& arg1, Args&&... args) +inline void PrintArgs(srt::obufstream& serr, Arg1&& arg1, Args&&... args) { serr << std::forward(arg1); PrintArgs(serr, args...); } +// Add exceptional handling for sync::atomic +template +inline void PrintArgs(srt::obufstream& serr, const srt::sync::atomic& arg1, Args&&... args) +{ + serr << arg1.load(); + PrintArgs(serr, args...); +} + template inline void LogDispatcher::PrintLogLine(const char* file SRT_ATR_UNUSED, int line SRT_ATR_UNUSED, const std::string& area SRT_ATR_UNUSED, Args&&... args SRT_ATR_UNUSED) { #ifdef ENABLE_LOGGING - std::ostringstream serr; - CreateLogLinePrefix(serr); - PrintArgs(serr, args...); - - if ( !isset(SRT_LOGF_DISABLE_EOL) ) - serr << std::endl; - - // Not sure, but it wasn't ever used. - SendLogLine(file, line, area, serr.str()); + Proxy(*this).dispatch(args...); #endif } @@ -466,15 +504,7 @@ template inline void LogDispatcher::PrintLogLine(const char* file SRT_ATR_UNUSED, int line SRT_ATR_UNUSED, const std::string& area SRT_ATR_UNUSED, const Arg& arg SRT_ATR_UNUSED) { #ifdef ENABLE_LOGGING - std::ostringstream serr; - CreateLogLinePrefix(serr); - serr << arg; - - if ( !isset(SRT_LOGF_DISABLE_EOL) ) - serr << std::endl; - - // Not sure, but it wasn't ever used. - SendLogLine(file, line, area, serr.str()); + Proxy(*this) << arg; #endif } diff --git a/srtcore/queue.cpp b/srtcore/queue.cpp index 98999a81f..43f7349fc 100644 --- a/srtcore/queue.cpp +++ b/srtcore/queue.cpp @@ -1078,8 +1078,8 @@ bool srt::CRendezvousQueue::qualifyToHandle(EReadStatus rst, else { HLOGC(cnlog.Debug, - log << "RID: socket @" << i->m_iID << " still active (remaining " << std::fixed - << (count_microseconds(i->m_tsTTL - tsNow) / 1000000.0) << "s of TTL)..."); + log << "RID: socket @" << i->m_iID << " still active (remaining " + << sfmt(count_microseconds(i->m_tsTTL - tsNow) / 1000000.0, "f") << "s of TTL)..."); } const steady_clock::time_point tsLastReq = i->m_pUDT->m_tsLastReqTime; diff --git a/srtcore/queue.h b/srtcore/queue.h index dd68a7721..055671e95 100644 --- a/srtcore/queue.h +++ b/srtcore/queue.h @@ -592,6 +592,10 @@ struct CMultiplexer , m_pRcvQueue(NULL) , m_pChannel(NULL) , m_pTimer(NULL) + , m_iPort(0) + , m_iIPversion(0) + , m_iRefCount(1) + , m_iID(-1) { } diff --git a/srtcore/socketconfig.cpp b/srtcore/socketconfig.cpp index d44330f78..6d1acf754 100644 --- a/srtcore/socketconfig.cpp +++ b/srtcore/socketconfig.cpp @@ -744,8 +744,8 @@ struct CSrtConfigSetter { co.uKmPreAnnouncePkt = (km_refresh - 1) / 2; LOGC(aclog.Warn, - log << "SRTO_KMREFRESHRATE=0x" << std::hex << km_refresh << ": setting SRTO_KMPREANNOUNCE=0x" - << std::hex << co.uKmPreAnnouncePkt); + log << "SRTO_KMREFRESHRATE=0x" << sfmt(km_refresh, "x") << ": setting SRTO_KMPREANNOUNCE=0x" + << sfmt(co.uKmPreAnnouncePkt, "x")); } } }; @@ -770,7 +770,8 @@ struct CSrtConfigSetter if (km_preanno > (kmref - 1) / 2) { LOGC(aclog.Error, - log << "SRTO_KMPREANNOUNCE=0x" << std::hex << km_preanno << " exceeds KmRefresh/2, 0x" << ((kmref - 1) / 2) + log << "SRTO_KMPREANNOUNCE=0x" << sfmt(km_preanno, "x") + << " exceeds KmRefresh/2, 0x" << sfmt((kmref - 1) / 2, "x") << " - OPTION REJECTED."); throw CUDTException(MJ_NOTSUP, MN_INVAL, 0); } diff --git a/srtcore/srt_sfmt.h b/srtcore/srt_sfmt.h new file mode 100644 index 000000000..1c719042d --- /dev/null +++ b/srtcore/srt_sfmt.h @@ -0,0 +1,1057 @@ +// SOURCE NOTE: +// +// This is copied directly from a public-domain library: +// +// URI: https://github.com/ethouris/fmt +// PATH: include/fmt/sfmt.h +// +// with slight modifications. +// +// Formatting library for C++ - C++03 compat version of on-demand tagged format API. +// +// Copyright (c) 2024 - present, Mikołaj Małecki +// All rights reserved. +// +// For the license information refer to format.h. + +// This is a header-only lightweight C++03-compatible formatting library, +// which provides the on-demand tagged format API and iostream-style wrapper +// for FILE type from stdio. It has nothing to do with the rest of the {fmt} +// library, except that it reuses the namespace. + +#ifndef INC_FMT_SFMT_H +#define INC_FMT_SFMT_H + +#include +#include +#include // std::abs +#include // std::div +#include +#include +#include + +namespace srt +{ + +namespace internal +{ + +template +class form_memory_buffer +{ +public: + static const size_t INITIAL_SIZE = PARAM_INITIAL_SIZE; + typedef std::list< std::vector > slices_t; + +private: + char first[INITIAL_SIZE]; + slices_t slices; + + size_t initial; // size used in `first` + size_t reserved; // total size plus slices in reserve + size_t total; // total size in use + +public: + form_memory_buffer(): initial(0), reserved(0), total(0) {} + + // For constants + template + form_memory_buffer(const char (&array)[N]): initial(N-1), reserved(N-1), total(N-1) + { + memcpy(first, array, N); + } + + size_t avail() + { + return reserved - total; + } + + char* get_first() { return first; } + const char* get_first() const { return first; } + size_t first_size() const { return initial; } + const slices_t& get_slices() const { return slices; } + size_t size() const { return total; } + bool empty() const { return total == 0; } + + void append(char c) + { + char wrap[1] = {c}; + append(wrap, 1); + } + + // NOTE: append ignores the reservation. It writes + // where the currently available space is. Use expose() + // and commit() together or not at all. + void append(const char* val, size_t size) + { + if (size == 0) + return; + + if (slices.empty()) + { + if (size < INITIAL_SIZE - initial) + { + // Still free space in first. + memcpy(first + initial, val, size); + initial += size; + total = initial; + if (reserved < total) + reserved = total; + return; + } + } + + slices.push_back(std::vector(val, val+size)); + total += size; + if (reserved < total) + reserved = total; + } + + char* expose(size_t size) + { + // Repeated exposure simply extends the + // reservation, if required more, or is ignored, + // if required less. + + // Note that ort + + size_t already_reserved = reserved - total; + if (already_reserved >= size) + { + // Identify the reserved region + if (slices.empty()) + { + reserved = total + size; + return first + initial; + } + + std::vector& last = slices.back(); + // Exceptionally resize that part if it doesn't + // fit. + if (last.size() != size) + last.resize(size); + reserved = total + size; + return &last[0]; + } + + // Check if you have any size available + // beyond the current reserved space. + // If not, allocate. + if (slices.empty()) + { + // Not yet resolved to use of the slices, + // so check free space in first. The value of + // 'reserved' should be still < INITIAL_SIZE. + if (INITIAL_SIZE - total >= size) + { + char* b = first + total; + reserved = total + size; + return b; + } + } + + // Otherwise allocate a new slice + // Check first if the last slice was already reserved + std::vector* plast = &slices.back(); + if (!already_reserved) + { + slices.push_back( std::vector() ); + plast = &slices.back(); + } + + plast->reserve(size); + plast->resize(size); + reserved = total + size; + return &(*plast)[0]; + } + + // Remove the last 'size' chars from reservation + bool unreserve(size_t size) + { + if (size > reserved - total) + return false; + + if (!slices.empty()) + { + // Check the last slice if it contains that size + std::vector& last = slices.back(); + if (last.size() < size) + return false; + + size_t remain = last.size() - size; + if (!remain) + { + slices.pop_back(); + reserved -= size; + return true; + } + + last.erase(last.begin() + remain, last.end()); + } + // Otherwise the space is in the initial buffer. + + reserved -= size; + return true; + } + + void commit() + { + total = reserved; + if (slices.empty()) + { + // This means we don't use extra slices, so + // this size must be also repeated in initial + initial = reserved; + } + } + + void clear() + { + slices.clear(); + total = 0; + reserved = 0; + initial = 0; + } +}; + +template +struct CheckChar +{ + static bool is(char c, const char (&series)[N]) + { + return c == series[I] || CheckChar::is(c, series); + } +}; + +template +struct CheckChar +{ + // Terminal version - if none interrupted with true, + // eventually return false. + static bool is(char , const char (&)[N]) { return false; } +}; + +template inline +bool isanyof(char c, const char (&series)[N]) +{ + return CheckChar::is(c, series); +} + +template inline +bool isnum_or(char c, const char (&series)[N]) +{ + if (c >= '0' && c <= '9') + return true; + return isanyof(c, series); +} + +template +struct Ensure +{ +}; + +template +struct Ensure +{ + static void CheckIfCharsetNonEmpty() + { + typename AnyType::wrong_condition v = AnyType::wrong_condition; + (void)v; + } +}; + +template inline +form_memory_buffer<> fix_format(const char* fmt, + const char (&allowed)[N1], + const char (&typed)[N2], + const char (&deftype)[N3], + const char* warn) +{ + // All these arrays must contain at least 2 elements, + // that is one character and terminating zero. + //Ensure= 2> c1; + Ensure= 2)> c2; (void)c2; + Ensure= 2)> c3; (void)c3; + + form_memory_buffer<> buf; + buf.append('%'); + + bool warn_error = false; + if (fmt) + { + size_t len = strlen(fmt); + for (size_t i = 0; i < len; ++i) + { + char c = fmt[i]; + if (internal::isnum_or(c, allowed)) + { + buf.append(c); + continue; + } + + if (internal::isanyof(c, typed)) + { + // If you have found any numbase character, + // add first all characters from the default, + // EXCEPT the last one. + buf.append(deftype, N3-2); + + // that's it, and we're done here. + buf.append(c); + return buf; + } + + // If any other character is found, add the warning + warn_error = true; + break; + } + } + + buf.append(deftype, N3); + + if (warn_error && warn) + { + buf.append(warn, strlen(warn)); + } + return buf; +} + + +#define SFMT_FORMAT_FIXER(TYPE, ALLOWED, TYPED, DEFTYPE, WARN) \ +inline form_memory_buffer<> apply_format_fix(TYPE, const char* fmt) \ +{ \ + return fix_format(fmt, ALLOWED, TYPED, DEFTYPE, WARN); \ +} + +#define SFMT_FORMAT_FIXER_TPL(TPAR, TYPE, ALLOWED, TYPED, DEFTYPE, WARN) \ +template\ +inline form_memory_buffer<> apply_format_fix(TYPE, const char* fmt)\ +{\ + return fix_format(fmt, ALLOWED, TYPED, DEFTYPE, WARN); \ +} + + + +// So, format in the format spec is: +// +// (missing): add the default format +// Using: diouxX - specify the numeric base +// Using efg - specify the float style + +// Modifiers like "h", "l", or "L" shall not +// be used. They will be inserted if needed. + +SFMT_FORMAT_FIXER(int, "+- '#", "dioxX", "i", ""); +SFMT_FORMAT_FIXER(short int, "+- '#", "dioxX", "hi", ""); +SFMT_FORMAT_FIXER(long int, "+- '#", "dioxX", "li", ""); +SFMT_FORMAT_FIXER(long long int, "+- '#", "dioxX", "lli", ""); + +SFMT_FORMAT_FIXER(unsigned int, "+- '#", "uoxX", "u", ""); +SFMT_FORMAT_FIXER(unsigned short int, "+- '#", "uoxX", "hu", ""); +SFMT_FORMAT_FIXER(unsigned long int, "+- '#", "uoxX", "lu", ""); +SFMT_FORMAT_FIXER(unsigned long long int, "+- '#", "uoxX", "llu", ""); + +SFMT_FORMAT_FIXER(double, "+- '#.", "EeFfgGaA", "g", ""); +SFMT_FORMAT_FIXER(float, "+- '#.", "EeFfgGaA", "g", ""); +SFMT_FORMAT_FIXER(long double, "+- '#.", "EeFfgGaA", "Lg", ""); + +SFMT_FORMAT_FIXER(char, "-", "c", "c", ""); + +SFMT_FORMAT_FIXER(std::string, "-.", "s", "s", ""); +SFMT_FORMAT_FIXER(const char*, "-.", "s", "s", ""); +SFMT_FORMAT_FIXER(char*, "-.", "s", "s", ""); +SFMT_FORMAT_FIXER_TPL(size_t N, const char (&)[N], "-.", "s", "s", ""); +SFMT_FORMAT_FIXER_TPL(size_t N, char (&)[N], "-.", "s", "s", ""); +SFMT_FORMAT_FIXER(void*, "-", "p", "p", ""); +SFMT_FORMAT_FIXER(const void*, "-", "p", "p", ""); + +#undef SFMT_FORMAT_FIXER_TPL +#undef SFMT_FORMAT_FIXER + +template +struct const_copy +{ + static void copy(char* target, const char *source) + { + *target = *source; + return const_copy::copy(target + 1, source + 1); + } +}; + +template<> +struct const_copy<1> // 1 because the last item is the terminal '\0'. +{ + static void copy(char*, const char *) { } // do nothing, terminal value +}; + +// These maps must cover all allowed values, for safety. +static const char present_int_map[8] = { 'i', 'o', 'x', 'X', 'd', 'd', 'd', 'd'}; +static const char present_float_map[8] = { 'g', 'G', 'a', 'A', 'e', 'E', 'f', 'g' }; + +} + +struct sfmc +{ + enum postype { pos_no, pos_plus, pos_space, pos_invalid }; + enum flavor { + flavor_dec = 0, + flavor_oct = 1, + flavor_hex = 2, + flavor_uhex = 3, + + flavor_general = 0, + flavor_ugeneral = 1, + flavor_fhex = 2, + flavor_ufhex = 3, + flavor_scientific = 4, + flavor_uscientific = 5, + flavor_fixed = 6 + }; + +protected: + short widthval; + short precisionval; + bool widthbit:1; + bool precisionbit:1; + bool altbit:1; + bool leftbit:1; + bool leadzerobit:1; + postype postype:2; + flavor presentation:3; + bool localized:1; + +public: + sfmc(): + widthval(0), + precisionval(6), + widthbit(false), + precisionbit(false), + altbit(false), + leftbit(false), + leadzerobit(false), + postype(pos_no), + presentation(flavor_dec), + localized(false) + { + } + +#define SFMTC_TAG(name, body) sfmc& name () { body; return *this; } +#define SFMTC_TAG_VAL(name, body) sfmc& name (int val) { body; return *this; } + + SFMTC_TAG(alt, altbit = true); + SFMTC_TAG(left, leftbit = true); + SFMTC_TAG(right, (void)0); + SFMTC_TAG_VAL(width, widthbit = true; widthval = std::abs(val)); + SFMTC_TAG_VAL(precision, precisionbit = true; precisionval = std::abs(val)); + SFMTC_TAG(dec, (void)0); + SFMTC_TAG(hex, presentation = flavor_hex); + SFMTC_TAG(oct, presentation = flavor_oct); + SFMTC_TAG(uhex, presentation = flavor_uhex); + SFMTC_TAG(general, (void)0); + SFMTC_TAG(ugeneral, presentation = flavor_ugeneral); + SFMTC_TAG(fhex, presentation = flavor_fhex); + SFMTC_TAG(ufhex, presentation = flavor_ufhex); + SFMTC_TAG(exp, presentation = flavor_scientific); + SFMTC_TAG(uexp, presentation = flavor_uscientific); + SFMTC_TAG(scientific, presentation = flavor_scientific); + SFMTC_TAG(uscientific, presentation = flavor_uscientific); + SFMTC_TAG(fixed, presentation = flavor_fixed); + SFMTC_TAG(nopos, (void)0); + SFMTC_TAG(posspace, postype = pos_space); + SFMTC_TAG(posplus, postype = pos_plus); + SFMTC_TAG(fillzero, leadzerobit = true); + +#undef SFMTC_TAG +#undef SFMTC_TAG_VAL + + // Utility function to store the number for width/precision + // For C++11 it could be constexpr, but this is C++03-compat code. + // It's bound to this structure because it's unsafe. + static std::size_t store_number(char* position, int number) + { + std::size_t shiftpos = 0; + std::div_t dm = std::div(number, 10); + if (dm.quot) + shiftpos = store_number(position, dm.quot); + position[shiftpos] = '0' + dm.rem; + return shiftpos + 1; + } + + template + internal::form_memory_buffer<> create_format_int(const char (&lnspec)[N]) const + { + using namespace internal; + + Ensure= 2)> c3; (void)c3; + + form_memory_buffer<> form; + + // Use reservation as this will be faster and also + // we don't know how many ciphers will be taken by width/precision + // We need to reserve 12 + 12 + 4 + 4 = 32. + char* buf = form.expose(32); + size_t used = 0; + buf[used++] = '%'; + + if (altbit) + buf[used++] = '#'; + + if (leftbit) + buf[used++] = '-'; + + if (localized) + buf[used++] = '\''; + + if (leadzerobit) + buf[used++] = '0'; + + if (widthbit) + { + size_t w = store_number(buf + used, widthval); + used += w; + } + + // That's it, now we copy the type length modifier + const_copy::copy(buf + used, lnspec); + used += (N - 2); + + // And finally the flavor modifier + if (int(presentation) == 0) + buf[used++] = lnspec[N-2]; + else + buf[used++] = present_int_map[presentation]; + buf[used] = '\0'; + + size_t unused = 32 - used; + if (unused > 0) + form.unreserve(unused); + form.commit(); + + return form; + } + + template + internal::form_memory_buffer<> create_format_float(const char (&lnspec)[N]) const + { + using namespace internal; + Ensure= 2> c3; (void)c3; + + form_memory_buffer<> form; + + // Use reservation as this will be faster and also + // we don't know how many ciphers will be taken by width/precision + // We need to reserve 12 + 12 + 4 + 4 = 32. + char* buf = form.expose(32); + size_t used = 0; + buf[used++] = '%'; + + if (altbit) + buf[used++] = '#'; + + if (leftbit) + buf[used++] = '-'; + + if (localized) + buf[used++] = '\''; + + if (leadzerobit) + buf[used++] = '0'; + + if (widthbit) + { + size_t w = store_number(buf + used, widthval); + used += w; + } + + if (precisionbit) + { + buf[used++] = '.'; + size_t w = store_number(buf + used, precisionval); + used += w; + } + + // That's it, now we copy the type length modifier + const_copy::copy(buf + used, lnspec); + used += (N - 2); + + // And finally the flavor modifier + if (int(presentation) == 0) + buf[used++] = lnspec[N-2]; + else + buf[used++] = present_float_map[presentation]; + buf[used] = '\0'; + + size_t unused = 32 - used; + if (unused > 0) + form.unreserve(unused); + form.commit(); + + return form; + } + + internal::form_memory_buffer<> create_format(int) const { return create_format_int("i"); } + internal::form_memory_buffer<> create_format(short int) const { return create_format_int("hi"); }; + internal::form_memory_buffer<> create_format(long int) const { return create_format_int("li"); }; + internal::form_memory_buffer<> create_format(long long int) const { return create_format_int("lli"); }; + + internal::form_memory_buffer<> create_format(unsigned int) const { return create_format_int("u"); }; + internal::form_memory_buffer<> create_format(unsigned short int) const { return create_format_int("hu"); }; + internal::form_memory_buffer<> create_format(unsigned long int) const { return create_format_int("lu"); }; + internal::form_memory_buffer<> create_format(unsigned long long int) const { return create_format_int("llu"); }; + + internal::form_memory_buffer<> create_format(double) const { return create_format_float("g"); }; + internal::form_memory_buffer<> create_format(float) const { return create_format_float("g"); }; + internal::form_memory_buffer<> create_format(long double) const { return create_format_float("Lg"); }; + + internal::form_memory_buffer<> create_format(char) const + { + internal::form_memory_buffer<> form; + form.append("%c", 3); + return form; + } + + internal::form_memory_buffer<> create_format_string() const + { + using namespace internal; + + form_memory_buffer<> form; + + // Use reservation as this will be faster and also + // we don't know how many ciphers will be taken by width/precision + // We need to reserve 12 + 12 + 4 + 4 = 32. + char* buf = form.expose(32); + size_t used = 0; + buf[used++] = '%'; + + if (leftbit) + buf[used++] = '-'; + + if (widthbit) + { + size_t w = store_number(buf + used, widthval); + used += w; + } + + if (precisionbit) + { + buf[used++] = '.'; + size_t w = store_number(buf + used, precisionval); + used += w; + } + + // No modifier supported + // XXX NOTE: wchar_t therefore not supported! + buf[used++] = 's'; + buf[used] = '\0'; + + size_t unused = 32 - used; + if (unused > 0) + form.unreserve(unused); + form.commit(); + + return form; + } + + internal::form_memory_buffer<> create_format(char*) const { return create_format_string(); }; + internal::form_memory_buffer<> create_format(const char*) const { return create_format_string(); }; + internal::form_memory_buffer<> create_format(std::string) const { return create_format_string(); }; +}; + +// fmt(val, sfmc().alt().hex().width(10)) + +namespace internal +{ + +template inline +void write_default(Stream& str, const Value& val); + +} + +class ostdiostream +{ +protected: + mutable FILE* in; + +public: + + FILE* raw() const { return in; } + + ostdiostream(FILE* f): in(f) {} + + ostdiostream& operator<<(const char* t) + { + std::fputs(t, in); + return *this; + } + + ostdiostream& operator<<(const std::string& s) + { + std::fputs(s.c_str(), in); + return *this; + } + + template + ostdiostream& operator<<(const internal::form_memory_buffer& b) + { + using namespace internal; + // Copy all pieces one by one + if (b.size() == 0) + return *this; + + std::fwrite(b.get_first(), 1, b.first_size(), in); + for (form_memory_buffer<>::slices_t::const_iterator i = b.get_slices().begin(); + i != b.get_slices().end(); ++i) + { + const char* data = &(*i)[0]; + std::fwrite(data, 1, i->size(), in); + } + return *this; + } + + template + ostdiostream& operator<<(const Value& v) + { + internal::write_default(*this, v); + return *this; + } +}; + + +class ofilestream: public ostdiostream +{ +public: + + ofilestream(): ostdiostream(0) {} + + ofilestream(const std::string& name, const std::string& mode = "") + : ostdiostream(0) // Set NULL initially, but then override + { + open(name, mode); + } + + bool good() const { return in; } + + void open(const std::string& name, const std::string& mode = "") + { + if (mode == "") + in = std::fopen(name.c_str(), "w"); + else + in = std::fopen(name.c_str(), mode.c_str()); + } + + // For the use of other functions than fopen() that can create the stream, + // but they still create FILE* that should be closed using fclose(). + void attach(FILE* other) + { + in = other; + } + + FILE* detach() + { + FILE* sav = in; + in = 0; + return sav; + } + + int close() + { + int retval = 0; + if (in) + { + retval = std::fclose(in); + in = 0; + } + return retval; + } + + ~ofilestream() + { + if (in) + std::fclose(in); + } +}; + +class obufstream +{ +protected: + internal::form_memory_buffer<> buffer; + +public: + + obufstream() {} + + void clear() + { + buffer.clear(); + } + + obufstream& operator<<(const char* t) + { + size_t len = strlen(t); + buffer.append(t, len); + return *this; + } + + obufstream& operator<<(const std::string& s) + { + buffer.append(s.data(), s.size()); + return *this; + } + + // For unusual manipulation, usually to add NUL termination. + // NOTE: you must make sure that you won't use the extended + // buffers if the intention was to get a string. + void append(char c) + { + buffer.append(c); + } + + const char* bufptr() const + { + return buffer.get_first(); + } + + template + obufstream& operator<<(const internal::form_memory_buffer& b) + { + using namespace internal; + // Copy all pieces one by one + if (b.size() == 0) + return *this; + + buffer.append(b.get_first(), b.first_size()); + for (form_memory_buffer<>::slices_t::const_iterator i = b.get_slices().begin(); + i != b.get_slices().end(); ++i) + { + // Would be tempting to move the blocks, but C++03 doesn't feature moving. + const char* data = &(*i)[0]; + buffer.append(data, i->size()); + } + return *this; + } + + obufstream& operator<<(const obufstream& source) + { + return *this << source.buffer; + } + + template + obufstream& operator<<(const Value& v) + { + internal::write_default(*this, v); + return *this; + } + + std::string str() const + { + using namespace internal; + std::string out; + if (buffer.empty()) + return out; + + out.reserve(buffer.size() + 1); + out.append(buffer.get_first(), buffer.first_size()); + for (form_memory_buffer<>::slices_t::const_iterator i = buffer.get_slices().begin(); + i != buffer.get_slices().end(); ++i) + { + // Would be tempting to move the blocks, but C++03 doesn't feature moving. + const char* data = &(*i)[0]; + out.append(data, i->size()); + } + return out; + } + + size_t size() const { return buffer.size(); } + + template + void copy_to(OutputContainer& out) const + { + using namespace internal; + + std::copy(buffer.get_first(), buffer.get_first() + buffer.first_size(), + std::back_inserter(out)); + + for (form_memory_buffer<>::slices_t::const_iterator i = buffer.get_slices().begin(); + i != buffer.get_slices().end(); ++i) + { + // Would be tempting to move the blocks, but C++03 doesn't feature moving. + const char* data = &(*i)[0]; + std::copy(data, data + i->size(), std::back_inserter(out)); + } + } + + template + size_t copy_to(OutputContainer& out, size_t maxsize) const + { + using namespace internal; + size_t avail = maxsize; + if (avail < buffer.first_size()) + { + std::copy(buffer.get_first(), buffer.get_first() + avail, + std::back_inserter(out)); + return maxsize; + } + + std::copy(buffer.get_first(), buffer.get_first() + buffer.first_size(), + std::back_inserter(out)); + + avail -= buffer.first_size(); + + for (form_memory_buffer<>::slices_t::const_iterator i = buffer.get_slices().begin(); + i != buffer.get_slices().end(); ++i) + { + // Would be tempting to move the blocks, but C++03 doesn't feature moving. + const char* data = &(*i)[0]; + + if (avail < i->size()) + { + std::copy(data, data + avail, std::back_inserter(out)); + return maxsize; + } + std::copy(data, data + i->size(), std::back_inserter(out)); + avail -= i->size(); + } + + return maxsize - avail; + } +}; + +namespace internal +{ +#if defined(_MSC_VER) && _MSC_VER < 1900 +#define FMT_SYM_SNPRINTF _snprintf +#define FMT_SIZE_SNPRINTF(bufsize) (bufsize-1) +#else +#define FMT_SYM_SNPRINTF std::snprintf +#define FMT_SIZE_SNPRINTF(bufsize) bufsize +#endif + +template +static inline size_t SNPrintfOne(char* buf, size_t bufsize, const char* fmt, const ValueType& val) +{ return FMT_SYM_SNPRINTF (buf, FMT_SIZE_SNPRINTF(bufsize), fmt, val); } + +static inline size_t SNPrintfOne(char* buf, size_t bufsize, const char* fmt, const std::string& val) +{ return FMT_SYM_SNPRINTF(buf, FMT_SIZE_SNPRINTF(bufsize), fmt, val.c_str()); } + +#undef FMT_SYM_SNPRINTF +#undef FMT_SIZE_SNPRINTF + +template inline +form_memory_buffer<> sfmt_imp(const Value& val, const form_memory_buffer<>& fstr, size_t bufsize) +{ + form_memory_buffer<> out; + // Reserve the maximum initial first, then shrink. + char* buf = out.expose(bufsize); + + size_t valsize = SNPrintfOne(buf, bufsize, fstr.get_first(), val); + + // Deemed impossible to happen, but still + if (valsize == bufsize) + { + bufsize *= 2; + // Just try again with one extra size, if this won't + // suffice, just add <...> at the end. + buf = out.expose(bufsize); + valsize = SNPrintfOne(buf, bufsize, fstr.get_first(), val); + if (valsize == bufsize) + { + char* end = buf + bufsize - 6; + strcpy(end, "<...>"); + } + } + + size_t unused = bufsize - valsize; + out.unreserve(unused); + out.commit(); + return out; +} +} + +template inline +internal::form_memory_buffer<> sfmt(const Value& val, const char* fmtspec = 0) +{ + using namespace internal; + + form_memory_buffer<> fstr = apply_format_fix(val, fmtspec); + size_t bufsize = form_memory_buffer<>::INITIAL_SIZE; + + // We want to use this buffer as a NUL-terminated string. + // So we need to add NUL character oursevles, form_memory_buffer<> + // doesn't do it an doesn't use the NUL-termination. + fstr.append('\0'); + + return sfmt_imp(val, fstr, bufsize); +} + +template inline +internal::form_memory_buffer<> sfmt(const Value& val, const sfmc& config) +{ + using namespace internal; + + form_memory_buffer<> fstr = config.create_format(val); + size_t bufsize = form_memory_buffer<>::INITIAL_SIZE; + return sfmt_imp(val, fstr, bufsize); +} + + + +namespace internal +{ +template inline +void write_default(Stream& s, const Value& v) +{ + s << sfmt(v, ""); +} + + +inline void sfmts_imp(const internal::form_memory_buffer<>& b, std::string& out) +{ + using namespace internal; + + if (b.size() == 0) + return; + + out.reserve(b.size()); + out.append(b.get_first(), b.first_size()); + for (form_memory_buffer<>::slices_t::const_iterator i = b.get_slices().begin(); + i != b.get_slices().end(); ++i) + { + const char* data = &(*i)[0]; + out.append(data, i->size()); + } +} +} + +template +inline std::string sfmts(const Value& val, const char* fmtspec = 0) +{ + std::string out; + internal::sfmts_imp(sfmt(val, fmtspec), (out)); + return out; +} + +template +inline std::string sfmts(const Value& val, const sfmc& fmtspec) +{ + std::string out; + internal::sfmts_imp(sfmt(val, fmtspec), (out)); + return out; +} + + +// Semi-manipulator to add the end-of-line. +const internal::form_memory_buffer<2> seol ("\n"); + +// Another manipulator. You can add yourself others the same way. +const struct os_flush_manip {} sflush; + +inline ostdiostream& operator<<(ostdiostream& sout, const os_flush_manip&) +{ + std::fflush(sout.raw()); + return sout; +}; + + +} + +#endif diff --git a/srtcore/sync.cpp b/srtcore/sync.cpp index a7cebb909..ff7473ca3 100644 --- a/srtcore/sync.cpp +++ b/srtcore/sync.cpp @@ -50,13 +50,17 @@ std::string FormatTime(const steady_clock::time_point& timestamp) const uint64_t hours = total_sec / (60 * 60) - days * 24; const uint64_t minutes = total_sec / 60 - (days * 24 * 60) - hours * 60; const uint64_t seconds = total_sec - (days * 24 * 60 * 60) - hours * 60 * 60 - minutes * 60; - ostringstream out; + steady_clock::time_point frac = timestamp - seconds_from(total_sec); + srt::obufstream out; if (days) out << days << "D "; - out << setfill('0') << setw(2) << hours << ":" - << setfill('0') << setw(2) << minutes << ":" - << setfill('0') << setw(2) << seconds << "." - << setfill('0') << setw(decimals) << (timestamp - seconds_from(total_sec)).time_since_epoch().count() << " [STDY]"; + + out << srt::sfmt(hours, "02") << ":" + << srt::sfmt(minutes, "02") << ":" + << srt::sfmt(seconds, "02") << "." + << srt::sfmt(frac.time_since_epoch().count(), + srt::sfmc().fillzero().width(decimals)) + << " [STDY]"; return out.str(); } @@ -72,8 +76,8 @@ std::string FormatTimeSys(const steady_clock::time_point& timestamp) char tmp_buf[512]; strftime(tmp_buf, 512, "%X.", &tm); - ostringstream out; - out << tmp_buf << setfill('0') << setw(6) << (count_microseconds(timestamp.time_since_epoch()) % 1000000) << " [SYST]"; + srt::obufstream out; + out << tmp_buf << srt::sfmt(count_microseconds(timestamp.time_since_epoch()) % 1000000, "06") << " [SYST]"; return out.str(); } diff --git a/srtcore/sync.h b/srtcore/sync.h index fb6d56432..40584a838 100644 --- a/srtcore/sync.h +++ b/srtcore/sync.h @@ -55,7 +55,7 @@ #include "srt.h" #include "utilities.h" #include "srt_attr_defs.h" - +#include "srt_sfmt.h" namespace srt { @@ -775,7 +775,9 @@ struct DurationUnitName template inline std::string FormatDuration(const steady_clock::duration& dur) { - return Sprint(std::fixed, DurationUnitName::count(dur)) + DurationUnitName::name(); + obufstream out; + out << sfmt(DurationUnitName::count(dur), "f") << DurationUnitName::name(); + return out.str(); } inline std::string FormatDuration(const steady_clock::duration& dur) diff --git a/srtcore/utilities.h b/srtcore/utilities.h index 1786cf0ae..d7f353765 100644 --- a/srtcore/utilities.h +++ b/srtcore/utilities.h @@ -34,7 +34,6 @@ written by #include #include #include -#include #include #if HAVE_CXX11 @@ -46,6 +45,8 @@ written by #include #include +#include "srt_sfmt.h" + // -------------- UTILITIES ------------------------ // --- ENDIAN --- @@ -484,7 +485,7 @@ class FixedArray void throw_invalid_index(int i) const { - std::stringstream ss; + srt::obufstream ss; ss << "Index " << i << "out of range"; throw std::runtime_error(ss.str()); } @@ -530,8 +531,8 @@ struct explicit_t // but this function has a different definition for C++11 and C++03. namespace srt_pair_op { - template - std::ostream& operator<<(std::ostream& s, const std::pair& v) + template + Stream& operator<<(Stream& s, const std::pair& v) { s << "{" << v.first << " " << v.second << "}"; return s; @@ -586,7 +587,7 @@ inline Stream& Print(Stream& sout, Arg1&& arg1, Args&&... args) template inline std::string Sprint(Args&&... args) { - std::ostringstream sout; + srt::obufstream sout; Print(sout, args...); return sout.str(); } @@ -597,27 +598,6 @@ inline std::string Sprint(Args&&... args) template using UniquePtr = std::unique_ptr; -template inline -std::string Printable(const Container& in, Value /*pseudoargument*/, Args&&... args) -{ - using namespace srt_pair_op; - std::ostringstream os; - Print(os, args...); - os << "[ "; - for (auto i: in) - os << Value(i) << " "; - os << "]"; - return os.str(); -} - -template inline -std::string Printable(const Container& in) -{ - using namespace srt_pair_op; - using Value = typename Container::value_type; - return Printable(in, Value()); -} - template auto map_get(Map& m, const Key& key, typename Map::mapped_type def = typename Map::mapped_type()) -> typename Map::mapped_type { @@ -693,34 +673,18 @@ class UniquePtr: public std::auto_ptr template inline std::string Sprint(const Arg1& arg) { - std::ostringstream sout; - sout << arg; - return sout.str(); + return srt::sfmts(arg); } // Ok, let it be 2-arg, in case when a manipulator is needed template inline std::string Sprint(const Arg1& arg1, const Arg2& arg2) { - std::ostringstream sout; + srt::obufstream sout; sout << arg1 << arg2; return sout.str(); } -template inline -std::string Printable(const Container& in) -{ - using namespace srt_pair_op; - typedef typename Container::value_type Value; - std::ostringstream os; - os << "[ "; - for (typename Container::const_iterator i = in.begin(); i != in.end(); ++i) - os << Value(*i) << " "; - os << "]"; - - return os.str(); -} - template typename Map::mapped_type map_get(Map& m, const Key& key, typename Map::mapped_type def = typename Map::mapped_type()) { @@ -751,6 +715,41 @@ typename Map::mapped_type const* map_getp(const Map& m, const Key& key) #endif +template inline +std::string Printable(const Container& in, Value /*pseudoargument*/, const char* fmt = 0) +{ + srt::obufstream os; + os << "[ "; + typedef typename Container::const_iterator it_t; + for (it_t i = in.begin(); i != in.end(); ++i) + os << srt::sfmt(*i, fmt) << " "; + os << "]"; + return os.str(); +} + +// Separate version for pairs, used for std::map +template inline +std::string Printable(const Container& in, std::pair/*pseudoargument*/, const char* fmtk = 0, const char* fmtv = 0) +{ + using namespace srt_pair_op; + srt::obufstream os; + os << "[ "; + typedef typename Container::const_iterator it_t; + for (it_t i = in.begin(); i != in.end(); ++i) + os << srt::sfmt(i->first, fmtk) << ":" << srt::sfmt(i->second, fmtv) << " "; + os << "]"; + return os.str(); +} + + +template inline +std::string Printable(const Container& in) +{ + using namespace srt_pair_op; + typedef typename Container::value_type Value; + return Printable(in, Value()); +} + // Printable with prefix added for every element. // Useful when printing a container of sockets or sequence numbers. template inline @@ -758,7 +757,7 @@ std::string PrintableMod(const Container& in, const std::string& prefix) { using namespace srt_pair_op; typedef typename Container::value_type Value; - std::ostringstream os; + srt::obufstream os; os << "[ "; for (typename Container::const_iterator y = in.begin(); y != in.end(); ++y) os << prefix << Value(*y) << " "; @@ -981,31 +980,11 @@ inline std::string FormatBinaryString(const uint8_t* bytes, size_t size) if ( size == 0 ) return ""; - //char buf[256]; - using namespace std; - - ostringstream os; - - // I know, it's funny to use sprintf and ostringstream simultaneously, - // but " %02X" in iostream is: << " " << hex << uppercase << setw(2) << setfill('0') << VALUE << setw(1) - // Too noisy. OTOH ostringstream solves the problem of memory allocation - // for a string of unpredictable size. - //sprintf(buf, "%02X", int(bytes[0])); - - os.fill('0'); - os.width(2); - os.setf(ios::basefield, ios::hex); - os.setf(ios::uppercase); - - //os << buf; - os << int(bytes[0]); + srt::obufstream os; - - for (size_t i = 1; i < size; ++i) + for (size_t i = 0; i < size; ++i) { - //sprintf(buf, " %02X", int(bytes[i])); - //os << buf; - os << int(bytes[i]); + os << srt::sfmt(bytes[i], "02X"); } return os.str(); } @@ -1171,10 +1150,7 @@ inline std::string BufferStamp(const char* mem, size_t size) } // Convert to hex string - ostringstream os; - os << hex << uppercase << setfill('0') << setw(8) << sum; - - return os.str(); + return srt::sfmts(sum, "08X"); } template diff --git a/testing/srt-test-live.cpp b/testing/srt-test-live.cpp index 17f4020dc..853ef87ad 100644 --- a/testing/srt-test-live.cpp +++ b/testing/srt-test-live.cpp @@ -301,7 +301,7 @@ extern "C" int SrtCheckGroupHook(void* , SRTSOCKET acpsock, int , const sockaddr size = sizeof gt; if (-1 != srt_getsockflag(acpsock, SRTO_GROUPTYPE, >, &size)) { - if (gt < Size(gtypes)) + if (size_t(gt) < Size(gtypes)) Verb() << " type=" << gtypes[gt] << VerbNoEOL; else Verb() << " type=" << int(gt) << VerbNoEOL; diff --git a/testing/srt-test-relay.cpp b/testing/srt-test-relay.cpp index 45d657128..18e6acf3d 100755 --- a/testing/srt-test-relay.cpp +++ b/testing/srt-test-relay.cpp @@ -367,9 +367,9 @@ SrtMainLoop::SrtMainLoop(const string& srt_uri, bool input_echoback, const strin Verb() << "SRT set up as input source and the first output target"; // Add SRT medium to output targets, and keep input medium empty. - unique_ptr m { new TargetMedium }; - m->Setup(m_srt_relay.get()); - m_output_media.push_back(move(m)); + unique_ptr tm { new TargetMedium }; + tm->Setup(m_srt_relay.get()); + m_output_media.push_back(move(tm)); } else { diff --git a/testing/testactivemedia.cpp b/testing/testactivemedia.cpp index 96344f0b2..6ca2bffa9 100644 --- a/testing/testactivemedia.cpp +++ b/testing/testactivemedia.cpp @@ -3,6 +3,11 @@ using namespace std; +#if ENABLE_LOGGING +namespace { +const char* fmt_yesno(bool b) { return b ? "yes" : "no"; } +} +#endif void SourceMedium::Runner() { @@ -17,7 +22,8 @@ void SourceMedium::Runner() Verb() << VerbLock << "Exiting SourceMedium: " << this; return; } - LOGP(applog.Debug, "SourceMedium(", typeid(*med).name(), "): [", input.payload.size(), "] MEDIUM -> BUFFER. signal(", &ready, ")"); + LOGP(applog.Debug, "SourceMedium(", typeid(*med).name(), "): [", input.payload.size(), + "] MEDIUM -> BUFFER. signal(", (void*)&ready, ")"); lock_guard g(buffer_lock); buffer.push_back(input); @@ -84,7 +90,7 @@ void TargetMedium::Runner() bool gotsomething = ready.wait_for(lg, chrono::seconds(1), [this] { return !running || !buffer.empty(); } ); LOGP(applog.Debug, "TargetMedium(", typeid(*med).name(), "): [", val.payload.size(), "] BUFFER update (timeout:", - boolalpha, gotsomething, " running: ", running, ")"); + fmt_yesno(!gotsomething), " running: ", running, ")"); if (::transmit_int_state || !running || !med || med->Broken()) { LOGP(applog.Debug, "TargetMedium(", typeid(*med).name(), "): buffer empty, medium ", @@ -120,4 +126,20 @@ void TargetMedium::Runner() } } +bool TargetMedium::Schedule(const MediaPacket& data) +{ + LOGP(applog.Debug, "TargetMedium::Schedule LOCK ... "); + std::lock_guard lg(buffer_lock); + LOGP(applog.Debug, "TargetMedium::Schedule LOCKED - checking: running=", running, " interrupt=", ::transmit_int_state); + if (!running || ::transmit_int_state) + { + LOGP(applog.Debug, "TargetMedium::Schedule: not running, discarding packet"); + return false; + } + + LOGP(applog.Debug, "TargetMedium(", typeid(*med).name(), "): Schedule: [", data.payload.size(), "] CLIENT -> BUFFER"); + buffer.push_back(data); + ready.notify_one(); + return true; +} diff --git a/testing/testactivemedia.hpp b/testing/testactivemedia.hpp index 011dcbfe7..e92abbe0c 100644 --- a/testing/testactivemedia.hpp +++ b/testing/testactivemedia.hpp @@ -6,7 +6,6 @@ #include #include #include -#include #include #include "testmedia.hpp" @@ -29,7 +28,7 @@ struct Medium std::mutex buffer_lock; std::thread thr; std::condition_variable ready; - std::atomic running = {false}; + srt::sync::atomic running {false}; std::exception_ptr xp; // To catch exception thrown by a thread virtual void Runner() = 0; @@ -147,22 +146,7 @@ struct TargetMedium: Medium { void Runner() override; - bool Schedule(const MediaPacket& data) - { - LOGP(applog.Debug, "TargetMedium::Schedule LOCK ... "); - std::lock_guard lg(buffer_lock); - LOGP(applog.Debug, "TargetMedium::Schedule LOCKED - checking: running=", running, " interrupt=", ::transmit_int_state); - if (!running || ::transmit_int_state) - { - LOGP(applog.Debug, "TargetMedium::Schedule: not running, discarding packet"); - return false; - } - - LOGP(applog.Debug, "TargetMedium(", typeid(*med).name(), "): Schedule: [", data.payload.size(), "] CLIENT -> BUFFER"); - buffer.push_back(data); - ready.notify_one(); - return true; - } + bool Schedule(const MediaPacket& data); void Clear() { diff --git a/testing/testmedia.cpp b/testing/testmedia.cpp index 2d6635288..197ee2231 100755 --- a/testing/testmedia.cpp +++ b/testing/testmedia.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include #if !defined(_WIN32) #include @@ -50,8 +49,8 @@ using srt_logging::SockStatusStr; using srt_logging::MemberStatusStr; #endif -std::atomic transmit_throw_on_interrupt {false}; -std::atomic transmit_int_state {false}; +srt::sync::atomic transmit_throw_on_interrupt {false}; +srt::sync::atomic transmit_int_state {false}; int transmit_bw_report = 0; unsigned transmit_stats_report = 0; size_t transmit_chunk_size = SRT_LIVE_DEF_PLSIZE; @@ -1059,8 +1058,8 @@ void SrtCommon::OpenGroupClient() if (!extras.empty()) { Verb() << "?" << extras[0] << VerbNoEOL; - for (size_t i = 1; i < extras.size(); ++i) - Verb() << "&" << extras[i] << VerbNoEOL; + for (size_t ei = 1; ei < extras.size(); ++ei) + Verb() << "&" << extras[ei] << VerbNoEOL; } Verb(); @@ -1130,15 +1129,15 @@ void SrtCommon::OpenGroupClient() // spread the setting on all sockets. ConfigurePost(m_sock); - for (size_t i = 0; i < targets.size(); ++i) + for (size_t ti = 0; ti < targets.size(); ++ti) { // As m_group_nodes is simply transformed into 'targets', // one index can be used to index them all. You don't // have to check if they have equal addresses because they // are equal by definition. - if (targets[i].id != -1 && targets[i].errorcode == SRT_SUCCESS) + if (targets[ti].id != -1 && targets[ti].errorcode == SRT_SUCCESS) { - m_group_nodes[i].socket = targets[i].id; + m_group_nodes[ti].socket = targets[ti].id; } } @@ -1159,12 +1158,12 @@ void SrtCommon::OpenGroupClient() } m_group_data.resize(size); - for (size_t i = 0; i < m_group_nodes.size(); ++i) + for (size_t ni = 0; ni < m_group_nodes.size(); ++ni) { - SRTSOCKET insock = m_group_nodes[i].socket; + SRTSOCKET insock = m_group_nodes[ni].socket; if (insock == -1) { - Verb() << "TARGET '" << sockaddr_any(targets[i].peeraddr).str() << "' connection failed."; + Verb() << "TARGET '" << sockaddr_any(targets[ni].peeraddr).str() << "' connection failed."; continue; } @@ -1194,11 +1193,11 @@ void SrtCommon::OpenGroupClient() NULL, NULL) != -1) { Verb() << "[C]" << VerbNoEOL; - for (int i = 0; i < len1; ++i) - Verb() << " " << ready_conn[i] << VerbNoEOL; + for (int ri = 0; ri < len1; ++ri) + Verb() << " " << ready_conn[ri] << VerbNoEOL; Verb() << "[E]" << VerbNoEOL; - for (int i = 0; i < len2; ++i) - Verb() << " " << ready_err[i] << VerbNoEOL; + for (int ri = 0; ri < len2; ++ri) + Verb() << " " << ready_err[ri] << VerbNoEOL; Verb() << ""; diff --git a/testing/testmedia.hpp b/testing/testmedia.hpp index be72471d1..470e825ef 100644 --- a/testing/testmedia.hpp +++ b/testing/testmedia.hpp @@ -15,7 +15,8 @@ #include #include #include -#include + +#include // use srt::sync::atomic instead of std::atomic for the sake of logging #include "apputil.hpp" #include "statswriter.hpp" @@ -25,7 +26,7 @@ extern srt_listen_callback_fn* transmit_accept_hook_fn; extern void* transmit_accept_hook_op; -extern std::atomic transmit_int_state; +extern srt::sync::atomic transmit_int_state; extern std::shared_ptr transmit_stats_writer; diff --git a/testing/testmediabase.hpp b/testing/testmediabase.hpp index 04a85d435..686198787 100644 --- a/testing/testmediabase.hpp +++ b/testing/testmediabase.hpp @@ -11,17 +11,17 @@ #ifndef INC_SRT_COMMON_TRANMITBASE_HPP #define INC_SRT_COMMON_TRANMITBASE_HPP -#include #include #include #include #include #include +#include "sync.h" #include "uriparser.hpp" typedef std::vector bytevector; -extern std::atomic transmit_throw_on_interrupt; +extern srt::sync::atomic transmit_throw_on_interrupt; extern int transmit_bw_report; extern unsigned transmit_stats_report; extern size_t transmit_chunk_size;