16
16
#include <utility>
17
17
#include <memory>
18
18
19
+
#include "srt.h" // Required for SRT_SYNC_CLOCK_* definitions.
19
20
#include "apputil.hpp"
20
21
#include "netinet_any.h"
21
22
#include "srt_compat.h"
@@ -352,339 +353,6 @@ string OptionHelpItem(const OptionName& o)
352
353
return out;
353
354
}
354
355
355
-
// Stats module
356
-
357
-
// Note: std::put_time is supported only in GCC 5 and higher
358
-
#if !defined(__GNUC__) || defined(__clang__) || (__GNUC__ >= 5)
359
-
#define HAS_PUT_TIME
360
-
#endif
361
-
362
-
template <class TYPE>
363
-
inline SrtStatData* make_stat(SrtStatCat cat, const string& name, const string& longname,
364
-
TYPE CBytePerfMon::*field)
365
-
{
366
-
return new SrtStatDataType<TYPE>(cat, name, longname, field);
367
-
}
368
-
369
-
#define STATX(catsuf, sname, lname, field) s.emplace_back(make_stat(SSC_##catsuf, #sname, #lname, &CBytePerfMon:: field))
370
-
#define STAT(catsuf, sname, field) STATX(catsuf, sname, field, field)
371
-
372
-
vector<unique_ptr<SrtStatData>> g_SrtStatsTable;
373
-
374
-
struct SrtStatsTableInit
375
-
{
376
-
SrtStatsTableInit(vector<unique_ptr<SrtStatData>>& s)
377
-
{
378
-
STATX(GEN, time, Time, msTimeStamp);
379
-
380
-
STAT(WINDOW, flow, pktFlowWindow);
381
-
STAT(WINDOW, congestion, pktCongestionWindow);
382
-
STAT(WINDOW, flight, pktFlightSize);
383
-
384
-
STAT(LINK, rtt, msRTT);
385
-
STAT(LINK, bandwidth, mbpsBandwidth);
386
-
STAT(LINK, maxBandwidth, mbpsMaxBW);
387
-
388
-
STAT(SEND, packets, pktSent);
389
-
STAT(SEND, packetsUnique, pktSentUnique);
390
-
STAT(SEND, packetsLost, pktSndLoss);
391
-
STAT(SEND, packetsDropped, pktSndDrop);
392
-
STAT(SEND, packetsRetransmitted, pktRetrans);
393
-
STAT(SEND, packetsFilterExtra, pktSndFilterExtra);
394
-
STAT(SEND, bytes, byteSent);
395
-
STAT(SEND, bytesUnique, byteSentUnique);
396
-
STAT(SEND, bytesDropped, byteSndDrop);
397
-
STAT(SEND, byteAvailBuf, byteAvailSndBuf);
398
-
STAT(SEND, msBuf, msSndBuf);
399
-
STAT(SEND, mbitRate, mbpsSendRate);
400
-
STAT(SEND, sendPeriod, usPktSndPeriod);
401
-
402
-
STAT(RECV, packets, pktRecv);
403
-
STAT(RECV, packetsUnique, pktRecvUnique);
404
-
STAT(RECV, packetsLost, pktRcvLoss);
405
-
STAT(RECV, packetsDropped, pktRcvDrop);
406
-
STAT(RECV, packetsRetransmitted, pktRcvRetrans);
407
-
STAT(RECV, packetsBelated, pktRcvBelated);
408
-
STAT(RECV, packetsFilterExtra, pktRcvFilterExtra);
409
-
STAT(RECV, packetsFilterSupply, pktRcvFilterSupply);
410
-
STAT(RECV, packetsFilterLoss, pktRcvFilterLoss);
411
-
STAT(RECV, bytes, byteRecv);
412
-
STAT(RECV, bytesUnique, byteRecvUnique);
413
-
STAT(RECV, bytesLost, byteRcvLoss);
414
-
STAT(RECV, bytesDropped, byteRcvDrop);
415
-
STAT(RECV, byteAvailBuf, byteAvailRcvBuf);
416
-
STAT(RECV, msBuf, msRcvBuf);
417
-
STAT(RECV, mbitRate, mbpsRecvRate);
418
-
STAT(RECV, msTsbPdDelay, msRcvTsbPdDelay);
419
-
}
420
-
} g_SrtStatsTableInit (g_SrtStatsTable);
421
-
422
-
423
-
#undef STAT
424
-
#undef STATX
425
-
426
-
string srt_json_cat_names [] = {
427
-
"",
428
-
"window",
429
-
"link",
430
-
"send",
431
-
"recv"
432
-
};
433
-
434
-
#ifdef HAS_PUT_TIME
435
-
// Follows ISO 8601
436
-
std::string SrtStatsWriter::print_timestamp()
437
-
{
438
-
using namespace std;
439
-
using namespace std::chrono;
440
-
441
-
const auto systime_now = system_clock::now();
442
-
const time_t time_now = system_clock::to_time_t(systime_now);
443
-
444
-
std::ostringstream output;
445
-
446
-
// SysLocalTime returns zeroed tm_now on failure, which is ok for put_time.
447
-
const tm tm_now = SysLocalTime(time_now);
448
-
output << std::put_time(&tm_now, "%FT%T.") << std::setfill('0') << std::setw(6);
449
-
const auto since_epoch = systime_now.time_since_epoch();
450
-
const seconds s = duration_cast<seconds>(since_epoch);
451
-
output << duration_cast<microseconds>(since_epoch - s).count();
452
-
output << std::put_time(&tm_now, "%z");
453
-
return output.str();
454
-
}
455
-
#else
456
-
457
-
// This is a stub. The error when not defining it would be too
458
-
// misleading, so this stub will work if someone mistakenly adds
459
-
// the item to the output format without checking that HAS_PUT_TIME.
460
-
string SrtStatsWriter::print_timestamp()
461
-
{ return "<NOT IMPLEMENTED>"; }
462
-
#endif // HAS_PUT_TIME
463
-
464
-
465
-
class SrtStatsJson : public SrtStatsWriter
466
-
{
467
-
static string quotekey(const string& name)
468
-
{
469
-
if (name == "")
470
-
return "";
471
-
472
-
return R"(")" + name + R"(":)";
473
-
}
474
-
475
-
static string quote(const string& name)
476
-
{
477
-
if (name == "")
478
-
return "";
479
-
480
-
return R"(")" + name + R"(")";
481
-
}
482
-
483
-
public:
484
-
string WriteStats(int sid, const CBytePerfMon& mon) override
485
-
{
486
-
std::ostringstream output;
487
-
488
-
string pretty_cr, pretty_tab;
489
-
if (Option("pretty"))
490
-
{
491
-
pretty_cr = "\n";
492
-
pretty_tab = "\t";
493
-
}
494
-
495
-
SrtStatCat cat = SSC_GEN;
496
-
497
-
// Do general manually
498
-
output << quotekey(srt_json_cat_names[cat]) << "{" << pretty_cr;
499
-
500
-
// SID is displayed manually
501
-
output << pretty_tab << quotekey("sid") << sid;
502
-
503
-
// Extra Timepoint is also displayed manually
504
-
#ifdef HAS_PUT_TIME
505
-
// NOTE: still assumed SSC_GEN category
506
-
output << "," << pretty_cr << pretty_tab
507
-
<< quotekey("timepoint") << quote(print_timestamp());
508
-
#endif
509
-
510
-
// Now continue with fields as specified in the table
511
-
for (auto& i: g_SrtStatsTable)
512
-
{
513
-
if (i->category == cat)
514
-
{
515
-
output << ","; // next item in same cat
516
-
output << pretty_cr;
517
-
output << pretty_tab;
518
-
if (cat != SSC_GEN)
519
-
output << pretty_tab;
520
-
}
521
-
else
522
-
{
523
-
if (cat != SSC_GEN)
524
-
{
525
-
// DO NOT close if general category, just
526
-
// enter the depth.
527
-
output << pretty_cr << pretty_tab << "}";
528
-
}
529
-
cat = i->category;
530
-
output << ",";
531
-
output << pretty_cr;
532
-
if (cat != SSC_GEN)
533
-
output << pretty_tab;
534
-
535
-
output << quotekey(srt_json_cat_names[cat]) << "{" << pretty_cr << pretty_tab;
536
-
if (cat != SSC_GEN)
537
-
output << pretty_tab;
538
-
}
539
-
540
-
// Print the current field
541
-
output << quotekey(i->name);
542
-
i->PrintValue(output, mon);
543
-
}
544
-
545
-
// Close the previous subcategory
546
-
if (cat != SSC_GEN)
547
-
{
548
-
output << pretty_cr << pretty_tab << "}" << pretty_cr;
549
-
}
550
-
551
-
// Close the general category entity
552
-
output << "}" << pretty_cr << endl;
553
-
554
-
return output.str();
555
-
}
556
-
557
-
string WriteBandwidth(double mbpsBandwidth) override
558
-
{
559
-
std::ostringstream output;
560
-
output << "{\"bandwidth\":" << mbpsBandwidth << '}' << endl;
561
-
return output.str();
562
-
}
563
-
};
564
-
565
-
class SrtStatsCsv : public SrtStatsWriter
566
-
{
567
-
private:
568
-
bool first_line_printed;
569
-
570
-
public:
571
-
SrtStatsCsv() : first_line_printed(false) {}
572
-
573
-
string WriteStats(int sid, const CBytePerfMon& mon) override
574
-
{
575
-
std::ostringstream output;
576
-
577
-
// Header
578
-
if (!first_line_printed)
579
-
{
580
-
#ifdef HAS_PUT_TIME
581
-
output << "Timepoint,";
582
-
#endif
583
-
output << "Time,SocketID";
584
-
585
-
for (auto& i: g_SrtStatsTable)
586
-
{
587
-
output << "," << i->longname;
588
-
}
589
-
output << endl;
590
-
first_line_printed = true;
591
-
}
592
-
593
-
// Values
594
-
#ifdef HAS_PUT_TIME
595
-
// HDR: Timepoint
596
-
output << print_timestamp() << ",";
597
-
#endif // HAS_PUT_TIME
598
-
599
-
// HDR: Time,SocketID
600
-
output << mon.msTimeStamp << "," << sid;
601
-
602
-
// HDR: the loop of all values in g_SrtStatsTable
603
-
for (auto& i: g_SrtStatsTable)
604
-
{
605
-
output << ",";
606
-
i->PrintValue(output, mon);
607
-
}
608
-
609
-
output << endl;
610
-
return output.str();
611
-
}
612
-
613
-
string WriteBandwidth(double mbpsBandwidth) override
614
-
{
615
-
std::ostringstream output;
616
-
output << "+++/+++SRT BANDWIDTH: " << mbpsBandwidth << endl;
617
-
return output.str();
618
-
}
619
-
};
620
-
621
-
class SrtStatsCols : public SrtStatsWriter
622
-
{
623
-
public:
624
-
string WriteStats(int sid, const CBytePerfMon& mon) override
625
-
{
626
-
std::ostringstream output;
627
-
output << "======= SRT STATS: sid=" << sid << endl;
628
-
output << "PACKETS SENT: " << setw(11) << mon.pktSent << " RECEIVED: " << setw(11) << mon.pktRecv << endl;
629
-
output << "LOST PKT SENT: " << setw(11) << mon.pktSndLoss << " RECEIVED: " << setw(11) << mon.pktRcvLoss << endl;
630
-
output << "REXMIT SENT: " << setw(11) << mon.pktRetrans << " RECEIVED: " << setw(11) << mon.pktRcvRetrans << endl;
631
-
output << "DROP PKT SENT: " << setw(11) << mon.pktSndDrop << " RECEIVED: " << setw(11) << mon.pktRcvDrop << endl;
632
-
output << "FILTER EXTRA TX: " << setw(11) << mon.pktSndFilterExtra << " RX: " << setw(11) << mon.pktRcvFilterExtra << endl;
633
-
output << "FILTER RX SUPPL: " << setw(11) << mon.pktRcvFilterSupply << " RX LOSS: " << setw(11) << mon.pktRcvFilterLoss << endl;
634
-
output << "RATE SENDING: " << setw(11) << mon.mbpsSendRate << " RECEIVING: " << setw(11) << mon.mbpsRecvRate << endl;
635
-
output << "BELATED RECEIVED: " << setw(11) << mon.pktRcvBelated << " AVG TIME: " << setw(11) << mon.pktRcvAvgBelatedTime << endl;
636
-
output << "REORDER DISTANCE: " << setw(11) << mon.pktReorderDistance << endl;
637
-
output << "WINDOW FLOW: " << setw(11) << mon.pktFlowWindow << " CONGESTION: " << setw(11) << mon.pktCongestionWindow << " FLIGHT: " << setw(11) << mon.pktFlightSize << endl;
638
-
output << "LINK RTT: " << setw(9) << mon.msRTT << "ms BANDWIDTH: " << setw(7) << mon.mbpsBandwidth << "Mb/s " << endl;
639
-
output << "BUFFERLEFT: SND: " << setw(11) << mon.byteAvailSndBuf << " RCV: " << setw(11) << mon.byteAvailRcvBuf << endl;
640
-
return output.str();
641
-
}
642
-
643
-
string WriteBandwidth(double mbpsBandwidth) override
644
-
{
645
-
std::ostringstream output;
646
-
output << "+++/+++SRT BANDWIDTH: " << mbpsBandwidth << endl;
647
-
return output.str();
648
-
}
649
-
};
650
-
651
-
shared_ptr<SrtStatsWriter> SrtStatsWriterFactory(SrtStatsPrintFormat printformat)
652
-
{
653
-
switch (printformat)
654
-
{
655
-
case SRTSTATS_PROFMAT_JSON:
656
-
return make_shared<SrtStatsJson>();
657
-
case SRTSTATS_PROFMAT_CSV:
658
-
return make_shared<SrtStatsCsv>();
659
-
case SRTSTATS_PROFMAT_2COLS:
660
-
return make_shared<SrtStatsCols>();
661
-
default:
662
-
break;
663
-
}
664
-
return nullptr;
665
-
}
666
-
667
-
SrtStatsPrintFormat ParsePrintFormat(string pf, string& w_extras)
668
-
{
669
-
size_t havecomma = pf.find(',');
670
-
if (havecomma != string::npos)
671
-
{
672
-
w_extras = pf.substr(havecomma+1);
673
-
pf = pf.substr(0, havecomma);
674
-
}
675
-
676
-
if (pf == "default")
677
-
return SRTSTATS_PROFMAT_2COLS;
678
-
679
-
if (pf == "json")
680
-
return SRTSTATS_PROFMAT_JSON;
681
-
682
-
if (pf == "csv")
683
-
return SRTSTATS_PROFMAT_CSV;
684
-
685
-
return SRTSTATS_PROFMAT_INVALID;
686
-
}
687
-
688
356
const char* SRTClockTypeStr()
689
357
{
690
358
const int clock_type = srt_clock_type();
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4