Retabbing and reformatting

This commit is contained in:
Paul-Louis Ageneau
2020-11-13 21:25:52 +01:00
parent b7a682cc50
commit ece1bd9352
43 changed files with 948 additions and 1033 deletions

View File

@ -2,13 +2,14 @@ cmake_minimum_required(VERSION 3.7)
add_executable(datachannel-sfu-media main.cpp)
set_target_properties(datachannel-sfu-media PROPERTIES
CXX_STANDARD 17
OUTPUT_NAME sfu-media)
CXX_STANDARD 17
OUTPUT_NAME sfu-media)
if(WIN32)
target_link_libraries(datachannel-sfu-media datachannel-static) # DLL exports only the C API
target_link_libraries(datachannel-sfu-media datachannel-static) # DLL exports only the C API
else()
target_link_libraries(datachannel-sfu-media datachannel)
target_link_libraries(datachannel-sfu-media datachannel)
endif()
target_link_libraries(datachannel-sfu-media datachannel nlohmann_json)
target_link_libraries(datachannel-sfu-media datachannel nlohmann_json)

View File

@ -29,11 +29,11 @@
using nlohmann::json;
struct Receiver {
std::shared_ptr<rtc::PeerConnection> conn;
std::shared_ptr<rtc::Track> track;
std::shared_ptr<rtc::PeerConnection> conn;
std::shared_ptr<rtc::Track> track;
};
int main() {
std::vector<std::shared_ptr<Receiver>> receivers;
std::vector<std::shared_ptr<Receiver>> receivers;
try {
rtc::InitLogger(rtc::LogLevel::Info);
@ -47,16 +47,17 @@ int main() {
auto description = pc->localDescription();
json message = {{"type", description->typeString()},
{"sdp", std::string(description.value())}};
std::cout << "Please copy/paste this offer to the SENDER: " << message << std::endl;
std::cout << "Please copy/paste this offer to the SENDER: " << message << std::endl;
}
});
rtc::Description::Video media("video", rtc::Description::Direction::RecvOnly);
media.addH264Codec(96);
media.setBitrate(3000); // Request 3Mbps (Browsers do not encode more than 2.5MBps from a webcam)
media.setBitrate(
3000); // Request 3Mbps (Browsers do not encode more than 2.5MBps from a webcam)
auto track = pc->addTrack(media);
pc->setLocalDescription();
pc->setLocalDescription();
auto session = std::make_shared<rtc::RtcpReceivingSession>();
track->setRtcpHandler(session);
@ -66,63 +67,65 @@ int main() {
track->onMessage(
[&receivers](rtc::binary message) {
// This is an RTP packet
auto rtp = (rtc::RTP*) message.data();
auto rtp = (rtc::RTP *)message.data();
rtp->setSsrc(targetSSRC);
for (auto pc : receivers) {
if (pc->track != nullptr && pc->track->isOpen()) {
pc->track->send(message);
}
if (pc->track != nullptr && pc->track->isOpen()) {
pc->track->send(message);
}
}
},
nullptr);
// Set the SENDERS Answer
{
std::cout << "Please copy/paste the answer provided by the SENDER: " << std::endl;
std::string sdp;
std::getline(std::cin, sdp);
std::cout << "Got answer" << sdp << std::endl;
json j = json::parse(sdp);
rtc::Description answer(j["sdp"].get<std::string>(), j["type"].get<std::string>());
pc->setRemoteDescription(answer);
}
// Set the SENDERS Answer
{
std::cout << "Please copy/paste the answer provided by the SENDER: " << std::endl;
std::string sdp;
std::getline(std::cin, sdp);
std::cout << "Got answer" << sdp << std::endl;
json j = json::parse(sdp);
rtc::Description answer(j["sdp"].get<std::string>(), j["type"].get<std::string>());
pc->setRemoteDescription(answer);
}
// For each receiver
// For each receiver
while (true) {
auto pc = std::make_shared<Receiver>();
pc->conn = std::make_shared<rtc::PeerConnection>();
pc->conn->onStateChange(
[](rtc::PeerConnection::State state) { std::cout << "State: " << state << std::endl; });
pc->conn->onGatheringStateChange([pc](rtc::PeerConnection::GatheringState state) {
std::cout << "Gathering State: " << state << std::endl;
if (state == rtc::PeerConnection::GatheringState::Complete) {
auto description = pc->conn->localDescription();
json message = {{"type", description->typeString()},
{"sdp", std::string(description.value())}};
std::cout << "Please copy/paste this offer to the RECEIVER: " << message << std::endl;
}
});
rtc::Description::Video media("video", rtc::Description::Direction::SendOnly);
media.addH264Codec(96);
media.setBitrate(
3000); // Request 3Mbps (Browsers do not encode more than 2.5MBps from a webcam)
auto pc = std::make_shared<Receiver>();
pc->conn = std::make_shared<rtc::PeerConnection>();
pc->conn->onStateChange([](rtc::PeerConnection::State state) {
std::cout << "State: " << state << std::endl;
});
pc->conn->onGatheringStateChange([pc](rtc::PeerConnection::GatheringState state) {
std::cout << "Gathering State: " << state << std::endl;
if (state == rtc::PeerConnection::GatheringState::Complete) {
auto description = pc->conn->localDescription();
json message = {{"type", description->typeString()},
{"sdp", std::string(description.value())}};
std::cout << "Please copy/paste this offer to the RECEIVER: " << message
<< std::endl;
}
});
rtc::Description::Video media("video", rtc::Description::Direction::SendOnly);
media.addH264Codec(96);
media.setBitrate(
3000); // Request 3Mbps (Browsers do not encode more than 2.5MBps from a webcam)
media.addSSRC(targetSSRC, "video-send");
media.addSSRC(targetSSRC, "video-send");
pc->track = pc->conn->addTrack(media);
pc->conn->setLocalDescription();
pc->track = pc->conn->addTrack(media);
pc->conn->setLocalDescription();
pc->track->onMessage([](rtc::binary var){}, nullptr);
pc->track->onMessage([](rtc::binary var) {}, nullptr);
std::cout << "Please copy/paste the answer provided by the RECEIVER: " << std::endl;
std::string sdp;
std::getline(std::cin, sdp);
std::cout << "Got answer" << sdp << std::endl;
json j = json::parse(sdp);
rtc::Description answer(j["sdp"].get<std::string>(), j["type"].get<std::string>());
pc->conn->setRemoteDescription(answer);
std::cout << "Please copy/paste the answer provided by the RECEIVER: " << std::endl;
std::string sdp;
std::getline(std::cin, sdp);
std::cout << "Got answer" << sdp << std::endl;
json j = json::parse(sdp);
rtc::Description answer(j["sdp"].get<std::string>(), j["type"].get<std::string>());
pc->conn->setRemoteDescription(answer);
receivers.push_back(pc);
receivers.push_back(pc);
}
} catch (const std::exception &e) {

View File

@ -72,4 +72,3 @@ std::ostream &operator<<(std::ostream &out, const rtc::Candidate::Type &type);
std::ostream &operator<<(std::ostream &out, const rtc::Candidate::TransportType &transportType);
#endif

View File

@ -38,8 +38,8 @@ class PeerConnection;
class DataChannel : public std::enable_shared_from_this<DataChannel>, public Channel {
public:
DataChannel(std::weak_ptr<PeerConnection> pc, uint16_t stream, string label,
string protocol, Reliability reliability);
DataChannel(std::weak_ptr<PeerConnection> pc, uint16_t stream, string label, string protocol,
Reliability reliability);
virtual ~DataChannel();
uint16_t stream() const;
@ -90,9 +90,9 @@ private:
class NegociatedDataChannel final : public DataChannel {
public:
NegociatedDataChannel(std::weak_ptr<PeerConnection> pc, uint16_t stream, string label,
string protocol, Reliability reliability);
string protocol, Reliability reliability);
NegociatedDataChannel(std::weak_ptr<PeerConnection> pc, std::weak_ptr<SctpTransport> transport,
uint16_t stream);
uint16_t stream);
~NegociatedDataChannel();
private:

View File

@ -77,11 +77,9 @@ public:
virtual void parseSdpLine(string_view line);
std::vector<string>::iterator beginAttributes();
std::vector<string>::iterator endAttributes();
std::vector<string>::iterator removeAttribute(std::vector<string>::iterator iterator);
std::vector<string>::iterator beginAttributes();
std::vector<string>::iterator endAttributes();
std::vector<string>::iterator removeAttribute(std::vector<string>::iterator iterator);
protected:
Entry(const string &mline, string mid, Direction dir = Direction::Unknown);
@ -130,13 +128,13 @@ public:
string description() const override;
Media reciprocate() const;
void removeFormat(const string &fmt);
void removeFormat(const string &fmt);
void addSSRC(uint32_t ssrc, std::string name);
void addSSRC(uint32_t ssrc);
void replaceSSRC(uint32_t oldSSRC, uint32_t ssrc, string name);
bool hasSSRC(uint32_t ssrc);
std::vector<uint32_t> getSSRCs();
void addSSRC(uint32_t ssrc, std::string name);
void addSSRC(uint32_t ssrc);
void replaceSSRC(uint32_t oldSSRC, uint32_t ssrc, string name);
bool hasSSRC(uint32_t ssrc);
std::vector<uint32_t> getSSRCs();
void setBitrate(int bitrate);
int getBitrate() const;
@ -145,32 +143,29 @@ public:
virtual void parseSdpLine(string_view line) override;
struct RTPMap {
RTPMap(string_view mline);
RTPMap() {}
struct RTPMap {
RTPMap(string_view mline);
RTPMap() {}
void removeFB(const string &string);
void addFB(const string &string);
void addAttribute(std::string attr) {
fmtps.emplace_back(attr);
}
void removeFB(const string &string);
void addFB(const string &string);
void addAttribute(std::string attr) { fmtps.emplace_back(attr); }
int pt;
string format;
int clockRate;
string encParams;
int pt;
string format;
int clockRate;
string encParams;
std::vector<string> rtcpFbs;
std::vector<string> fmtps;
std::vector<string> rtcpFbs;
std::vector<string> fmtps;
static int parsePT(string_view view);
void setMLine(string_view view);
};
static int parsePT(string_view view);
void setMLine(string_view view);
};
std::map<int, RTPMap>::iterator beginMaps();
std::map<int, RTPMap>::iterator endMaps();
std::map<int, RTPMap>::iterator removeMap(std::map<int, RTPMap>::iterator iterator);
std::map<int, RTPMap>::iterator beginMaps();
std::map<int, RTPMap>::iterator endMaps();
std::map<int, RTPMap>::iterator removeMap(std::map<int, RTPMap>::iterator iterator);
private:
virtual string generateSdpLines(string_view eol) const override;
@ -184,26 +179,25 @@ public:
std::vector<uint32_t> mSsrcs;
public:
void addRTPMap(const RTPMap& map);
};
void addRTPMap(const RTPMap &map);
};
class Audio : public Media {
public:
Audio(string mid = "audio", Direction dir = Direction::SendOnly);
void addAudioCodec(int payloadType, const string &codec);
void addOpusCodec(int payloadType);
void addAudioCodec(int payloadType, const string &codec);
void addOpusCodec(int payloadType);
};
class Video : public Media {
public:
Video(string mid = "video", Direction dir = Direction::SendOnly);
void addVideoCodec(int payloadType, const string &codec);
void addH264Codec(int payloadType);
void addVP8Codec(int payloadType);
void addVP9Codec(int payloadType);
void addVideoCodec(int payloadType, const string &codec);
void addH264Codec(int payloadType);
void addVP8Codec(int payloadType);
void addVP9Codec(int payloadType);
};
bool hasApplication() const;

View File

@ -49,6 +49,6 @@ enum class LogLevel { // Don't change, it must match plog severity
void InitLogger(LogLevel level);
void InitLogger(plog::Severity severity, plog::IAppender *appender = nullptr);
}
} // namespace rtc
#endif

View File

@ -139,8 +139,8 @@ private:
void forwardMessage(message_ptr message);
void forwardMedia(message_ptr message);
void forwardBufferedAmount(uint16_t stream, size_t amount);
std::optional<std::string> getMidFromSSRC(SSRC ssrc);
std::optional<uint32_t> getMLineFromSSRC(SSRC ssrc);
std::optional<std::string> getMidFromSSRC(SSRC ssrc);
std::optional<uint32_t> getMLineFromSSRC(SSRC ssrc);
std::shared_ptr<DataChannel> emplaceDataChannel(Description::Role role, string label,
DataChannelInit init);
@ -153,7 +153,6 @@ private:
void incomingTrack(Description::Media description);
void openTracks();
void validateRemoteDescription(const Description &description);
void processLocalDescription(Description description);
void processLocalCandidate(Candidate candidate);
@ -182,13 +181,13 @@ private:
std::shared_ptr<DtlsTransport> mDtlsTransport;
std::shared_ptr<SctpTransport> mSctpTransport;
std::unordered_map<uint16_t, std::weak_ptr<DataChannel>> mDataChannels; // by stream ID
std::unordered_map<string, std::weak_ptr<Track>> mTracks; // by mid
std::vector<std::weak_ptr<Track>> mTrackLines; // by SDP order
std::unordered_map<uint16_t, std::weak_ptr<DataChannel>> mDataChannels; // by stream ID
std::unordered_map<string, std::weak_ptr<Track>> mTracks; // by mid
std::vector<std::weak_ptr<Track>> mTrackLines; // by SDP order
std::shared_mutex mDataChannelsMutex, mTracksMutex;
std::unordered_map<uint32_t, string> mMidFromSssrc; // cache
std::unordered_map<uint32_t , unsigned int> mMLineFromSssrc; // cache
std::unordered_map<uint32_t, string> mMidFromSssrc; // cache
std::unordered_map<uint32_t, unsigned int> mMLineFromSssrc; // cache
std::atomic<State> mState;
std::atomic<GatheringState> mGatheringState;

View File

@ -170,4 +170,3 @@ template <typename T> std::optional<T> Queue<T>::popImpl() {
} // namespace rtc
#endif

View File

@ -37,4 +37,3 @@ struct Reliability {
} // namespace rtc
#endif

View File

