Browse Source

Merge pull request #50 from murat-dogan/stats

Stats
Paul-Louis Ageneau 5 years ago
parent
commit
d446f49d5f

+ 1 - 1
deps/libjuice

@@ -1 +1 @@
-Subproject commit de88282d7bde7660b5d606cb302e56f079c171df
+Subproject commit dd3a5375b5fcc0e6122217dbf22af55bd6910ec3

+ 6 - 0
include/rtc/peerconnection.hpp

@@ -89,6 +89,12 @@ public:
 
 	bool getSelectedCandidatePair(CandidateInfo *local, CandidateInfo *remote);
 
+	// Stats
+	void clearStats();
+	size_t bytesSent();
+	size_t bytesReceived();
+	std::optional<std::chrono::milliseconds> rtt();
+
 private:
 	init_token mInitToken = Init::Token();
 

+ 28 - 1
src/peerconnection.cpp

@@ -579,6 +579,34 @@ bool PeerConnection::getSelectedCandidatePair(CandidateInfo *local, CandidateInf
 #endif
 }
 
+void PeerConnection::clearStats() {
+	auto sctpTransport = std::atomic_load(&mSctpTransport);
+	if (sctpTransport)
+		return sctpTransport->clearStats();
+}
+
+size_t PeerConnection::bytesSent() {
+	auto sctpTransport = std::atomic_load(&mSctpTransport);
+	if (sctpTransport)
+		return sctpTransport->bytesSent();
+	return 0;
+}
+
+size_t PeerConnection::bytesReceived() {
+	auto sctpTransport = std::atomic_load(&mSctpTransport);
+	if (sctpTransport)
+		return sctpTransport->bytesReceived();
+	return 0;
+}
+
+std::optional<std::chrono::milliseconds> PeerConnection::rtt() {
+	auto sctpTransport = std::atomic_load(&mSctpTransport);
+	if (sctpTransport)
+		return sctpTransport->rtt();
+	PLOG_WARNING << "Could not load sctpTransport";
+	return std::nullopt;
+}
+
 } // namespace rtc
 
 std::ostream &operator<<(std::ostream &out, const rtc::PeerConnection::State &state) {
@@ -629,4 +657,3 @@ std::ostream &operator<<(std::ostream &out, const rtc::PeerConnection::Gathering
 	}
 	return out << str;
 }
-

+ 26 - 0
src/sctptransport.cpp