@ -102,12 +102,14 @@ typedef struct {
const char *protocol; // empty string if NULL
bool negotiated;
bool manualStream;
uint16_t stream; // numeric ID 0-65534, ignored if manualStream is false
uint16_t stream; // numeric ID 0-65534, ignored if manualStream is false
} rtcDataChannelInit;
typedef void(RTC_API *rtcLogCallbackFunc)(rtcLogLevel level, const char *message);
typedef void(RTC_API *rtcDescriptionCallbackFunc)(int pc, const char *sdp, const char *type, void *ptr);
typedef void(RTC_API *rtcCandidateCallbackFunc)(int pc, const char *cand, const char *mid, void *ptr);
typedef void(RTC_API *rtcDescriptionCallbackFunc)(int pc, const char *sdp, const char *type,
void *ptr);
typedef void(RTC_API *rtcCandidateCallbackFunc)(int pc, const char *cand, const char *mid,
void *ptr);
typedef void(RTC_API *rtcStateChangeCallbackFunc)(int pc, rtcState state, void *ptr);
typedef void(RTC_API *rtcGatheringStateCallbackFunc)(int pc, rtcGatheringState state, void *ptr);
typedef void(RTC_API *rtcSignalingStateCallbackFunc)(int pc, rtcSignalingState state, void *ptr);
@ -147,15 +149,18 @@ RTC_EXPORT int rtcGetRemoteDescription(int pc, char *buffer, int size);
RTC_EXPORT int rtcGetLocalAddress(int pc, char *buffer, int size);
RTC_EXPORT int rtcGetRemoteAddress(int pc, char *buffer, int size);
RTC_EXPORT int rtcGetSelectedCandidatePair(int pc, char *local, int localSize, char *remote, int remoteSize);
RTC_EXPORT int rtcGetSelectedCandidatePair(int pc, char *local, int localSize, char *remote,
int remoteSize);
// DataChannel
RTC_EXPORT int rtcSetDataChannelCallback(int pc, rtcDataChannelCallbackFunc cb);
RTC_EXPORT int rtcAddDataChannel(int pc, const char *label); // returns dc id
RTC_EXPORT int rtcAddDataChannelEx(int pc, const char *label, const rtcDataChannelInit *init); // returns dc id
RTC_EXPORT int rtcAddDataChannelEx(int pc, const char *label,
const rtcDataChannelInit *init); // returns dc id
// Equivalent to calling rtcAddDataChannel() and rtcSetLocalDescription()
RTC_EXPORT int rtcCreateDataChannel(int pc, const char *label); // returns dc id
RTC_EXPORT int rtcCreateDataChannelEx(int pc, const char *label, const rtcDataChannelInit *init); // returns dc id
RTC_EXPORT int rtcCreateDataChannelEx(int pc, const char *label,
const rtcDataChannelInit *init); // returns dc id
RTC_EXPORT int rtcDeleteDataChannel(int dc);
RTC_EXPORT int rtcGetDataChannelStream(int dc);

View File

@ -27,4 +27,3 @@
// C API
#include "rtc.h"

View File

@ -31,35 +31,34 @@ namespace rtc {
class RtcpHandler {
protected:
/**
* Use this callback when trying to send custom data (such as RTCP) to the client.
*/
synchronized_callback<rtc::message_ptr> outgoingCallback;
/**
* Use this callback when trying to send custom data (such as RTCP) to the client.
*/
synchronized_callback<rtc::message_ptr> outgoingCallback;
public:
/**
* Called when there is traffic coming from the peer
* @param ptr
* @return
*/
virtual rtc::message_ptr incoming(rtc::message_ptr ptr) = 0;
/**
* Called when there is traffic coming from the peer
* @param ptr
* @return
*/
virtual rtc::message_ptr incoming(rtc::message_ptr ptr) = 0;
/**
* Called when there is traffic that needs to be sent to the peer
* @param ptr
* @return
*/
virtual rtc::message_ptr outgoing(rtc::message_ptr ptr) = 0;
/**
* Called when there is traffic that needs to be sent to the peer
* @param ptr
* @return
*/
virtual rtc::message_ptr outgoing(rtc::message_ptr ptr) = 0;
/**
* This callback is used to send traffic back to the peer.
* This callback skips calling the track's methods.
* @param cb
*/
void onOutgoing(const std::function<void(rtc::message_ptr)> &cb);
/**
* This callback is used to send traffic back to the peer.
* This callback skips calling the track's methods.
* @param cb
*/
void onOutgoing(const std::function<void(rtc::message_ptr)>& cb);
virtual bool requestKeyframe() {return false;}
virtual bool requestKeyframe() { return false; }
};
class Track;
@ -67,20 +66,19 @@ class Track;
// An RtcpSession can be plugged into a Track to handle the whole RTCP session
class RtcpReceivingSession : public RtcpHandler {
public:
rtc::message_ptr incoming(rtc::message_ptr ptr) override;
rtc::message_ptr outgoing(rtc::message_ptr ptr) override;
bool send(rtc::message_ptr ptr);
rtc::message_ptr incoming(rtc::message_ptr ptr) override;
rtc::message_ptr outgoing(rtc::message_ptr ptr) override;
bool send(rtc::message_ptr ptr);
void requestBitrate(unsigned int newBitrate);
bool requestKeyframe() override;
bool requestKeyframe() override;
protected:
void pushREMB(unsigned int bitrate);
void pushRR(unsigned int lastSR_delay);
void pushPLI();
void pushPLI();
unsigned int mRequestedBitrate = 0;
SSRC mSsrc = 0;

View File

@ -37,491 +37,456 @@
#endif
namespace rtc {
typedef uint32_t SSRC;
typedef uint32_t SSRC;
#pragma pack(push, 1)
struct RTP {
private:
uint8_t _first;
uint8_t _payloadType;
uint16_t _seqNumber;
uint32_t _timestamp;
SSRC _ssrc;
uint8_t _first;
uint8_t _payloadType;
uint16_t _seqNumber;
uint32_t _timestamp;
SSRC _ssrc;
public:
SSRC csrc[16];
SSRC csrc[16];
inline uint8_t version() const { return _first >> 6; }
inline bool padding() const { return (_first >> 5) & 0x01; }
inline uint8_t csrcCount() const { return _first & 0x0F; }
inline uint8_t marker() const { return _payloadType & 0b10000000; }
inline uint8_t payloadType() const { return _payloadType & 0b01111111; }
inline uint16_t seqNumber() const { return ntohs(_seqNumber); }
inline uint32_t timestamp() const { return ntohl(_timestamp); }
inline uint32_t ssrc() const { return ntohl(_ssrc);}
inline uint8_t version() const { return _first >> 6; }
inline bool padding() const { return (_first >> 5) & 0x01; }
inline uint8_t csrcCount() const { return _first & 0x0F; }
inline uint8_t marker() const { return _payloadType & 0b10000000; }
inline uint8_t payloadType() const { return _payloadType & 0b01111111; }
inline uint16_t seqNumber() const { return ntohs(_seqNumber); }
inline uint32_t timestamp() const { return ntohl(_timestamp); }
inline uint32_t ssrc() const { return ntohl(_ssrc); }
inline size_t getSize() const {
return ((char*)&csrc) - ((char*)this) + sizeof(SSRC)*csrcCount();
}
inline size_t getSize() const {
return ((char *)&csrc) - ((char *)this) + sizeof(SSRC) * csrcCount();
}
char * getBody() const {
return ((char*) &csrc) + sizeof(SSRC)*csrcCount();
}
char *getBody() const { return ((char *)&csrc) + sizeof(SSRC) * csrcCount(); }
inline void setSeqNumber(uint16_t newSeqNo) {
_seqNumber = htons(newSeqNo);
}
inline void setPayloadType(uint8_t newPayloadType) {
_payloadType = (_payloadType & 0b10000000u) | (0b01111111u & newPayloadType);
}
inline void setSsrc(uint32_t ssrc) {
_ssrc = htonl(ssrc);
}
inline void setSeqNumber(uint16_t newSeqNo) { _seqNumber = htons(newSeqNo); }
inline void setPayloadType(uint8_t newPayloadType) {
_payloadType = (_payloadType & 0b10000000u) | (0b01111111u & newPayloadType);
}
inline void setSsrc(uint32_t ssrc) { _ssrc = htonl(ssrc); }
void setTimestamp(uint32_t i) {
_timestamp = htonl(i);
}
void setTimestamp(uint32_t i) { _timestamp = htonl(i); }
};
struct RTCP_ReportBlock {
SSRC ssrc;
SSRC ssrc;
private:
uint32_t _fractionLostAndPacketsLost; // fraction lost is 8-bit, packets lost is 24-bit
uint16_t _seqNoCycles;
uint16_t _highestSeqNo;
uint32_t _jitter;
uint32_t _lastReport;
uint32_t _delaySinceLastReport;
uint32_t _fractionLostAndPacketsLost; // fraction lost is 8-bit, packets lost is 24-bit
uint16_t _seqNoCycles;
uint16_t _highestSeqNo;
uint32_t _jitter;
uint32_t _lastReport;
uint32_t _delaySinceLastReport;
public:
inline void preparePacket(SSRC ssrc, [[maybe_unused]] unsigned int packetsLost,
[[maybe_unused]] unsigned int totalPackets, uint16_t highestSeqNo,
uint16_t seqNoCycles, uint32_t jitter, uint64_t lastSR_NTP,
uint64_t lastSR_DELAY) {
setSeqNo(highestSeqNo, seqNoCycles);
setJitter(jitter);
setSSRC(ssrc);
inline void preparePacket(SSRC ssrc, [[maybe_unused]] unsigned int packetsLost,
[[maybe_unused]] unsigned int totalPackets, uint16_t highestSeqNo,
uint16_t seqNoCycles, uint32_t jitter, uint64_t lastSR_NTP,
uint64_t lastSR_DELAY) {
setSeqNo(highestSeqNo, seqNoCycles);
setJitter(jitter);
setSSRC(ssrc);
// Middle 32 bits of NTP Timestamp
// this->lastReport = lastSR_NTP >> 16u;
setNTPOfSR(uint64_t(lastSR_NTP));
setDelaySinceSR(uint32_t(lastSR_DELAY));
// Middle 32 bits of NTP Timestamp
// this->lastReport = lastSR_NTP >> 16u;
setNTPOfSR(uint64_t(lastSR_NTP));
setDelaySinceSR(uint32_t(lastSR_DELAY));
// The delay, expressed in units of 1/65536 seconds
// this->delaySinceLastReport = lastSR_DELAY;
}
// The delay, expressed in units of 1/65536 seconds
// this->delaySinceLastReport = lastSR_DELAY;
}
inline void setSSRC(SSRC ssrc) { this->ssrc = htonl(ssrc); }
inline SSRC getSSRC() const { return ntohl(ssrc); }
inline void setSSRC(SSRC ssrc) { this->ssrc = htonl(ssrc); }
inline SSRC getSSRC() const { return ntohl(ssrc); }
inline void setPacketsLost([[maybe_unused]] unsigned int packetsLost,
[[maybe_unused]] unsigned int totalPackets) {
// TODO Implement loss percentages.
_fractionLostAndPacketsLost = 0;
}
inline unsigned int getLossPercentage() const {
// TODO Implement loss percentages.
return 0;
}
inline unsigned int getPacketLostCount() const {
// TODO Implement total packets lost.
return 0;
}
inline void setPacketsLost([[maybe_unused]] unsigned int packetsLost,
[[maybe_unused]] unsigned int totalPackets) {
// TODO Implement loss percentages.
_fractionLostAndPacketsLost = 0;
}
inline unsigned int getLossPercentage() const {
// TODO Implement loss percentages.
return 0;
}
inline unsigned int getPacketLostCount() const {
// TODO Implement total packets lost.
return 0;
}
inline uint16_t seqNoCycles() const { return ntohs(_seqNoCycles); }
inline uint16_t highestSeqNo() const { return ntohs(_highestSeqNo); }
inline uint32_t jitter() const { return ntohl(_jitter); }
inline uint16_t seqNoCycles() const { return ntohs(_seqNoCycles); }
inline uint16_t highestSeqNo() const { return ntohs(_highestSeqNo); }
inline uint32_t jitter() const { return ntohl(_jitter); }
inline void setSeqNo(uint16_t highestSeqNo, uint16_t seqNoCycles) {
_highestSeqNo = htons(highestSeqNo);
_seqNoCycles = htons(seqNoCycles);
}
inline void setSeqNo(uint16_t highestSeqNo, uint16_t seqNoCycles) {
_highestSeqNo = htons(highestSeqNo);
_seqNoCycles = htons(seqNoCycles);
}
inline void setJitter(uint32_t jitter) { _jitter = htonl(jitter); }
inline void setJitter(uint32_t jitter) { _jitter = htonl(jitter); }
inline void setNTPOfSR(uint64_t ntp) { _lastReport = htonll(ntp >> 16u); }
inline uint32_t getNTPOfSR() const { return ntohl(_lastReport) << 16u; }
inline void setNTPOfSR(uint64_t ntp) { _lastReport = htonll(ntp >> 16u); }
inline uint32_t getNTPOfSR() const { return ntohl(_lastReport) << 16u; }
inline void setDelaySinceSR(uint32_t sr) {
// The delay, expressed in units of 1/65536 seconds
_delaySinceLastReport = htonl(sr);
}
inline uint32_t getDelaySinceSR() const { return ntohl(_delaySinceLastReport); }
inline void setDelaySinceSR(uint32_t sr) {
// The delay, expressed in units of 1/65536 seconds
_delaySinceLastReport = htonl(sr);
}
inline uint32_t getDelaySinceSR() const { return ntohl(_delaySinceLastReport); }
inline void log() const {
PLOG_VERBOSE << "RTCP report block: "
<< "ssrc="
<< ntohl(ssrc)
// TODO: Implement these reports
// << ", fractionLost=" << fractionLost
// << ", packetsLost=" << packetsLost
<< ", highestSeqNo=" << highestSeqNo() << ", seqNoCycles=" << seqNoCycles()
<< ", jitter=" << jitter() << ", lastSR=" << getNTPOfSR()
<< ", lastSRDelay=" << getDelaySinceSR();
}
inline void log() const {
PLOG_VERBOSE << "RTCP report block: "
<< "ssrc="
<< ntohl(ssrc)
// TODO: Implement these reports
// << ", fractionLost=" << fractionLost
// << ", packetsLost=" << packetsLost
<< ", highestSeqNo=" << highestSeqNo() << ", seqNoCycles=" << seqNoCycles()
<< ", jitter=" << jitter() << ", lastSR=" << getNTPOfSR()
<< ", lastSRDelay=" << getDelaySinceSR();
}
};
struct RTCP_HEADER {
private:
uint8_t _first;
uint8_t _payloadType;
uint16_t _length;
uint8_t _first;
uint8_t _payloadType;
uint16_t _length;
public:
inline uint8_t version() const { return _first >> 6; }
inline bool padding() const { return (_first >> 5) & 0x01; }
inline uint8_t reportCount() const { return _first & 0x0F; }
inline uint8_t payloadType() const { return _payloadType; }
inline uint16_t length() const { return ntohs(_length); }
inline size_t lengthInBytes() const {
return (1+length())*4;
}
inline uint8_t version() const { return _first >> 6; }
inline bool padding() const { return (_first >> 5) & 0x01; }
inline uint8_t reportCount() const { return _first & 0x0F; }
inline uint8_t payloadType() const { return _payloadType; }
inline uint16_t length() const { return ntohs(_length); }
inline size_t lengthInBytes() const { return (1 + length()) * 4; }
inline void setPayloadType(uint8_t type) { _payloadType = type; }
inline void setReportCount(uint8_t count) { _first = (_first & 0b11100000u) | (count & 0b00011111u); }
inline void setLength(uint16_t length) { _length = htons(length); }
inline void setPayloadType(uint8_t type) { _payloadType = type; }
inline void setReportCount(uint8_t count) {
_first = (_first & 0b11100000u) | (count & 0b00011111u);
}
inline void setLength(uint16_t length) { _length = htons(length); }
inline void prepareHeader(uint8_t payloadType, uint8_t reportCount, uint16_t length) {
_first = 0b10000000; // version 2, no padding
setReportCount(reportCount);
setPayloadType(payloadType);
setLength(length);
}
inline void prepareHeader(uint8_t payloadType, uint8_t reportCount, uint16_t length) {
_first = 0b10000000; // version 2, no padding
setReportCount(reportCount);
setPayloadType(payloadType);
setLength(length);
}
inline void log() const {
PLOG_INFO << "RTCP header: "
<< "version=" << unsigned(version()) << ", padding=" << padding()
<< ", reportCount=" << unsigned(reportCount())
<< ", payloadType=" << unsigned(payloadType()) << ", length=" << length();
}
inline void log() const {
PLOG_INFO << "RTCP header: "
<< "version=" << unsigned(version()) << ", padding=" << padding()
<< ", reportCount=" << unsigned(reportCount())
<< ", payloadType=" << unsigned(payloadType()) << ", length=" << length();
}
};
struct RTCP_FB_HEADER {
RTCP_HEADER header;
SSRC packetSender;
SSRC mediaSource;
RTCP_HEADER header;
SSRC packetSender;
SSRC mediaSource;
[[nodiscard]] SSRC getPacketSenderSSRC() const {
return ntohl(packetSender);
}
[[nodiscard]] SSRC getPacketSenderSSRC() const { return ntohl(packetSender); }
[[nodiscard]] SSRC getMediaSourceSSRC() const {
return ntohl(mediaSource);
}
[[nodiscard]] SSRC getMediaSourceSSRC() const { return ntohl(mediaSource); }
void setPacketSenderSSRC(SSRC ssrc) {
this->packetSender = htonl(ssrc);
}
void setPacketSenderSSRC(SSRC ssrc) { this->packetSender = htonl(ssrc); }
void setMediaSourceSSRC(SSRC ssrc) {
this->mediaSource = htonl(ssrc);
}
void setMediaSourceSSRC(SSRC ssrc) { this->mediaSource = htonl(ssrc); }
void log() {
header.log();
PLOG_VERBOSE << "FB: " << " packet sender: " << getPacketSenderSSRC() << " media source: " << getMediaSourceSSRC();
}
void log() {
header.log();
PLOG_VERBOSE << "FB: "
<< " packet sender: " << getPacketSenderSSRC()
<< " media source: " << getMediaSourceSSRC();
}
};
struct RTCP_SR {
RTCP_HEADER header;
SSRC _senderSSRC;
RTCP_HEADER header;
SSRC _senderSSRC;
private:
uint64_t _ntpTimestamp;
uint32_t _rtpTimestamp;
uint32_t _packetCount;
uint32_t _octetCount;
uint64_t _ntpTimestamp;
uint32_t _rtpTimestamp;
uint32_t _packetCount;
uint32_t _octetCount;
RTCP_ReportBlock _reportBlocks;
RTCP_ReportBlock _reportBlocks;
public:
inline void preparePacket(SSRC senderSSRC, uint8_t reportCount) {
unsigned int length =
((sizeof(header) + 24 + reportCount * sizeof(RTCP_ReportBlock)) / 4) - 1;
header.prepareHeader(200, reportCount, uint16_t(length));
this->_senderSSRC = htonl(senderSSRC);
}
inline void preparePacket(SSRC senderSSRC, uint8_t reportCount) {
unsigned int length =
((sizeof(header) + 24 + reportCount * sizeof(RTCP_ReportBlock)) / 4) - 1;
header.prepareHeader(200, reportCount, uint16_t(length));
this->_senderSSRC = htonl(senderSSRC);
}
inline RTCP_ReportBlock *getReportBlock(int num) { return &_reportBlocks + num; }
inline const RTCP_ReportBlock *getReportBlock(int num) const { return &_reportBlocks + num; }
inline RTCP_ReportBlock *getReportBlock(int num) { return &_reportBlocks + num; }
inline const RTCP_ReportBlock *getReportBlock(int num) const { return &_reportBlocks + num; }
[[nodiscard]] inline size_t getSize() const {
// "length" in packet is one less than the number of 32 bit words in the packet.
return sizeof(uint32_t) * (1 + size_t(header.length()));
}
[[nodiscard]] inline size_t getSize() const {
// "length" in packet is one less than the number of 32 bit words in the packet.
return sizeof(uint32_t) * (1 + size_t(header.length()));
}
inline uint64_t ntpTimestamp() const { return ntohll(_ntpTimestamp); }
inline uint32_t rtpTimestamp() const { return ntohl(_rtpTimestamp); }
inline uint32_t packetCount() const { return ntohl(_packetCount); }
inline uint32_t octetCount() const { return ntohl(_octetCount); }
inline uint32_t senderSSRC() const {return ntohl(_senderSSRC);}
inline uint64_t ntpTimestamp() const { return ntohll(_ntpTimestamp); }
inline uint32_t rtpTimestamp() const { return ntohl(_rtpTimestamp); }
inline uint32_t packetCount() const { return ntohl(_packetCount); }
inline uint32_t octetCount() const { return ntohl(_octetCount); }
inline uint32_t senderSSRC() const { return ntohl(_senderSSRC); }
inline void setNtpTimestamp(uint32_t ts) { _ntpTimestamp = htonll(ts); }
inline void setRtpTimestamp(uint32_t ts) { _rtpTimestamp = htonl(ts); }
inline void setNtpTimestamp(uint32_t ts) { _ntpTimestamp = htonll(ts); }
inline void setRtpTimestamp(uint32_t ts) { _rtpTimestamp = htonl(ts); }
inline void log() const {
header.log();
PLOG_VERBOSE << "RTCP SR: "
<< " SSRC=" << senderSSRC() << ", NTP_TS=" << ntpTimestamp()
<< ", RTP_TS=" << rtpTimestamp() << ", packetCount=" << packetCount()
<< ", octetCount=" << octetCount();
inline void log() const {
header.log();
PLOG_VERBOSE << "RTCP SR: "
<< " SSRC=" << senderSSRC() << ", NTP_TS=" << ntpTimestamp()
<< ", RTP_TS=" << rtpTimestamp() << ", packetCount=" << packetCount()
<< ", octetCount=" << octetCount();
for (unsigned i = 0; i < unsigned(header.reportCount()); i++) {
getReportBlock(i)->log();
}
}
for (unsigned i = 0; i < unsigned(header.reportCount()); i++) {
getReportBlock(i)->log();
}
}
};
struct RTCP_RR {
RTCP_HEADER header;
SSRC _senderSSRC;
RTCP_HEADER header;
SSRC _senderSSRC;
private:
RTCP_ReportBlock _reportBlocks;
RTCP_ReportBlock _reportBlocks;
public:
inline RTCP_ReportBlock *getReportBlock(int num) { return &_reportBlocks + num; }
inline const RTCP_ReportBlock *getReportBlock(int num) const { return &_reportBlocks + num; }
inline RTCP_ReportBlock *getReportBlock(int num) { return &_reportBlocks + num; }
inline const RTCP_ReportBlock *getReportBlock(int num) const { return &_reportBlocks + num; }
inline SSRC senderSSRC() const { return ntohl(_senderSSRC); }
inline void setSenderSSRC(SSRC ssrc) { this->_senderSSRC = htonl(ssrc); }
inline SSRC senderSSRC() const { return ntohl(_senderSSRC); }
inline void setSenderSSRC(SSRC ssrc) { this->_senderSSRC = htonl(ssrc); }
[[nodiscard]] inline size_t getSize() const {
// "length" in packet is one less than the number of 32 bit words in the packet.
return sizeof(uint32_t) * (1 + size_t(header.length()));
}
[[nodiscard]] inline size_t getSize() const {
// "length" in packet is one less than the number of 32 bit words in the packet.
return sizeof(uint32_t) * (1 + size_t(header.length()));
}
inline void preparePacket(SSRC senderSSRC, uint8_t reportCount) {
// "length" in packet is one less than the number of 32 bit words in the packet.
size_t length = (sizeWithReportBlocks(reportCount) / 4) - 1;
header.prepareHeader(201, reportCount, uint16_t(length));
this->_senderSSRC = htonl(senderSSRC);
}
inline void preparePacket(SSRC senderSSRC, uint8_t reportCount) {
// "length" in packet is one less than the number of 32 bit words in the packet.
size_t length = (sizeWithReportBlocks(reportCount) / 4) - 1;
header.prepareHeader(201, reportCount, uint16_t(length));
this->_senderSSRC = htonl(senderSSRC);
}
inline static size_t sizeWithReportBlocks(uint8_t reportCount) {
return sizeof(header) + 4 + size_t(reportCount) * sizeof(RTCP_ReportBlock);
}
inline static size_t sizeWithReportBlocks(uint8_t reportCount) {
return sizeof(header) + 4 + size_t(reportCount) * sizeof(RTCP_ReportBlock);
}
inline bool isSenderReport() {
return header.payloadType() == 200;
}
inline bool isSenderReport() { return header.payloadType() == 200; }
inline bool isReceiverReport() {
return header.payloadType() == 201;
}
inline bool isReceiverReport() { return header.payloadType() == 201; }
inline void log() const {
header.log();
PLOG_VERBOSE << "RTCP RR: "
<< " SSRC=" << ntohl(_senderSSRC);
inline void log() const {
header.log();
PLOG_VERBOSE << "RTCP RR: "
<< " SSRC=" << ntohl(_senderSSRC);
for (unsigned i = 0; i < unsigned(header.reportCount()); i++) {
getReportBlock(i)->log();
}
}
for (unsigned i = 0; i < unsigned(header.reportCount()); i++) {
getReportBlock(i)->log();
}
}
};
struct RTCP_REMB {
RTCP_FB_HEADER header;
RTCP_FB_HEADER header;
/*! \brief Unique identifier ('R' 'E' 'M' 'B') */
char id[4];
/*! \brief Unique identifier ('R' 'E' 'M' 'B') */
char id[4];
/*! \brief Num SSRC, Br Exp, Br Mantissa (bit mask) */
uint32_t bitrate;
/*! \brief Num SSRC, Br Exp, Br Mantissa (bit mask) */
uint32_t bitrate;
SSRC ssrc[1];
SSRC ssrc[1];
[[nodiscard]] unsigned int getSize() const {
// "length" in packet is one less than the number of 32 bit words in the packet.
return sizeof(uint32_t) * (1 + header.header.length());
}
[[nodiscard]] unsigned int getSize() const {
// "length" in packet is one less than the number of 32 bit words in the packet.
return sizeof(uint32_t) * (1 + header.header.length());
}
void preparePacket(SSRC senderSSRC, unsigned int numSSRC, unsigned int bitrate) {
void preparePacket(SSRC senderSSRC, unsigned int numSSRC, unsigned int bitrate) {
// Report Count becomes the format here.
header.header.prepareHeader(206, 15, 0);
// Report Count becomes the format here.
header.header.prepareHeader(206, 15, 0);
// Always zero.
header.setMediaSourceSSRC(0);
// Always zero.
header.setMediaSourceSSRC(0);
header.setPacketSenderSSRC(senderSSRC);
header.setPacketSenderSSRC(senderSSRC);
id[0] = 'R';
id[1] = 'E';
id[2] = 'M';
id[3] = 'B';
id[0] = 'R';
id[1] = 'E';
id[2] = 'M';
id[3] = 'B';
setBitrate(numSSRC, bitrate);
}
setBitrate(numSSRC, bitrate);
}
void setBitrate(unsigned int numSSRC, unsigned int bitrate) {
unsigned int exp = 0;
while (bitrate > pow(2, 18) - 1) {
exp++;
bitrate /= 2;
}
void setBitrate(unsigned int numSSRC, unsigned int bitrate) {
unsigned int exp = 0;
while (bitrate > pow(2, 18) - 1) {
exp++;
bitrate /= 2;
}
// "length" in packet is one less than the number of 32 bit words in the packet.
header.header.setLength(uint16_t((offsetof(RTCP_REMB, ssrc) / sizeof(uint32_t)) - 1 + numSSRC));
// "length" in packet is one less than the number of 32 bit words in the packet.
header.header.setLength(
uint16_t((offsetof(RTCP_REMB, ssrc) / sizeof(uint32_t)) - 1 + numSSRC));
this->bitrate = htonl(
(numSSRC << (32u - 8u)) | (exp << (32u - 8u - 6u)) | bitrate
);
}
this->bitrate = htonl((numSSRC << (32u - 8u)) | (exp << (32u - 8u - 6u)) | bitrate);
}
void setSsrc(int iterator, SSRC newSssrc){
ssrc[iterator] = htonl(newSssrc);
}
void setSsrc(int iterator, SSRC newSssrc) { ssrc[iterator] = htonl(newSssrc); }
size_t static inline sizeWithSSRCs(int count) {
return sizeof(RTCP_REMB) + (count-1)*sizeof(SSRC);
}
size_t static inline sizeWithSSRCs(int count) {
return sizeof(RTCP_REMB) + (count - 1) * sizeof(SSRC);
}
};
struct RTCP_PLI {
RTCP_FB_HEADER header;
RTCP_FB_HEADER header;
void preparePacket(SSRC messageSSRC) {
header.header.prepareHeader(206, 1, 2);
header.setPacketSenderSSRC(messageSSRC);
header.setMediaSourceSSRC(messageSSRC);
}
void preparePacket(SSRC messageSSRC) {
header.header.prepareHeader(206, 1, 2);
header.setPacketSenderSSRC(messageSSRC);
header.setMediaSourceSSRC(messageSSRC);
}
void print() {
header.log();
}
void print() { header.log(); }
[[nodiscard]] static unsigned int size() {
return sizeof(RTCP_FB_HEADER);
}
[[nodiscard]] static unsigned int size() { return sizeof(RTCP_FB_HEADER); }
};
struct RTCP_FIR_PART {
uint32_t ssrc;
uint32_t ssrc;
#if __BYTE_ORDER == __BIG_ENDIAN
uint32_t seqNo: 8;
uint32_t: 24;
uint32_t seqNo : 8;
uint32_t : 24;
#elif __BYTE_ORDER == __LITTLE_ENDIAN
uint32_t: 24;
uint32_t seqNo: 8;
uint32_t : 24;
uint32_t seqNo : 8;
#endif
};
struct RTCP_FIR {
RTCP_FB_HEADER header;
RTCP_FIR_PART parts[1];
RTCP_FB_HEADER header;
RTCP_FIR_PART parts[1];
void preparePacket(SSRC messageSSRC, uint8_t seqNo) {
header.header.prepareHeader(206, 4, 2 + 2 * 1);
header.setPacketSenderSSRC(messageSSRC);
header.setMediaSourceSSRC(messageSSRC);
parts[0].ssrc = htonl(messageSSRC);
parts[0].seqNo = seqNo;
}
void preparePacket(SSRC messageSSRC, uint8_t seqNo) {
header.header.prepareHeader(206, 4, 2 + 2 * 1);
header.setPacketSenderSSRC(messageSSRC);
header.setMediaSourceSSRC(messageSSRC);
parts[0].ssrc = htonl(messageSSRC);
parts[0].seqNo = seqNo;
}
void print() {
header.log();
}
void print() { header.log(); }
[[nodiscard]] static unsigned int size() {
return sizeof(RTCP_FB_HEADER) + sizeof(RTCP_FIR_PART);
}
[[nodiscard]] static unsigned int size() {
return sizeof(RTCP_FB_HEADER) + sizeof(RTCP_FIR_PART);
}
};
struct RTCP_NACK_PART {
uint16_t pid;
uint16_t blp;
uint16_t pid;
uint16_t blp;
};
class RTCP_NACK {
public:
RTCP_FB_HEADER header;
RTCP_NACK_PART parts[1];
RTCP_FB_HEADER header;
RTCP_NACK_PART parts[1];
public:
void preparePacket(SSRC ssrc, unsigned int discreteSeqNoCount) {
header.header.prepareHeader(205, 1, 2 + discreteSeqNoCount);
header.setMediaSourceSSRC(ssrc);
header.setPacketSenderSSRC(ssrc);
}
void preparePacket(SSRC ssrc, unsigned int discreteSeqNoCount) {
header.header.prepareHeader(205, 1, 2 + discreteSeqNoCount);
header.setMediaSourceSSRC(ssrc);
header.setPacketSenderSSRC(ssrc);
}
/**
* Add a packet to the list of missing packets.
* @param fciCount The number of FCI fields that are present in this packet.
* Let the number start at zero and let this function grow the number.
* @param fciPID The seq no of the active FCI. It will be initialized automatically, and will change automatically.
* @param missingPacket The seq no of the missing packet. This will be added to the queue.
* @return true if the packet has grown, false otherwise.
*/
bool addMissingPacket(unsigned int *fciCount, uint16_t *fciPID, const uint16_t &missingPacket) {
if (*fciCount == 0 || missingPacket < *fciPID || missingPacket > (*fciPID + 16)) {
parts[*fciCount].pid = htons(missingPacket);
parts[*fciCount].blp = 0;
*fciPID = missingPacket;
(*fciCount)++;
return true;
} else {
// TODO SPEEED!
parts[(*fciCount) - 1].blp = htons(
ntohs(parts[(*fciCount) - 1].blp) | (1u << (unsigned int) (missingPacket - *fciPID)));
return false;
}
}
/**
* Add a packet to the list of missing packets.
* @param fciCount The number of FCI fields that are present in this packet.
* Let the number start at zero and let this function grow the number.
* @param fciPID The seq no of the active FCI. It will be initialized automatically, and will
* change automatically.
* @param missingPacket The seq no of the missing packet. This will be added to the queue.
* @return true if the packet has grown, false otherwise.
*/
bool addMissingPacket(unsigned int *fciCount, uint16_t *fciPID, const uint16_t &missingPacket) {
if (*fciCount == 0 || missingPacket < *fciPID || missingPacket > (*fciPID + 16)) {
parts[*fciCount].pid = htons(missingPacket);
parts[*fciCount].blp = 0;
*fciPID = missingPacket;
(*fciCount)++;
return true;
} else {
// TODO SPEEED!
parts[(*fciCount) - 1].blp = htons(ntohs(parts[(*fciCount) - 1].blp) |
(1u << (unsigned int)(missingPacket - *fciPID)));
return false;
}
}
[[nodiscard]] static unsigned int getSize(unsigned int discreteSeqNoCount) {
return offsetof(RTCP_NACK, parts) + sizeof(RTCP_NACK_PART) * discreteSeqNoCount;
}
[[nodiscard]] static unsigned int getSize(unsigned int discreteSeqNoCount) {
return offsetof(RTCP_NACK, parts) + sizeof(RTCP_NACK_PART) * discreteSeqNoCount;
}
[[nodiscard]] unsigned int getSeqNoCount() {
return header.header.length() - 2;
}
[[nodiscard]] unsigned int getSeqNoCount() { return header.header.length() - 2; }
};
class RTP_RTX {
private:
RTP header;
RTP header;
public:
size_t copyTo(RTP *dest, size_t totalSize, uint8_t originalPayloadType) {
memmove((char *)dest, (char *)this, header.getSize());
dest->setSeqNumber(getOriginalSeqNo());
dest->setPayloadType(originalPayloadType);
memmove(dest->getBody(), getBody(), getBodySize(totalSize));
return totalSize;
}
size_t copyTo(RTP *dest, size_t totalSize, uint8_t originalPayloadType) {
memmove((char*)dest, (char*)this, header.getSize());
dest->setSeqNumber(getOriginalSeqNo());
dest->setPayloadType(originalPayloadType);
memmove(dest->getBody(), getBody(), getBodySize(totalSize));
return totalSize;
}
[[nodiscard]] uint16_t getOriginalSeqNo() const {
return ntohs(*(uint16_t *)(header.getBody()));
}
[[nodiscard]] uint16_t getOriginalSeqNo() const {
return ntohs(*(uint16_t *) (header.getBody()));
}
char *getBody() { return header.getBody() + sizeof(uint16_t); }
char *getBody() {
return header.getBody() + sizeof(uint16_t);
}
size_t getBodySize(size_t totalSize) { return totalSize - ((char *)getBody() - (char *)this); }
size_t getBodySize(size_t totalSize) {
return totalSize - ((char *) getBody() - (char *) this);
}
RTP &getHeader() { return header; }
RTP &getHeader() {
return header;
}
size_t normalizePacket(size_t totalSize, SSRC originalSSRC, uint8_t originalPayloadType) {
header.setSeqNumber(getOriginalSeqNo());
header.setSsrc(originalSSRC); // TODO Endianess
header.setPayloadType(originalPayloadType);
// TODO, the -12 is the size of the header (which is variable!)
memmove(header.getBody(), header.getBody() + sizeof(uint16_t), totalSize - 12 - sizeof(uint16_t));
return totalSize - sizeof(uint16_t);
}
size_t normalizePacket(size_t totalSize, SSRC originalSSRC, uint8_t originalPayloadType) {
header.setSeqNumber(getOriginalSeqNo());
header.setSsrc(originalSSRC); // TODO Endianess
header.setPayloadType(originalPayloadType);
// TODO, the -12 is the size of the header (which is variable!)
memmove(header.getBody(), header.getBody() + sizeof(uint16_t),
totalSize - 12 - sizeof(uint16_t));
return totalSize - sizeof(uint16_t);
}
};
#pragma pack(pop)
};
#endif //WEBRTC_SERVER_RTP_HPP
}; // namespace rtc
#endif // WEBRTC_SERVER_RTP_HPP

View File

@ -80,10 +80,8 @@ private:
std::shared_ptr<RtcpHandler> mRtcpHandler;
friend class PeerConnection;
};
} // namespace rtc
#endif