@@ -364,6 +364,8 @@ bool SctpTransport::trySendMessage(message_ptr message) {
 
 	if (ret >= 0) {
 		PLOG_VERBOSE << "SCTP sent size=" << message->size();
+		if (message->type == Message::Type::Binary || message->type == Message::Type::String)
+			mBytesSent += message->size();
 		return true;
 	} else if (errno == EWOULDBLOCK || errno == EAGAIN) {
 		PLOG_VERBOSE << "SCTP sending not possible";
@@ -470,9 +472,11 @@ void SctpTransport::processData(const byte *data, size_t len, uint16_t sid, Payl
 
 	case PPID_STRING:
 		if (mPartialStringData.empty()) {
+			mBytesReceived += len;
 			recv(make_message(data, data + len, Message::String, sid));
 		} else {
 			mPartialStringData.insert(mPartialStringData.end(), data, data + len);
+			mBytesReceived += mPartialStringData.size();
 			recv(make_message(mPartialStringData.begin(), mPartialStringData.end(), Message::String,
 			                  sid));
 			mPartialStringData.clear();
@@ -492,9 +496,11 @@ void SctpTransport::processData(const byte *data, size_t len, uint16_t sid, Payl
 
 	case PPID_BINARY:
 		if (mPartialBinaryData.empty()) {
+			mBytesReceived += len;
 			recv(make_message(data, data + len, Message::Binary, sid));
 		} else {
 			mPartialBinaryData.insert(mPartialBinaryData.end(), data, data + len);
+			mBytesReceived += mPartialStringData.size();
 			recv(make_message(mPartialBinaryData.begin(), mPartialBinaryData.end(), Message::Binary,
 			                  sid));
 			mPartialBinaryData.clear();
@@ -578,6 +584,26 @@ void SctpTransport::processNotification(const union sctp_notification *notify, s
 	}
 }
 
+void SctpTransport::clearStats() {
+	mBytesReceived = 0;
+	mBytesSent = 0;
+}
+
+size_t SctpTransport::bytesSent() { return mBytesSent; }
+
+size_t SctpTransport::bytesReceived() { return mBytesReceived; }
+
+std::optional<std::chrono::milliseconds> SctpTransport::rtt() {
+	struct sctp_status status = {};
+	socklen_t len = sizeof(status);
+
+	if (usrsctp_getsockopt(this->mSock, IPPROTO_SCTP, SCTP_STATUS, &status, &len)) {
+		PLOG_WARNING << "Could not read SCTP_STATUS";
+		return std::nullopt;
+	}
+	return std::chrono::milliseconds(status.sstat_primary.spinfo_srtt);
+}
+
 int SctpTransport::RecvCallback(struct socket *sock, union sctp_sockstore addr, void *data,
                                 size_t len, struct sctp_rcvinfo recv_info, int flags, void *ptr) {
 	int ret = static_cast<SctpTransport *>(ptr)->handleRecv(

+ 9 - 0
src/sctptransport.hpp

@@ -54,6 +54,12 @@ public:
 	void flush();
 	void reset(unsigned int stream);
 
+	// Stats
+	void clearStats();
+	size_t bytesSent();
+	size_t bytesReceived();
+	std::optional<std::chrono::milliseconds> rtt();
+
 private:
 	// Order seems wrong but these are the actual values
 	// See https://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-13#section-8
@@ -101,6 +107,9 @@ private:
 	state_callback mStateChangeCallback;
 	std::atomic<State> mState;
 
+	// Stats
+	std::atomic<size_t> mBytesSent = 0, mBytesReceived = 0;
+
 	binary mPartialRecv, mPartialStringData, mPartialBinaryData;
 
 	static int RecvCallback(struct socket *sock, union sctp_sockstore addr, void *data, size_t len,

+ 8 - 0
test/p2p/answerer.cpp

@@ -128,11 +128,19 @@ int main(int argc, char **argv) {
 				break;
 			}
 			CandidateInfo local, remote;
+			std::optional<std::chrono::milliseconds> rtt = pc->rtt();
 			if (pc->getSelectedCandidatePair(&local, &remote)) {
 				cout << "Local: " << local.address << ":" << local.port << " " << local.type << " "
 				     << local.transportType << endl;
 				cout << "Remote: " << remote.address << ":" << remote.port << " " << remote.type
 				     << " " << remote.transportType << endl;
+				cout << "Bytes Sent:" << pc->bytesSent()
+				     << " / Bytes Received:" << pc->bytesReceived() << " / Round-Trip Time:";
+				if (rtt.has_value())
+					cout << rtt.value().count();
+				else
+					cout << "null";
+				cout << " ms";
 			} else
 				cout << "Could not get Candidate Pair Info" << endl;
 			break;

+ 8 - 0
test/p2p/offerer.cpp

@@ -128,11 +128,19 @@ int main(int argc, char **argv) {
 				break;
 			}
 			CandidateInfo local, remote;
+			std::optional<std::chrono::milliseconds> rtt = pc->rtt();
 			if (pc->getSelectedCandidatePair(&local, &remote)) {
 				cout << "Local: " << local.address << ":" << local.port << " " << local.type << " "
 				     << local.transportType << endl;
 				cout << "Remote: " << remote.address << ":" << remote.port << " " << remote.type
 				     << " " << remote.transportType << endl;
+				cout << "Bytes Sent:" << pc->bytesSent()
+				     << " / Bytes Received:" << pc->bytesReceived() << " / Round-Trip Time:";
+				if (rtt.has_value())
+					cout << rtt.value().count();
+				else
+					cout << "null";
+				cout << " ms";
 			} else
 				cout << "Could not get Candidate Pair Info" << endl;
 			break;