View File

@ -25,8 +25,7 @@ namespace rtc {
using std::to_integer;
string to_base64(const binary &data) {
static const char tab[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const char tab[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
string out;
out.reserve(3 * ((data.size() + 3) / 4));

View File

@ -61,9 +61,8 @@ Candidate::Candidate(string candidate) : Candidate() {
mCandidate = std::move(candidate);
}
Candidate::Candidate(string candidate, string mid)
: Candidate(std::move(candidate)) {
if(!mid.empty())
Candidate::Candidate(string candidate, string mid) : Candidate(std::move(candidate)) {
if (!mid.empty())
mMid.emplace(std::move(mid));
}

View File

@ -304,9 +304,7 @@ int rtcDeletePeerConnection(int pc) {
});
}
int rtcAddDataChannel(int pc, const char *label) {
return rtcAddDataChannelEx(pc, label, nullptr);
}
int rtcAddDataChannel(int pc, const char *label) { return rtcAddDataChannelEx(pc, label, nullptr); }
int rtcAddDataChannelEx(int pc, const char *label, const rtcDataChannelInit *init) {
return WRAP({

View File

@ -153,22 +153,23 @@ Certificate::Certificate(string crt_pem, string key_pem) {
mFingerprint = make_fingerprint(mX509.get());
}
Certificate::Certificate(shared_ptr<X509> x509, shared_ptr<EVP_PKEY> pkey) :
mX509(std::move(x509)), mPKey(std::move(pkey))
{
Certificate::Certificate(shared_ptr<X509> x509, shared_ptr<EVP_PKEY> pkey)
: mX509(std::move(x509)), mPKey(std::move(pkey)) {
mFingerprint = make_fingerprint(mX509.get());
}
string Certificate::fingerprint() const { return mFingerprint; }
std::tuple<X509 *, EVP_PKEY *> Certificate::credentials() const { return {mX509.get(), mPKey.get()}; }
std::tuple<X509 *, EVP_PKEY *> Certificate::credentials() const {
return {mX509.get(), mPKey.get()};
}
string make_fingerprint(X509 *x509) {
const size_t size = 32;
unsigned char buffer[size];
unsigned int len = size;
if (!X509_digest(x509, EVP_sha256(), buffer, &len))
throw std::runtime_error("X509 fingerprint error");
unsigned char buffer[size];
unsigned int len = size;
if (!X509_digest(x509, EVP_sha256(), buffer, &len))
throw std::runtime_error("X509 fingerprint error");
std::ostringstream oss;
oss << std::hex << std::uppercase << std::setfill('0');
@ -186,10 +187,10 @@ certificate_ptr make_certificate_impl(string commonName) {
shared_ptr<X509> x509(X509_new(), X509_free);
shared_ptr<EVP_PKEY> pkey(EVP_PKEY_new(), EVP_PKEY_free);
unique_ptr<RSA, decltype(&RSA_free)> rsa(RSA_new(), RSA_free);
unique_ptr<RSA, decltype(&RSA_free)> rsa(RSA_new(), RSA_free);
unique_ptr<BIGNUM, decltype(&BN_free)> exponent(BN_new(), BN_free);
unique_ptr<BIGNUM, decltype(&BN_free)> serial_number(BN_new(), BN_free);
unique_ptr<X509_NAME, decltype(&X509_NAME_free)> name(X509_NAME_new(), X509_NAME_free);
unique_ptr<X509_NAME, decltype(&X509_NAME_free)> name(X509_NAME_new(), X509_NAME_free);
if (!x509 || !pkey || !rsa || !exponent || !serial_number || !name)
throw std::runtime_error("Unable allocate structures for certificate generation");

View File

@ -26,13 +26,9 @@ size_t Channel::bufferedAmount() const { return mBufferedAmount; }
size_t Channel::availableAmount() const { return 0; }
void Channel::onOpen(std::function<void()> callback) {
mOpenCallback = callback;
}
void Channel::onOpen(std::function<void()> callback) { mOpenCallback = callback; }
void Channel::onClosed(std::function<void()> callback) {
mClosedCallback = callback;
}
void Channel::onClosed(std::function<void()> callback) { mClosedCallback = callback; }
void Channel::onError(std::function<void(string error)> callback) { mErrorCallback = callback; }
@ -57,9 +53,7 @@ void Channel::onBufferedAmountLow(std::function<void()> callback) {
void Channel::setBufferedAmountLowThreshold(size_t amount) { mBufferedAmountLowThreshold = amount; }
void Channel::onAvailable(std::function<void()> callback) {
mAvailableCallback = callback;
}
void Channel::onAvailable(std::function<void()> callback) { mAvailableCallback = callback; }
void Channel::triggerOpen() { mOpenCallback(); }
@ -96,4 +90,3 @@ void Channel::resetCallbacks() {
}
} // namespace rtc

View File

@ -137,8 +137,8 @@ Description::Description(const string &sdp, Type type, Role role)
}
Description::Description(const string &sdp, string typeString)
: Description(sdp, !typeString.empty() ? stringToType(typeString) : Type::Unspec, Role::ActPass) {
}
: Description(sdp, !typeString.empty() ? stringToType(typeString) : Type::Unspec,
Role::ActPass) {}
Description::Type Description::type() const { return mType; }
@ -177,7 +177,7 @@ void Description::addCandidate(Candidate candidate) {
}
void Description::addCandidates(std::vector<Candidate> candidates) {
for(Candidate candidate : candidates) {
for (Candidate candidate : candidates) {
candidate.hintMid(bundleMid());
mCandidates.emplace_back(std::move(candidate));
}
@ -385,7 +385,8 @@ int Description::addAudio(string mid, Direction dir) {
return addMedia(Audio(std::move(mid), dir));
}
std::variant<Description::Media *, Description::Application *> Description::media(unsigned int index) {
std::variant<Description::Media *, Description::Application *>
Description::media(unsigned int index) {
if (index >= mEntries.size())
throw std::out_of_range("Media index out of range");
@ -432,7 +433,6 @@ Description::Entry::Entry(const string &mline, string mid, Direction dir)
ss >> mType;
ss >> port; // ignored
ss >> mDescription;
}
void Description::Entry::setDirection(Direction dir) { mDirection = dir; }
@ -472,9 +472,10 @@ string Description::Entry::generateSdpLines(string_view eol) const {
}
for (const auto &attr : mAttributes) {
if (attr.find("extmap") == std::string::npos && attr.find("rtcp-rsize") == std::string::npos)
sdp << "a=" << attr << eol;
}
if (attr.find("extmap") == std::string::npos &&
attr.find("rtcp-rsize") == std::string::npos)
sdp << "a=" << attr << eol;
}
return sdp.str();
}
@ -500,38 +501,35 @@ void Description::Entry::parseSdpLine(string_view line) {
mAttributes.emplace_back(line.substr(2));
}
}
std::vector< string>::iterator Description::Entry::beginAttributes() {
return mAttributes.begin();
}
std::vector< string>::iterator Description::Entry::endAttributes() {
return mAttributes.end();
}
std::vector< string>::iterator Description::Entry::removeAttribute(std::vector<string>::iterator it) {
return mAttributes.erase(it);
std::vector<string>::iterator Description::Entry::beginAttributes() { return mAttributes.begin(); }
std::vector<string>::iterator Description::Entry::endAttributes() { return mAttributes.end(); }
std::vector<string>::iterator
Description::Entry::removeAttribute(std::vector<string>::iterator it) {
return mAttributes.erase(it);
}
void Description::Media::addSSRC(uint32_t ssrc, std::string name) {
mAttributes.emplace_back("ssrc:" + std::to_string(ssrc) + " cname:" + name);
mSsrcs.emplace_back(ssrc);
mAttributes.emplace_back("ssrc:" + std::to_string(ssrc) + " cname:" + name);
mSsrcs.emplace_back(ssrc);
}
void Description::Media::replaceSSRC(uint32_t oldSSRC, uint32_t ssrc, std::string name) {
auto it = mAttributes.begin();
while (it != mAttributes.end()) {
if (it->find("ssrc:" + std::to_string(oldSSRC)) == 0) {
it = mAttributes.erase(it);
}else
it++;
}
mAttributes.emplace_back("ssrc:" + std::to_string(ssrc) + " cname:" + name);
auto it = mAttributes.begin();
while (it != mAttributes.end()) {
if (it->find("ssrc:" + std::to_string(oldSSRC)) == 0) {
it = mAttributes.erase(it);
} else
it++;
}
mAttributes.emplace_back("ssrc:" + std::to_string(ssrc) + " cname:" + name);
}
void Description::Media::addSSRC(uint32_t ssrc) {
mAttributes.emplace_back("ssrc:" + std::to_string(ssrc));
mAttributes.emplace_back("ssrc:" + std::to_string(ssrc));
}
bool Description::Media::hasSSRC(uint32_t ssrc) {
return std::find(mSsrcs.begin(), mSsrcs.end(), ssrc) != mSsrcs.end();
return std::find(mSsrcs.begin(), mSsrcs.end(), ssrc) != mSsrcs.end();
}
Description::Application::Application(string mid)
@ -682,48 +680,48 @@ void Description::Media::removeFormat(const string &fmt) {
void Description::Video::addVideoCodec(int payloadType, const string &codec) {
RTPMap map(std::to_string(payloadType) + ' ' + codec + "/90000");
map.addFB("nack");
map.addFB("nack pli");
// map.addFB("nack fir");
map.addFB("nack");
map.addFB("nack pli");
// map.addFB("nack fir");
map.addFB("goog-remb");
if (codec == "H264") {
// Use Constrained Baseline profile Level 4.2 (necessary for Firefox)
// https://developer.mozilla.org/en-US/docs/Web/Media/Formats/WebRTC_codecs#Supported_video_codecs
// TODO: Should be 42E0 but 42C0 appears to be more compatible. Investigate this.
map.fmtps.emplace_back("profile-level-id=4de01f;packetization-mode=1;level-asymmetry-allowed=1");
map.fmtps.emplace_back(
"profile-level-id=4de01f;packetization-mode=1;level-asymmetry-allowed=1");
// Because certain Android devices don't like me, let us just negotiate some random
{
RTPMap map(std::to_string(payloadType+1) + ' ' + codec + "/90000");
RTPMap map(std::to_string(payloadType + 1) + ' ' + codec + "/90000");
map.addFB("nack");
map.addFB("nack pli");
// map.addFB("nack fir");
map.addFB("nack pli");
// map.addFB("nack fir");
map.addFB("goog-remb");
addRTPMap(map);
}
}
}
addRTPMap(map);
// // RTX Packets
/* TODO
* TIL that Firefox does not properly support the negotiation of RTX! It works, but doesn't negotiate the SSRC so
* we have no idea what SSRC is RTX going to be. Three solutions:
* One) we don't negotitate it and (maybe) break RTX support with Edge.
* Two) we do negotiate it and rebuild the original packet before we send it distribute it to each track.
* Three) we complain to mozilla. This one probably won't do much.
*/
// RTPMap rtx(std::to_string(payloadType+1) + " rtx/90000");
// // TODO rtx-time is how long can a request be stashed for before needing to resend it. Needs to be parameterized
// rtx.addAttribute("apt=" + std::to_string(payloadType) + ";rtx-time=3000");
// addRTPMap(rtx);
// // RTX Packets
/* TODO
* TIL that Firefox does not properly support the negotiation of RTX! It works, but doesn't
* negotiate the SSRC so we have no idea what SSRC is RTX going to be. Three solutions: One) we
* don't negotitate it and (maybe) break RTX support with Edge. Two) we do negotiate it and
* rebuild the original packet before we send it distribute it to each track. Three) we complain
* to mozilla. This one probably won't do much.
*/
// RTPMap rtx(std::to_string(payloadType+1) + " rtx/90000");
// // TODO rtx-time is how long can a request be stashed for before needing to resend it.
// Needs to be parameterized rtx.addAttribute("apt=" + std::to_string(payloadType) +
// ";rtx-time=3000"); addRTPMap(rtx);
}
void Description::Audio::addAudioCodec(int payloadType, const string &codec) {
// TODO This 48000/2 should be parameterized
RTPMap map(std::to_string(payloadType) + ' ' + codec + "/48000/2");
map.fmtps.emplace_back("maxaveragebitrate=96000; stereo=1; sprop-stereo=1; useinbandfec=1");
addRTPMap(map);
// TODO This 48000/2 should be parameterized
RTPMap map(std::to_string(payloadType) + ' ' + codec + "/48000/2");
map.fmtps.emplace_back("maxaveragebitrate=96000; stereo=1; sprop-stereo=1; useinbandfec=1");
addRTPMap(map);
}
void Description::Video::addH264Codec(int pt) { addVideoCodec(pt, "H264"); }
@ -758,9 +756,9 @@ string Description::Media::generateSdpLines(string_view eol) const {
sdp << eol;
for (const auto &val : map.rtcpFbs) {
if (val != "transport-cc" )
sdp << "a=rtcp-fb:" << map.pt << ' ' << val << eol;
}
if (val != "transport-cc")
sdp << "a=rtcp-fb:" << map.pt << ' ' << val << eol;
}
for (const auto &val : map.fmtps)
sdp << "a=fmtp:" << map.pt << ' ' << val << eol;
}
@ -774,32 +772,32 @@ void Description::Media::parseSdpLine(string_view line) {
auto [key, value] = parse_pair(attr);
if (key == "rtpmap") {
auto pt = Description::Media::RTPMap::parsePT(value);
auto it = mRtpMap.find(pt);
if (it == mRtpMap.end()) {
it = mRtpMap.insert(std::make_pair(pt, Description::Media::RTPMap(value))).first;
}else {
it->second.setMLine(value);
}
auto pt = Description::Media::RTPMap::parsePT(value);
auto it = mRtpMap.find(pt);
if (it == mRtpMap.end()) {
it = mRtpMap.insert(std::make_pair(pt, Description::Media::RTPMap(value))).first;
} else {
it->second.setMLine(value);
}
} else if (key == "rtcp-fb") {
size_t p = value.find(' ');
int pt = to_integer<int>(value.substr(0, p));
auto it = mRtpMap.find(pt);
if (it == mRtpMap.end()) {
it = mRtpMap.insert(std::make_pair(pt, Description::Media::RTPMap())).first;
}
it->second.rtcpFbs.emplace_back(value.substr(p + 1));
it = mRtpMap.insert(std::make_pair(pt, Description::Media::RTPMap())).first;
}
it->second.rtcpFbs.emplace_back(value.substr(p + 1));
} else if (key == "fmtp") {
size_t p = value.find(' ');
int pt = to_integer<int>(value.substr(0, p));
auto it = mRtpMap.find(pt);
if (it == mRtpMap.end())
it = mRtpMap.insert(std::make_pair(pt, Description::Media::RTPMap())).first;
it->second.fmtps.emplace_back(value.substr(p + 1));
it = mRtpMap.insert(std::make_pair(pt, Description::Media::RTPMap())).first;
it->second.fmtps.emplace_back(value.substr(p + 1));
} else if (key == "rtcp-mux") {
// always added
}else if (key == "ssrc") {
mSsrcs.emplace_back(std::stoul((std::string)value));
// always added
} else if (key == "ssrc") {
mSsrcs.emplace_back(std::stoul((std::string)value));
} else {
Entry::parseSdpLine(line);
}
@ -810,37 +808,35 @@ void Description::Media::parseSdpLine(string_view line) {
}
}
void Description::Media::addRTPMap(const Description::Media::RTPMap& map) {
mRtpMap.emplace(map.pt, map);
void Description::Media::addRTPMap(const Description::Media::RTPMap &map) {
mRtpMap.emplace(map.pt, map);
}
std::vector<uint32_t> Description::Media::getSSRCs() {
std::vector<uint32_t> vec;
for (auto &val : mAttributes) {
PLOG_DEBUG << val;
if (val.find("ssrc:") == 0) {
vec.emplace_back(std::stoul((std::string)val.substr(5, val.find(" "))));
}
}
return vec;
std::vector<uint32_t> vec;
for (auto &val : mAttributes) {
PLOG_DEBUG << val;
if (val.find("ssrc:") == 0) {
vec.emplace_back(std::stoul((std::string)val.substr(5, val.find(" "))));
}
}
return vec;
}
std::map<int, Description::Media::RTPMap>::iterator Description::Media::beginMaps() {
return mRtpMap.begin();
return mRtpMap.begin();
}
std::map<int, Description::Media::RTPMap>::iterator Description::Media::endMaps() {
return mRtpMap.end();
return mRtpMap.end();
}
std::map<int, Description::Media::RTPMap>::iterator
Description::Media::removeMap(std::map<int, Description::Media::RTPMap>::iterator iterator) {
return mRtpMap.erase(iterator);
return mRtpMap.erase(iterator);
}
Description::Media::RTPMap::RTPMap(string_view mline) {
setMLine(mline);
}
Description::Media::RTPMap::RTPMap(string_view mline) { setMLine(mline); }
void Description::Media::RTPMap::removeFB(const string &str) {
auto it = rtcpFbs.begin();
@ -855,39 +851,37 @@ void Description::Media::RTPMap::removeFB(const string &str) {
void Description::Media::RTPMap::addFB(const string &str) { rtcpFbs.emplace_back(str); }
int Description::Media::RTPMap::parsePT(string_view view) {
size_t p = view.find(' ');
size_t p = view.find(' ');
return to_integer<int>(view.substr(0, p));
return to_integer<int>(view.substr(0, p));
}
void Description::Media::RTPMap::setMLine(string_view mline) {
size_t p = mline.find(' ');
size_t p = mline.find(' ');
this->pt = to_integer<int>(mline.substr(0, p));
this->pt = to_integer<int>(mline.substr(0, p));
string_view line = mline.substr(p + 1);
size_t spl = line.find('/');
this->format = line.substr(0, spl);
string_view line = mline.substr(p + 1);
size_t spl = line.find('/');
this->format = line.substr(0, spl);
line = line.substr(spl + 1);
spl = line.find('/');
if (spl == string::npos) {
spl = line.find(' ');
}
if (spl == string::npos)
this->clockRate = to_integer<int>(line);
else {
this->clockRate = to_integer<int>(line.substr(0, spl));
this->encParams = line.substr(spl+1);
}
line = line.substr(spl + 1);
spl = line.find('/');
if (spl == string::npos) {
spl = line.find(' ');
}
if (spl == string::npos)
this->clockRate = to_integer<int>(line);
else {
this->clockRate = to_integer<int>(line.substr(0, spl));
this->encParams = line.substr(spl + 1);
}
}
Description::Audio::Audio(string mid, Direction dir)
: Media("audio 9 UDP/TLS/RTP/SAVPF", std::move(mid), dir) {}
void Description::Audio::addOpusCodec(int payloadType) {
addAudioCodec(payloadType, "OPUS");
}
void Description::Audio::addOpusCodec(int payloadType) { addAudioCodec(payloadType, "OPUS"); }
Description::Video::Video(string mid, Direction dir)
: Media("video 9 UDP/TLS/RTP/SAVPF", std::move(mid), dir) {}

View File

@ -110,31 +110,30 @@ bool DtlsSrtpTransport::sendMedia(message_ptr message) {
if (err == srtp_err_status_replay_fail)
throw std::runtime_error("SRTCP packet is a replay");
else if (err == srtp_err_status_no_ctx) {
auto ssrc = ((RTCP_SR*) message->data())->senderSSRC();
PLOG_INFO << "Adding SSRC to SRTCP: " << ssrc;
addSSRC(ssrc);
if ((err = srtp_protect_rtcp(mSrtpOut, message->data(), &size)))
throw std::runtime_error("SRTCP protect error, status=" +
to_string(static_cast<int>(err)));
}else {
throw std::runtime_error("SRTCP protect error, status=" +
to_string(static_cast<int>(err)));
}
auto ssrc = ((RTCP_SR *)message->data())->senderSSRC();
PLOG_INFO << "Adding SSRC to SRTCP: " << ssrc;
addSSRC(ssrc);
if ((err = srtp_protect_rtcp(mSrtpOut, message->data(), &size)))
throw std::runtime_error("SRTCP protect error, status=" +
to_string(static_cast<int>(err)));
} else {
throw std::runtime_error("SRTCP protect error, status=" +
to_string(static_cast<int>(err)));
}
}
PLOG_VERBOSE << "Protected SRTCP packet, size=" << size;
} else {
if (srtp_err_status_t err = srtp_protect(mSrtpOut, message->data(), &size)) {
if (err == srtp_err_status_replay_fail)
throw std::runtime_error("Outgoing SRTP packet is a replay");
else if (err == srtp_err_status_no_ctx) {
auto ssrc = ((RTP*) message->data())->ssrc();
PLOG_INFO << "Adding SSRC to RTP: " << ssrc;
addSSRC(ssrc);
if ((err = srtp_protect_rtcp(mSrtpOut, message->data(), &size)))
throw std::runtime_error("SRTCP protect error, status=" +
to_string(static_cast<int>(err)));
}
else
else if (err == srtp_err_status_no_ctx) {
auto ssrc = ((RTP *)message->data())->ssrc();
PLOG_INFO << "Adding SSRC to RTP: " << ssrc;
addSSRC(ssrc);
if ((err = srtp_protect_rtcp(mSrtpOut, message->data(), &size)))
throw std::runtime_error("SRTCP protect error, status=" +
to_string(static_cast<int>(err)));
} else
throw std::runtime_error("SRTP protect error, status=" +
to_string(static_cast<int>(err)));
}
@ -189,23 +188,22 @@ void DtlsSrtpTransport::incoming(message_ptr message) {
PLOG_WARNING << "Incoming SRTCP packet is a replay";
else if (err == srtp_err_status_auth_fail)
PLOG_WARNING << "Incoming SRTCP packet failed authentication check";
else if (err == srtp_err_status_no_ctx) {
auto ssrc = ((RTCP_SR*) message->data())->senderSSRC();
PLOG_INFO << "Adding SSRC to RTCP: " << ssrc;
addSSRC(ssrc);
if ((err = srtp_unprotect_rtcp(mSrtpIn, message->data(), &size)))
throw std::runtime_error("SRTCP unprotect error, status=" +
to_string(static_cast<int>(err)));
}
else {
PLOG_WARNING << "SRTCP unprotect error, status=" << err << " SSRC="
<< ((RTCP_SR *) message->data())->senderSSRC();
}
return;
else if (err == srtp_err_status_no_ctx) {
auto ssrc = ((RTCP_SR *)message->data())->senderSSRC();
PLOG_INFO << "Adding SSRC to RTCP: " << ssrc;
addSSRC(ssrc);
if ((err = srtp_unprotect_rtcp(mSrtpIn, message->data(), &size)))
throw std::runtime_error("SRTCP unprotect error, status=" +
to_string(static_cast<int>(err)));
} else {
PLOG_WARNING << "SRTCP unprotect error, status=" << err
<< " SSRC=" << ((RTCP_SR *)message->data())->senderSSRC();
}
return;
}
PLOG_VERBOSE << "Unprotected SRTCP packet, size=" << size;
message->type = Message::Type::Control;
auto rtp = (RTCP_SR*) message->data();
auto rtp = (RTCP_SR *)message->data();
message->stream = rtp->senderSSRC();
} else {
PLOG_VERBOSE << "Incoming SRTP packet, size=" << size;
@ -214,21 +212,21 @@ void DtlsSrtpTransport::incoming(message_ptr message) {
PLOG_WARNING << "Incoming SRTP packet is a replay";
else if (err == srtp_err_status_auth_fail)
PLOG_WARNING << "Incoming SRTP packet failed authentication check";
else if (err == srtp_err_status_no_ctx) {
auto ssrc = ((RTP*) message->data())->ssrc();
PLOG_INFO << "Adding SSRC to RTP: " << ssrc;
addSSRC(ssrc);
if ((err = srtp_unprotect(mSrtpIn, message->data(), &size)))
throw std::runtime_error("SRTCP unprotect error, status=" +
to_string(static_cast<int>(err)));
}
else
PLOG_WARNING << "SRTP unprotect error, status=" << err << " SSRC=" << ((RTP*)message->data())->ssrc();
else if (err == srtp_err_status_no_ctx) {
auto ssrc = ((RTP *)message->data())->ssrc();
PLOG_INFO << "Adding SSRC to RTP: " << ssrc;
addSSRC(ssrc);
if ((err = srtp_unprotect(mSrtpIn, message->data(), &size)))
throw std::runtime_error("SRTCP unprotect error, status=" +
to_string(static_cast<int>(err)));
} else
PLOG_WARNING << "SRTP unprotect error, status=" << err
<< " SSRC=" << ((RTP *)message->data())->ssrc();
return;
}
PLOG_VERBOSE << "Unprotected SRTP packet, size=" << size;
message->type = Message::Type::Binary;
auto rtp = (RTP*) message->data();
auto rtp = (RTP *)message->data();
message->stream = rtp->ssrc();
}
@ -301,18 +299,18 @@ void DtlsSrtpTransport::postHandshake() {
std::memcpy(mServerSessionKey + SRTP_AES_128_KEY_LEN, serverSalt, SRTP_SALT_LEN);
// Add SSRC=1 as an inbound because that is what Chrome does.
srtp_policy_t inbound = {};
srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&inbound.rtp);
srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&inbound.rtcp);
inbound.ssrc.type = ssrc_specific;
inbound.ssrc.value = 1;
inbound.key = mIsClient ? mServerSessionKey : mClientSessionKey;
inbound.next = nullptr;
srtp_policy_t inbound = {};
srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&inbound.rtp);
srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&inbound.rtcp);
inbound.ssrc.type = ssrc_specific;
inbound.ssrc.value = 1;
inbound.key = mIsClient ? mServerSessionKey : mClientSessionKey;
inbound.next = nullptr;
if (srtp_err_status_t err = srtp_add_stream(mSrtpIn, &inbound)) {
throw std::runtime_error("SRTP add inbound stream failed, status=" +
to_string(static_cast<int>(err)));
}
if (srtp_err_status_t err = srtp_add_stream(mSrtpIn, &inbound)) {
throw std::runtime_error("SRTP add inbound stream failed, status=" +
to_string(static_cast<int>(err)));
}
mInitDone = true;
}
@ -321,34 +319,33 @@ void DtlsSrtpTransport::addSSRC(uint32_t ssrc) {
if (!mInitDone)
throw std::logic_error("Attempted to add SSRC before SRTP keying material is derived");
srtp_policy_t inbound = {};
srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&inbound.rtp);
srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&inbound.rtcp);
inbound.ssrc.type = ssrc_specific;
inbound.ssrc.value = ssrc;
inbound.key = mIsClient ? mServerSessionKey : mClientSessionKey;
inbound.next = nullptr;
inbound.allow_repeat_tx = true;
srtp_policy_t inbound = {};
srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&inbound.rtp);
srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&inbound.rtcp);
inbound.ssrc.type = ssrc_specific;
inbound.ssrc.value = ssrc;
inbound.key = mIsClient ? mServerSessionKey : mClientSessionKey;
inbound.next = nullptr;
inbound.allow_repeat_tx = true;
if (srtp_err_status_t err = srtp_add_stream(mSrtpIn, &inbound))
throw std::runtime_error("SRTP add inbound stream failed, status=" +
to_string(static_cast<int>(err)));
if (srtp_err_status_t err = srtp_add_stream(mSrtpIn, &inbound))
throw std::runtime_error("SRTP add inbound stream failed, status=" +
to_string(static_cast<int>(err)));
srtp_policy_t outbound = {};
srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&outbound.rtp);
srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&outbound.rtcp);
outbound.ssrc.type = ssrc_specific;
outbound.ssrc.value = ssrc;
outbound.key = mIsClient ? mClientSessionKey : mServerSessionKey;
outbound.next = nullptr;
outbound.allow_repeat_tx = true;
srtp_policy_t outbound = {};
srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&outbound.rtp);
srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&outbound.rtcp);
outbound.ssrc.type = ssrc_specific;
outbound.ssrc.value = ssrc;
outbound.key = mIsClient ? mClientSessionKey : mServerSessionKey;
outbound.next = nullptr;
outbound.allow_repeat_tx = true;
if (srtp_err_status_t err = srtp_add_stream(mSrtpOut, &outbound))
throw std::runtime_error("SRTP add outbound stream failed, status=" +
to_string(static_cast<int>(err)));
if (srtp_err_status_t err = srtp_add_stream(mSrtpOut, &outbound))
throw std::runtime_error("SRTP add outbound stream failed, status=" +
to_string(static_cast<int>(err)));
}
} // namespace rtc
#endif

View File

@ -177,7 +177,7 @@ void DtlsTransport::runRecvLoop() {
// Receive loop
try {
PLOG_INFO << "DTLS handshake finished";
postHandshake();
postHandshake();
changeState(State::Connected);
const size_t bufferSize = maxMtu;
@ -575,4 +575,3 @@ long DtlsTransport::BioMethodCtrl(BIO * /*bio*/, int cmd, long /*num*/, void * /
#endif
} // namespace rtc

View File

@ -92,4 +92,3 @@ protected:
} // namespace rtc
#endif

View File

@ -130,9 +130,7 @@ IceTransport::~IceTransport() {
mAgent.reset();
}
bool IceTransport::stop() {
return Transport::stop();
}
bool IceTransport::stop() { return Transport::stop(); }
Description::Role IceTransport::role() const { return mRole; }
@ -141,11 +139,13 @@ Description IceTransport::getLocalDescription(Description::Type type) const {
if (juice_get_local_description(mAgent.get(), sdp, JUICE_MAX_SDP_STRING_LEN) < 0)
throw std::runtime_error("Failed to generate local SDP");
return Description(string(sdp), type, type == Description::Type::Offer ? Description::Role::ActPass : mRole);
return Description(string(sdp), type,
type == Description::Type::Offer ? Description::Role::ActPass : mRole);
}
void IceTransport::setRemoteDescription(const Description &description) {
mRole = description.role() == Description::Role::Active ? Description::Role::Passive : Description::Role::Active;
mRole = description.role() == Description::Role::Active ? Description::Role::Passive
: Description::Role::Active;
mMid = description.bundleMid();
if (juice_set_remote_description(mAgent.get(),
@ -191,7 +191,7 @@ bool IceTransport::getSelectedCandidatePair(Candidate *local, Candidate *remote)
char sdpLocal[JUICE_MAX_CANDIDATE_SDP_STRING_LEN];
char sdpRemote[JUICE_MAX_CANDIDATE_SDP_STRING_LEN];
if (juice_get_selected_candidates(mAgent.get(), sdpLocal, JUICE_MAX_CANDIDATE_SDP_STRING_LEN,
sdpRemote, JUICE_MAX_CANDIDATE_SDP_STRING_LEN) == 0) {
sdpRemote, JUICE_MAX_CANDIDATE_SDP_STRING_LEN) == 0) {
if (local) {
*local = Candidate(sdpLocal, mMid);
local->resolve(Candidate::ResolveMode::Simple);
@ -736,15 +736,17 @@ void IceTransport::LogCallback(const gchar * /*logDomain*/, GLogLevelFlags logLe
bool IceTransport::getSelectedCandidatePair(Candidate *local, Candidate *remote) {
NiceCandidate *niceLocal, *niceRemote;
if(!nice_agent_get_selected_pair(mNiceAgent.get(), mStreamId, 1, &niceLocal, &niceRemote))
if (!nice_agent_get_selected_pair(mNiceAgent.get(), mStreamId, 1, &niceLocal, &niceRemote))
return false;
gchar *sdpLocal = nice_agent_generate_local_candidate_sdp(mNiceAgent.get(), niceLocal);
if(local) *local = Candidate(sdpLocal, mMid);
if (local)
*local = Candidate(sdpLocal, mMid);
g_free(sdpLocal);
gchar *sdpRemote = nice_agent_generate_local_candidate_sdp(mNiceAgent.get(), niceRemote);
if(remote) *remote = Candidate(sdpRemote, mMid);
if (remote)
*remote = Candidate(sdpRemote, mMid);
g_free(sdpRemote);
if (local)

View File

@ -20,8 +20,8 @@
#define RTC_ICE_TRANSPORT_H
#include "candidate.hpp"
#include "description.hpp"
#include "configuration.hpp"
#include "description.hpp"
#include "include.hpp"
#include "peerconnection.hpp"
#include "transport.hpp"

View File

@ -142,4 +142,3 @@ Init::~Init() {
}
} // namespace rtc

View File

@ -44,5 +44,4 @@ void InitLogger(plog::Severity severity, plog::IAppender *appender) {
logger->addAppender(appender);
}
}
}
} // namespace rtc

View File

@ -119,7 +119,6 @@ bool PeerConnection::hasMedia() const {
void PeerConnection::setLocalDescription(Description::Type type) {
PLOG_VERBOSE << "Setting local description, type=" << Description::typeToString(type);
SignalingState signalingState = mSignalingState.load();
if (type == Description::Type::Rollback) {
if (signalingState == SignalingState::HaveLocalOffer ||
@ -679,205 +678,201 @@ void PeerConnection::forwardMedia(message_ptr message) {
if (!message)
return;
// Browsers like to compound their packets with a random SSRC.
// we have to do this monstrosity to distribute the report blocks
std::optional<unsigned int> mediaLine;
if (message->type == Message::Control) {
size_t offset = 0;
std::vector<SSRC> ssrcsFound;
bool hasFound = false;
std::optional<unsigned int> mediaLine;
if (message->type == Message::Control) {
size_t offset = 0;
std::vector<SSRC> ssrcsFound;
bool hasFound = false;
while ((sizeof(rtc::RTCP_HEADER) + offset) <= message->size()) {
auto header = (rtc::RTCP_HEADER *) (message->data() + offset);
if (header->lengthInBytes() > message->size() - offset) {
PLOG_WARNING << "Packet was truncated";
break;
}
offset += header->lengthInBytes();
if (header->payloadType() == 205 || header->payloadType() == 206) {
auto rtcpfb = (RTCP_FB_HEADER *) header;
auto ssrc = rtcpfb->getPacketSenderSSRC();
if (std::find(ssrcsFound.begin(), ssrcsFound.end(), ssrc) == ssrcsFound.end()) {
mediaLine = getMLineFromSSRC(ssrc);
if (mediaLine.has_value()) {
hasFound = true;
std::shared_lock lock(mTracksMutex); // read-only
if (auto track = mTrackLines[*mediaLine].lock()) {
track->incoming(message);
}
ssrcsFound.emplace_back(ssrc);
}
}
while ((sizeof(rtc::RTCP_HEADER) + offset) <= message->size()) {
auto header = (rtc::RTCP_HEADER *)(message->data() + offset);
if (header->lengthInBytes() > message->size() - offset) {
PLOG_WARNING << "Packet was truncated";
break;
}
offset += header->lengthInBytes();
if (header->payloadType() == 205 || header->payloadType() == 206) {
auto rtcpfb = (RTCP_FB_HEADER *)header;
auto ssrc = rtcpfb->getPacketSenderSSRC();
if (std::find(ssrcsFound.begin(), ssrcsFound.end(), ssrc) == ssrcsFound.end()) {
mediaLine = getMLineFromSSRC(ssrc);
if (mediaLine.has_value()) {
hasFound = true;
std::shared_lock lock(mTracksMutex); // read-only
if (auto track = mTrackLines[*mediaLine].lock()) {
track->incoming(message);
}
ssrcsFound.emplace_back(ssrc);
}
}
ssrc = rtcpfb->getMediaSourceSSRC();
if (std::find(ssrcsFound.begin(), ssrcsFound.end(), ssrc) == ssrcsFound.end()) {
mediaLine = getMLineFromSSRC(ssrc);
if (mediaLine.has_value()) {
hasFound = true;
std::shared_lock lock(mTracksMutex); // read-only
if (auto track = mTrackLines[*mediaLine].lock()) {
track->incoming(message);
}
ssrcsFound.emplace_back(ssrc);
}
}
}else if (header->payloadType() == 200 || header->payloadType() == 201) {
auto rtcpsr = (RTCP_SR *) header;
auto ssrc = rtcpsr->senderSSRC();
if (std::find(ssrcsFound.begin(), ssrcsFound.end(), ssrc) == ssrcsFound.end()) {
mediaLine = getMLineFromSSRC(ssrc);
if (mediaLine.has_value()) {
hasFound = true;
std::shared_lock lock(mTracksMutex); // read-only
if (auto track = mTrackLines[*mediaLine].lock()) {
track->incoming(message);
}
ssrcsFound.emplace_back(ssrc);
}
}
for (int i = 0; i < rtcpsr->header.reportCount(); i++) {
auto block = rtcpsr->getReportBlock(i);
ssrc = block->getSSRC();
if (std::find(ssrcsFound.begin(), ssrcsFound.end(), ssrc) == ssrcsFound.end()) {
mediaLine = getMLineFromSSRC(ssrc);
if (mediaLine.has_value()) {
hasFound = true;
std::shared_lock lock(mTracksMutex); // read-only
if (auto track = mTrackLines[*mediaLine].lock()) {
track->incoming(message);
}
ssrcsFound.emplace_back(ssrc);
}
}
}
} else {
//PT=202 == SDES
//PT=207 == Extended Report
if (header->payloadType() != 202 && header->payloadType() != 207) {
PLOG_WARNING << "Unknown packet type: " << (int) header->version() << " " << header->payloadType() << "";
}
}
}
ssrc = rtcpfb->getMediaSourceSSRC();
if (std::find(ssrcsFound.begin(), ssrcsFound.end(), ssrc) == ssrcsFound.end()) {
mediaLine = getMLineFromSSRC(ssrc);
if (mediaLine.has_value()) {
hasFound = true;
std::shared_lock lock(mTracksMutex); // read-only
if (auto track = mTrackLines[*mediaLine].lock()) {
track->incoming(message);
}
ssrcsFound.emplace_back(ssrc);
}
}
} else if (header->payloadType() == 200 || header->payloadType() == 201) {
auto rtcpsr = (RTCP_SR *)header;
auto ssrc = rtcpsr->senderSSRC();
if (std::find(ssrcsFound.begin(), ssrcsFound.end(), ssrc) == ssrcsFound.end()) {
mediaLine = getMLineFromSSRC(ssrc);
if (mediaLine.has_value()) {
hasFound = true;
std::shared_lock lock(mTracksMutex); // read-only
if (auto track = mTrackLines[*mediaLine].lock()) {
track->incoming(message);
}
ssrcsFound.emplace_back(ssrc);
}
}
for (int i = 0; i < rtcpsr->header.reportCount(); i++) {
auto block = rtcpsr->getReportBlock(i);
ssrc = block->getSSRC();
if (std::find(ssrcsFound.begin(), ssrcsFound.end(), ssrc) == ssrcsFound.end()) {
mediaLine = getMLineFromSSRC(ssrc);
if (mediaLine.has_value()) {
hasFound = true;
std::shared_lock lock(mTracksMutex); // read-only
if (auto track = mTrackLines[*mediaLine].lock()) {
track->incoming(message);
}
ssrcsFound.emplace_back(ssrc);
}
}
}
} else {
// PT=202 == SDES
// PT=207 == Extended Report
if (header->payloadType() != 202 && header->payloadType() != 207) {
PLOG_WARNING << "Unknown packet type: " << (int)header->version() << " "
<< header->payloadType() << "";
}
}
}
if (hasFound)
return;
}
if (hasFound)
return;
}
unsigned int ssrc = message->stream;
mediaLine = getMLineFromSSRC(ssrc);
unsigned int ssrc = message->stream;
mediaLine = getMLineFromSSRC(ssrc);
if (!mediaLine) {
/* TODO
* So the problem is that when stop sending streams, we stop getting report blocks for those streams
* Therefore when we get compound RTCP packets, they are empty, and we can't forward them.
* Therefore, it is expected that we don't know where to forward packets.
* Is this ideal? No! Do I know how to fix it? No!
*/
// PLOG_WARNING << "Track not found for SSRC " << ssrc << ", dropping";
/* TODO
* So the problem is that when stop sending streams, we stop getting report blocks for
* those streams Therefore when we get compound RTCP packets, they are empty, and we can't
* forward them. Therefore, it is expected that we don't know where to forward packets. Is
* this ideal? No! Do I know how to fix it? No!
*/
// PLOG_WARNING << "Track not found for SSRC " << ssrc << ", dropping";
return;
}
std::shared_lock lock(mTracksMutex); // read-only
if (auto track = mTrackLines[*mediaLine].lock()) {
track->incoming(message);
}
if (auto track = mTrackLines[*mediaLine].lock()) {
track->incoming(message);
}
}
std::optional<unsigned int> PeerConnection::getMLineFromSSRC(SSRC ssrc) {
if (auto it = mMLineFromSssrc.find(ssrc); it != mMLineFromSssrc.end()) {
return it->second;
}else {
{
std::lock_guard lock(mRemoteDescriptionMutex);
if (!mRemoteDescription)
return nullopt;
for (unsigned int i = 0; i < mRemoteDescription->mediaCount(); ++i) {
if (std::visit(
rtc::overloaded{[&](Description::Application *) -> bool {
return false;
},
[&](Description::Media *media) -> bool {
return media->hasSSRC(ssrc);
}},
mRemoteDescription->media(i))) {
if (auto it = mMLineFromSssrc.find(ssrc); it != mMLineFromSssrc.end()) {
return it->second;
} else {
{
std::lock_guard lock(mRemoteDescriptionMutex);
if (!mRemoteDescription)
return nullopt;
for (unsigned int i = 0; i < mRemoteDescription->mediaCount(); ++i) {
if (std::visit(
rtc::overloaded{[&](Description::Application *) -> bool { return false; },
[&](Description::Media *media) -> bool {
return media->hasSSRC(ssrc);
}},
mRemoteDescription->media(i))) {
mMLineFromSssrc.emplace(ssrc, i);
return i;
}
}
}
{
std::lock_guard lock(mLocalDescriptionMutex);
if (!mLocalDescription)
return nullopt;
for (unsigned int i = 0; i < mLocalDescription->mediaCount(); ++i) {
if (std::visit(
rtc::overloaded{[&](Description::Application *) -> bool {
return false;
},
[&](Description::Media *media) -> bool {
return media->hasSSRC(ssrc);
}},
mLocalDescription->media(i))) {
mMLineFromSssrc.emplace(ssrc, i);
return i;
}
}
}
{
std::lock_guard lock(mLocalDescriptionMutex);
if (!mLocalDescription)
return nullopt;
for (unsigned int i = 0; i < mLocalDescription->mediaCount(); ++i) {
if (std::visit(
rtc::overloaded{[&](Description::Application *) -> bool { return false; },
[&](Description::Media *media) -> bool {
return media->hasSSRC(ssrc);
}},
mLocalDescription->media(i))) {
mMLineFromSssrc.emplace(ssrc, i);
return i;
}
}
}
}
return std::nullopt;
mMLineFromSssrc.emplace(ssrc, i);
return i;
}
}
}
}
return std::nullopt;
}
std::optional<std::string> PeerConnection::getMidFromSSRC(SSRC ssrc) {
if (auto it = mMidFromSssrc.find(ssrc); it != mMidFromSssrc.end()) {
return it->second;
} else {
{
std::lock_guard lock(mRemoteDescriptionMutex);
if (!mRemoteDescription)
return nullopt;
for (unsigned int i = 0; i < mRemoteDescription->mediaCount(); ++i) {
if (auto found = std::visit(
rtc::overloaded{[&](Description::Application *) -> std::optional<string> {
return std::nullopt;
},
[&](Description::Media *media) -> std::optional<string> {
return media->hasSSRC(ssrc)
? std::make_optional(media->mid())
: nullopt;
}},
mRemoteDescription->media(i))) {
if (auto it = mMidFromSssrc.find(ssrc); it != mMidFromSssrc.end()) {
return it->second;
} else {
{
std::lock_guard lock(mRemoteDescriptionMutex);
if (!mRemoteDescription)
return nullopt;
for (unsigned int i = 0; i < mRemoteDescription->mediaCount(); ++i) {
if (auto found = std::visit(
rtc::overloaded{[&](Description::Application *) -> std::optional<string> {
return std::nullopt;
},
[&](Description::Media *media) -> std::optional<string> {
return media->hasSSRC(ssrc)
? std::make_optional(media->mid())
: nullopt;
}},
mRemoteDescription->media(i))) {
mMidFromSssrc.emplace(ssrc, *found);
return *found;
}
}
}
{
std::lock_guard lock(mLocalDescriptionMutex);
if (!mLocalDescription)
return nullopt;
for (unsigned int i = 0; i < mLocalDescription->mediaCount(); ++i) {
if (auto found = std::visit(
rtc::overloaded{[&](Description::Application *) -> std::optional<string> {
return std::nullopt;
},
[&](Description::Media *media) -> std::optional<string> {
return media->hasSSRC(ssrc)
? std::make_optional(media->mid())
: nullopt;
}},
mLocalDescription->media(i))) {
mMidFromSssrc.emplace(ssrc, *found);
return *found;
}
}
}
{
std::lock_guard lock(mLocalDescriptionMutex);
if (!mLocalDescription)
return nullopt;
for (unsigned int i = 0; i < mLocalDescription->mediaCount(); ++i) {
if (auto found = std::visit(
rtc::overloaded{[&](Description::Application *) -> std::optional<string> {
return std::nullopt;
},
[&](Description::Media *media) -> std::optional<string> {
return media->hasSSRC(ssrc)
? std::make_optional(media->mid())
: nullopt;
}},
mLocalDescription->media(i))) {
mMidFromSssrc.emplace(ssrc, *found);
return *found;
}
}
}
mMidFromSssrc.emplace(ssrc, *found);
return *found;
}
}
}
}
return nullopt;
return nullopt;
}
void PeerConnection::forwardBufferedAmount(uint16_t stream, size_t amount) {
@ -979,7 +974,7 @@ void PeerConnection::incomingTrack(Description::Media description) {
if (mTracks.find(description.mid()) == mTracks.end()) {
auto track = std::make_shared<Track>(std::move(description));
mTracks.emplace(std::make_pair(track->mid(), track));
mTrackLines.emplace_back(track);
mTrackLines.emplace_back(track);
triggerTrack(track);
}
}
@ -1092,21 +1087,21 @@ void PeerConnection::processLocalDescription(Description description) {
auto reciprocated = remoteMedia->reciprocate();
#if !RTC_ENABLE_MEDIA
// No media support, mark as inactive
reciprocated.setDirection(Description::Direction::Inactive);
// No media support, mark as inactive
reciprocated.setDirection(Description::Direction::Inactive);
#endif
incomingTrack(reciprocated);
incomingTrack(reciprocated);
PLOG_DEBUG
<< "Reciprocating media in local description, mid=\""
<< reciprocated.mid() << "\", active=" << std::boolalpha
<< (reciprocated.direction() != Description::Direction::Inactive);
PLOG_DEBUG
<< "Reciprocating media in local description, mid=\""
<< reciprocated.mid() << "\", active=" << std::boolalpha
<< (reciprocated.direction() != Description::Direction::Inactive);
description.addMedia(std::move(reciprocated));
},
},
remote->media(i));
}
description.addMedia(std::move(reciprocated));
},
},
remote->media(i));
}
if (description.type() == Description::Type::Offer) {
// This is an offer, add locally created data channels and tracks
@ -1128,23 +1123,23 @@ void PeerConnection::processLocalDescription(Description description) {
// Add media for local tracks
std::shared_lock lock(mTracksMutex);
for (auto it = mTrackLines.begin(); it != mTrackLines.end(); ++it) {
if (auto track = it->lock()) {
if (description.hasMid(track->mid()))
continue;
for (auto it = mTrackLines.begin(); it != mTrackLines.end(); ++it) {
if (auto track = it->lock()) {
if (description.hasMid(track->mid()))
continue;
auto media = track->description();
auto media = track->description();
#if !RTC_ENABLE_MEDIA
// No media support, mark as inactive
media.setDirection(Description::Direction::Inactive);
// No media support, mark as inactive
media.setDirection(Description::Direction::Inactive);
#endif
PLOG_DEBUG << "Adding media to local description, mid=\"" << media.mid()
<< "\", active=" << std::boolalpha
<< (media.direction() != Description::Direction::Inactive);
PLOG_DEBUG << "Adding media to local description, mid=\"" << media.mid()
<< "\", active=" << std::boolalpha
<< (media.direction() != Description::Direction::Inactive);
description.addMedia(std::move(media));
}
}
description.addMedia(std::move(media));
}
}
}
// Set local fingerprint (wait for certificate if necessary)

View File

@ -41,4 +41,3 @@ void Processor::schedule() {
}
} // namespace rtc

View File

@ -44,8 +44,7 @@ public:
void join();
template <class F, class... Args>
void enqueue(F &&f, Args &&... args);
template <class F, class... Args> void enqueue(F &&f, Args &&... args);
protected:
void schedule();

View File

@ -19,9 +19,9 @@
#include "rtcp.hpp"
#include "track.hpp"
#include <cmath>
#include <utility>
#include "track.hpp"
#ifdef _WIN32
#include <winsock2.h>
@ -29,12 +29,9 @@
#include <arpa/inet.h>
#endif
namespace rtc {
rtc::message_ptr RtcpReceivingSession::outgoing(rtc::message_ptr ptr) {
return ptr;
}
rtc::message_ptr RtcpReceivingSession::outgoing(rtc::message_ptr ptr) { return ptr; }
rtc::message_ptr RtcpReceivingSession::incoming(rtc::message_ptr ptr) {
if (ptr->type == rtc::Message::Type::Binary) {
@ -98,7 +95,7 @@ void RtcpReceivingSession::pushREMB(unsigned int bitrate) {
remb->preparePacket(mSsrc, 1, bitrate);
remb->setSsrc(0, mSsrc);
send(msg);
send(msg);
}
void RtcpReceivingSession::pushRR(unsigned int lastSR_delay) {
@ -109,13 +106,13 @@ void RtcpReceivingSession::pushRR(unsigned int lastSR_delay) {
lastSR_delay);
rr->log();
send(msg);
send(msg);
}
bool RtcpReceivingSession::send(message_ptr msg) {
try {
outgoingCallback(std::move(msg));
return true;
outgoingCallback(std::move(msg));
return true;
} catch (const std::exception &e) {
LOG_DEBUG << "RTCP tx failed: " << e.what();
}
@ -123,19 +120,18 @@ bool RtcpReceivingSession::send(message_ptr msg) {
}
bool RtcpReceivingSession::requestKeyframe() {
pushPLI();
return true; // TODO Make this false when it is impossible (i.e. Opus).
pushPLI();
return true; // TODO Make this false when it is impossible (i.e. Opus).
}
void RtcpReceivingSession::pushPLI() {
auto msg = rtc::make_message(rtc::RTCP_PLI::size(), rtc::Message::Type::Control);
auto *pli = (rtc::RTCP_PLI *) msg->data();
pli->preparePacket(mSsrc);
send(msg);
auto msg = rtc::make_message(rtc::RTCP_PLI::size(), rtc::Message::Type::Control);
auto *pli = (rtc::RTCP_PLI *)msg->data();
pli->preparePacket(mSsrc);
send(msg);
}
void RtcpHandler::onOutgoing(const std::function<void(rtc::message_ptr)>& cb) {
this->outgoingCallback = synchronized_callback<rtc::message_ptr>(cb);
void RtcpHandler::onOutgoing(const std::function<void(rtc::message_ptr)> &cb) {
this->outgoingCallback = synchronized_callback<rtc::message_ptr>(cb);
}
} // namespace rtc

View File

@ -100,7 +100,7 @@ private:
std::mutex mWriteMutex;
std::condition_variable mWrittenCondition;
std::atomic<bool> mWritten = false; // written outside lock
std::atomic<bool> mWritten = false; // written outside lock
std::atomic<bool> mWrittenOnce = false; // same
binary mPartialMessage, mPartialNotification;

View File

@ -75,4 +75,3 @@ std::function<void()> ThreadPool::dequeue() {
}
} // namespace rtc

View File

@ -75,13 +75,13 @@ auto ThreadPool::enqueue(F &&f, Args &&... args) -> invoke_future_t<F, Args...>
using R = std::invoke_result_t<std::decay_t<F>, std::decay_t<Args>...>;
auto bound = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
auto task = std::make_shared<std::packaged_task<R()>>([bound = std::move(bound)]() mutable {
try {
return bound();
} catch (const std::exception &e) {
PLOG_WARNING << e.what();
throw;
}
});
try {
return bound();
} catch (const std::exception &e) {
PLOG_WARNING << e.what();
throw;
}
});
std::future<R> result = task->get_future();
mTasks.emplace([task = std::move(task), token = Init::Token()]() { return (*task)(); });

View File

@ -127,4 +127,3 @@ bool check(SSL *ssl, int ret, const string &message) {
} // namespace rtc::openssl
#endif

View File

@ -56,12 +56,12 @@ gnutls_datum_t make_datum(char *data, size_t size);
#include <openssl/ssl.h>
#include <openssl/bio.h>
#include <openssl/bn.h>
#include <openssl/ec.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
#include <openssl/rsa.h>
#include <openssl/bn.h>
#include <openssl/x509.h>
#ifndef BIO_EOF
#define BIO_EOF -1

View File

@ -62,10 +62,10 @@ TlsTransport::TlsTransport(shared_ptr<TcpTransport> lower, string host, state_ca
gnutls::check(gnutls_priority_set_direct(mSession, priorities, &err_pos),
"Failed to set TLS priorities");
PLOG_VERBOSE << "Server Name Indication: " << mHost;
PLOG_VERBOSE << "Server Name Indication: " << mHost;
gnutls_server_name_set(mSession, GNUTLS_NAME_DNS, mHost.data(), mHost.size());
gnutls_session_set_ptr(mSession, this);
gnutls_session_set_ptr(mSession, this);
gnutls_transport_set_ptr(mSession, this);
gnutls_transport_set_push_function(mSession, WriteCallback);
gnutls_transport_set_pull_function(mSession, ReadCallback);
@ -110,7 +110,7 @@ bool TlsTransport::send(message_ptr message) {
PLOG_VERBOSE << "Send size=" << message->size();
if(message->size() == 0)
if (message->size() == 0)
return true;
ssize_t ret;
@ -207,10 +207,10 @@ ssize_t TlsTransport::ReadCallback(gnutls_transport_ptr_t ptr, void *data, size_
message_ptr &message = t->mIncomingMessage;
size_t &position = t->mIncomingMessagePosition;
if(message && position >= message->size())
if (message && position >= message->size())
message.reset();
if(!message) {
if (!message) {
position = 0;
while (auto next = t->mIncomingQueue.pop()) {
message = *next;
@ -221,15 +221,14 @@ ssize_t TlsTransport::ReadCallback(gnutls_transport_ptr_t ptr, void *data, size_
}
}
if(message) {
if (message) {
size_t available = message->size() - position;
ssize_t len = std::min(maxlen, available);
std::memcpy(data, message->data() + position, len);
position+= len;
position += len;
gnutls_transport_set_errno(t->mSession, 0);
return len;
}
else {
} else {
// Closed
gnutls_transport_set_errno(t->mSession, 0);
return 0;

View File

@ -32,9 +32,8 @@ string Track::mid() const { return mMediaDescription.mid(); }
Description::Media Track::description() const { return mMediaDescription; }
void Track::setDescription(Description::Media description) {
if(description.mid() != mMediaDescription.mid())
if (description.mid() != mMediaDescription.mid())
throw std::logic_error("Media description mid does not match track mid");
mMediaDescription = std::move(description);
@ -80,9 +79,7 @@ size_t Track::maxMessageSize() const {
return 65535 - 12 - 4; // SRTP/UDP
}
size_t Track::availableAmount() const {
return mRecvQueue.amount();
}
size_t Track::availableAmount() const { return mRecvQueue.amount(); }
#if RTC_ENABLE_MEDIA
void Track::open(shared_ptr<DtlsSrtpTransport> transport) {
@ -93,34 +90,34 @@ void Track::open(shared_ptr<DtlsSrtpTransport> transport) {
bool Track::outgoing(message_ptr message) {
if (mRtcpHandler) {
message = mRtcpHandler->outgoing(message);
if (!message)
return false;
}
if (mRtcpHandler) {
message = mRtcpHandler->outgoing(message);
if (!message)
return false;
}
auto direction = mMediaDescription.direction();
if ((direction == Description::Direction::RecvOnly ||
direction == Description::Direction::Inactive) &&
message->type != Message::Control) {
PLOG_WARNING << "Track media direction does not allow transmission, dropping";
return false;
}
auto direction = mMediaDescription.direction();
if ((direction == Description::Direction::RecvOnly ||
direction == Description::Direction::Inactive) &&
message->type != Message::Control) {
PLOG_WARNING << "Track media direction does not allow transmission, dropping";
return false;
}
if (mIsClosed)
throw std::runtime_error("Track is closed");
if (mIsClosed)
throw std::runtime_error("Track is closed");
if (message->size() > maxMessageSize())
throw std::runtime_error("Message size exceeds limit");
if (message->size() > maxMessageSize())
throw std::runtime_error("Message size exceeds limit");
#if RTC_ENABLE_MEDIA
auto transport = mDtlsSrtpTransport.lock();
if (!transport)
throw std::runtime_error("Track transport is not open");
auto transport = mDtlsSrtpTransport.lock();
if (!transport)
throw std::runtime_error("Track transport is not open");
return transport->sendMedia(message);
return transport->sendMedia(message);
#else
PLOG_WARNING << "Ignoring track send (not compiled with SRTP support)";
PLOG_WARNING << "Ignoring track send (not compiled with SRTP support)";
return false;
#endif
}
@ -130,10 +127,10 @@ void Track::incoming(message_ptr message) {
return;
if (mRtcpHandler) {
message = mRtcpHandler->incoming(message);
if (!message)
return ;
}
message = mRtcpHandler->incoming(message);
if (!message)
return;
}
auto direction = mMediaDescription.direction();
if ((direction == Description::Direction::SendOnly ||
@ -154,30 +151,27 @@ void Track::incoming(message_ptr message) {
void Track::setRtcpHandler(std::shared_ptr<RtcpHandler> handler) {
mRtcpHandler = std::move(handler);
if (mRtcpHandler) {
mRtcpHandler->onOutgoing([&]([[maybe_unused]] const rtc::message_ptr& message) {
#if RTC_ENABLE_MEDIA
mRtcpHandler->onOutgoing([&]([[maybe_unused]] const rtc::message_ptr &message) {
#if RTC_ENABLE_MEDIA
auto transport = mDtlsSrtpTransport.lock();
if (!transport)
throw std::runtime_error("Track transport is not open");
throw std::runtime_error("Track transport is not open");
return transport->sendMedia(message);
#else
#else
PLOG_WARNING << "Ignoring track send (not compiled with SRTP support)";
return false;
#endif
return false;
#endif
});
}
}
bool Track::requestKeyframe() {
if (mRtcpHandler)
return mRtcpHandler->requestKeyframe();
return false;
if (mRtcpHandler)
return mRtcpHandler->requestKeyframe();
return false;
}
std::shared_ptr<RtcpHandler> Track::getRtcpHandler() {
return mRtcpHandler;
}
std::shared_ptr<RtcpHandler> Track::getRtcpHandler() { return mRtcpHandler; }
} // namespace rtc

View File

@ -36,8 +36,7 @@ public:
using state_callback = std::function<void(State state)>;
Transport(std::shared_ptr<Transport> lower = nullptr, state_callback callback = nullptr)
: mLower(std::move(lower)), mStateChangeCallback(std::move(callback)) {
}
: mLower(std::move(lower)), mStateChangeCallback(std::move(callback)) {}
virtual ~Transport() { stop(); }

View File

@ -28,7 +28,6 @@ using std::weak_ptr;
namespace rtc {
VerifiedTlsTransport::VerifiedTlsTransport(shared_ptr<TcpTransport> lower, string host,
state_callback callback)
: TlsTransport(std::move(lower), std::move(host), std::move(callback)) {
@ -48,4 +47,3 @@ VerifiedTlsTransport::~VerifiedTlsTransport() {}
} // namespace rtc
#endif

View File

@ -256,7 +256,8 @@ shared_ptr<TlsTransport> WebSocket::initTlsTransport() {
if (mConfig.disableTlsVerification)
transport = std::make_shared<TlsTransport>(lower, mHostname, stateChangeCallback);
else
transport = std::make_shared<VerifiedTlsTransport>(lower, mHostname, stateChangeCallback);
transport =
std::make_shared<VerifiedTlsTransport>(lower, mHostname, stateChangeCallback);
#endif
std::atomic_store(&mTlsTransport, transport);

View File

@ -17,9 +17,9 @@
*/
#include "wstransport.hpp"
#include "base64.hpp"
#include "tcptransport.hpp"
#include "tlstransport.hpp"
#include "base64.hpp"
#if RTC_ENABLE_WEBSOCKET

View File

@ -20,11 +20,11 @@
#if RTC_ENABLE_WEBSOCKET
#include <atomic>
#include <chrono>
#include <iostream>
#include <memory>
#include <thread>
#include <atomic>
using namespace rtc;
using namespace std;
@ -56,7 +56,7 @@ void test_websocket() {
ws->onMessage([&received, &myMessage](variant<binary, string> message) {
if (holds_alternative<string>(message)) {
string str = std::move(get<string>(message));
if((received = (str == myMessage)))
if ((received = (str == myMessage)))
cout << "WebSocket: Received expected message" << endl;
else
cout << "WebSocket: Received UNEXPECTED message" << endl;
@ -72,7 +72,7 @@ void test_websocket() {
if (!ws->isOpen())
throw runtime_error("WebSocket is not open");
if(!received)
if (!received)
throw runtime_error("Expected message not received");
ws->close();
@ -86,4 +86,3 @@ void test_websocket() {
}
#endif