From fe254a31dff126c9b083cce8e725bb8d0ccc709c Mon Sep 17 00:00:00 2001 From: EKR Date: Wed, 26 Sep 2012 10:14:23 -0700 Subject: [PATCH] Bug 792175 - Move PeerConnection operations onto main thread. r=jesup,derf,ehugg --- media/mtransport/nricemediastream.cpp | 5 +- media/mtransport/runnable_utils.py | 2 +- media/mtransport/runnable_utils_generated.h | 740 ++++++++++++++++++ .../signaling/src/media/VcmSIPCCBinding.cpp | 621 +++++++++++---- .../signaling/src/media/VcmSIPCCBinding.h | 12 +- .../src/mediapipeline/MediaPipeline.cpp | 19 +- .../src/peerconnection/PeerConnectionCtx.cpp | 93 ++- .../src/peerconnection/PeerConnectionCtx.h | 24 +- .../src/peerconnection/PeerConnectionImpl.cpp | 492 ++++++------ .../src/peerconnection/PeerConnectionImpl.h | 89 ++- .../webrtc/signaling/test/FakeMediaStreams.h | 12 +- .../signaling/test/FakeMediaStreamsImpl.h | 7 + .../signaling/test/signaling_unittests.cpp | 52 +- 13 files changed, 1691 insertions(+), 477 deletions(-) diff --git a/media/mtransport/nricemediastream.cpp b/media/mtransport/nricemediastream.cpp index ce872c902f8..afdd1865fa3 100644 --- a/media/mtransport/nricemediastream.cpp +++ b/media/mtransport/nricemediastream.cpp @@ -107,7 +107,7 @@ nsresult NrIceMediaStream::ParseAttributes(std::vector& for (size_t i=0; i(attributes[i].c_str())); } - + // Still need to call nr_ice_ctx_parse_stream_attributes. int r = nr_ice_peer_ctx_parse_stream_attributes(ctx_->peer(), stream_, @@ -127,7 +127,8 @@ nsresult NrIceMediaStream::ParseAttributes(std::vector& nsresult NrIceMediaStream::ParseTrickleCandidate(const std::string& candidate) { int r; - MOZ_MTLOG(PR_LOG_DEBUG, "NrIceCtx(" << ctx_->name() << "): parsing trickle candidate " << candidate); + MOZ_MTLOG(PR_LOG_DEBUG, "NrIceCtx(" << ctx_->name() << ")/STREAM(" << + name() << ") : parsing trickle candidate " << candidate); r = nr_ice_peer_ctx_parse_trickle_candidate(ctx_->peer(), stream_, diff --git a/media/mtransport/runnable_utils.py b/media/mtransport/runnable_utils.py index b5d28b9cdb1..2934445bfd9 100644 --- a/media/mtransport/runnable_utils.py +++ b/media/mtransport/runnable_utils.py @@ -1,7 +1,7 @@ # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -MAX_ARGS = 10 +MAX_ARGS = 15 boilerplate = "/* This Source Code Form is subject to the terms of the Mozilla Public\n\ * License, v. 2.0. If a copy of the MPL was not distributed with this\n\ diff --git a/media/mtransport/runnable_utils_generated.h b/media/mtransport/runnable_utils_generated.h index 6d4aaa4fc35..195cf16c45b 100644 --- a/media/mtransport/runnable_utils_generated.h +++ b/media/mtransport/runnable_utils_generated.h @@ -903,6 +903,606 @@ template class runnable_args_nm_10 : public runnable_args_base { + public: + runnable_args_nm_10(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) : + m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9) {} + + NS_IMETHOD Run() { + m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_); + return NS_OK; + } + + private: + M m_; + A0 a0_; + A1 a1_; + A2 a2_; + A3 a3_; + A4 a4_; + A5 a5_; + A6 a6_; + A7 a7_; + A8 a8_; + A9 a9_; +}; + + + +// 10 arguments -- +template class runnable_args_nm_10_ret : public runnable_args_base { + public: + runnable_args_nm_10_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, R *r) : + m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9) {} + + NS_IMETHOD Run() { + *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_); + return NS_OK; + } + + private: + M m_; + R* r_; + A0 a0_; + A1 a1_; + A2 a2_; + A3 a3_; + A4 a4_; + A5 a5_; + A6 a6_; + A7 a7_; + A8 a8_; + A9 a9_; +}; + + + +// 10 arguments -- +template class runnable_args_m_10 : public runnable_args_base { + public: + runnable_args_m_10(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) : + o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9) {} + + NS_IMETHOD Run() { + ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_); + return NS_OK; + } + + private: + C o_; + M m_; + A0 a0_; + A1 a1_; + A2 a2_; + A3 a3_; + A4 a4_; + A5 a5_; + A6 a6_; + A7 a7_; + A8 a8_; + A9 a9_; +}; + + + +// 10 arguments -- +template class runnable_args_m_10_ret : public runnable_args_base { + public: + runnable_args_m_10_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, R *r) : + o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9) {} + + NS_IMETHOD Run() { + *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_); + return NS_OK; + } + + private: + C o_; + M m_; + R* r_; + A0 a0_; + A1 a1_; + A2 a2_; + A3 a3_; + A4 a4_; + A5 a5_; + A6 a6_; + A7 a7_; + A8 a8_; + A9 a9_; +}; + + + +// 11 arguments -- +template class runnable_args_nm_11 : public runnable_args_base { + public: + runnable_args_nm_11(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) : + m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10) {} + + NS_IMETHOD Run() { + m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_); + return NS_OK; + } + + private: + M m_; + A0 a0_; + A1 a1_; + A2 a2_; + A3 a3_; + A4 a4_; + A5 a5_; + A6 a6_; + A7 a7_; + A8 a8_; + A9 a9_; + A10 a10_; +}; + + + +// 11 arguments -- +template class runnable_args_nm_11_ret : public runnable_args_base { + public: + runnable_args_nm_11_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, R *r) : + m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10) {} + + NS_IMETHOD Run() { + *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_); + return NS_OK; + } + + private: + M m_; + R* r_; + A0 a0_; + A1 a1_; + A2 a2_; + A3 a3_; + A4 a4_; + A5 a5_; + A6 a6_; + A7 a7_; + A8 a8_; + A9 a9_; + A10 a10_; +}; + + + +// 11 arguments -- +template class runnable_args_m_11 : public runnable_args_base { + public: + runnable_args_m_11(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) : + o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10) {} + + NS_IMETHOD Run() { + ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_); + return NS_OK; + } + + private: + C o_; + M m_; + A0 a0_; + A1 a1_; + A2 a2_; + A3 a3_; + A4 a4_; + A5 a5_; + A6 a6_; + A7 a7_; + A8 a8_; + A9 a9_; + A10 a10_; +}; + + + +// 11 arguments -- +template class runnable_args_m_11_ret : public runnable_args_base { + public: + runnable_args_m_11_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, R *r) : + o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10) {} + + NS_IMETHOD Run() { + *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_); + return NS_OK; + } + + private: + C o_; + M m_; + R* r_; + A0 a0_; + A1 a1_; + A2 a2_; + A3 a3_; + A4 a4_; + A5 a5_; + A6 a6_; + A7 a7_; + A8 a8_; + A9 a9_; + A10 a10_; +}; + + + +// 12 arguments -- +template class runnable_args_nm_12 : public runnable_args_base { + public: + runnable_args_nm_12(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11) : + m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11) {} + + NS_IMETHOD Run() { + m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_); + return NS_OK; + } + + private: + M m_; + A0 a0_; + A1 a1_; + A2 a2_; + A3 a3_; + A4 a4_; + A5 a5_; + A6 a6_; + A7 a7_; + A8 a8_; + A9 a9_; + A10 a10_; + A11 a11_; +}; + + + +// 12 arguments -- +template class runnable_args_nm_12_ret : public runnable_args_base { + public: + runnable_args_nm_12_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, R *r) : + m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11) {} + + NS_IMETHOD Run() { + *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_); + return NS_OK; + } + + private: + M m_; + R* r_; + A0 a0_; + A1 a1_; + A2 a2_; + A3 a3_; + A4 a4_; + A5 a5_; + A6 a6_; + A7 a7_; + A8 a8_; + A9 a9_; + A10 a10_; + A11 a11_; +}; + + + +// 12 arguments -- +template class runnable_args_m_12 : public runnable_args_base { + public: + runnable_args_m_12(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11) : + o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11) {} + + NS_IMETHOD Run() { + ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_); + return NS_OK; + } + + private: + C o_; + M m_; + A0 a0_; + A1 a1_; + A2 a2_; + A3 a3_; + A4 a4_; + A5 a5_; + A6 a6_; + A7 a7_; + A8 a8_; + A9 a9_; + A10 a10_; + A11 a11_; +}; + + + +// 12 arguments -- +template class runnable_args_m_12_ret : public runnable_args_base { + public: + runnable_args_m_12_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, R *r) : + o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11) {} + + NS_IMETHOD Run() { + *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_); + return NS_OK; + } + + private: + C o_; + M m_; + R* r_; + A0 a0_; + A1 a1_; + A2 a2_; + A3 a3_; + A4 a4_; + A5 a5_; + A6 a6_; + A7 a7_; + A8 a8_; + A9 a9_; + A10 a10_; + A11 a11_; +}; + + + +// 13 arguments -- +template class runnable_args_nm_13 : public runnable_args_base { + public: + runnable_args_nm_13(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12) : + m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12) {} + + NS_IMETHOD Run() { + m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_); + return NS_OK; + } + + private: + M m_; + A0 a0_; + A1 a1_; + A2 a2_; + A3 a3_; + A4 a4_; + A5 a5_; + A6 a6_; + A7 a7_; + A8 a8_; + A9 a9_; + A10 a10_; + A11 a11_; + A12 a12_; +}; + + + +// 13 arguments -- +template class runnable_args_nm_13_ret : public runnable_args_base { + public: + runnable_args_nm_13_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, R *r) : + m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12) {} + + NS_IMETHOD Run() { + *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_); + return NS_OK; + } + + private: + M m_; + R* r_; + A0 a0_; + A1 a1_; + A2 a2_; + A3 a3_; + A4 a4_; + A5 a5_; + A6 a6_; + A7 a7_; + A8 a8_; + A9 a9_; + A10 a10_; + A11 a11_; + A12 a12_; +}; + + + +// 13 arguments -- +template class runnable_args_m_13 : public runnable_args_base { + public: + runnable_args_m_13(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12) : + o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12) {} + + NS_IMETHOD Run() { + ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_); + return NS_OK; + } + + private: + C o_; + M m_; + A0 a0_; + A1 a1_; + A2 a2_; + A3 a3_; + A4 a4_; + A5 a5_; + A6 a6_; + A7 a7_; + A8 a8_; + A9 a9_; + A10 a10_; + A11 a11_; + A12 a12_; +}; + + + +// 13 arguments -- +template class runnable_args_m_13_ret : public runnable_args_base { + public: + runnable_args_m_13_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, R *r) : + o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12) {} + + NS_IMETHOD Run() { + *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_); + return NS_OK; + } + + private: + C o_; + M m_; + R* r_; + A0 a0_; + A1 a1_; + A2 a2_; + A3 a3_; + A4 a4_; + A5 a5_; + A6 a6_; + A7 a7_; + A8 a8_; + A9 a9_; + A10 a10_; + A11 a11_; + A12 a12_; +}; + + + +// 14 arguments -- +template class runnable_args_nm_14 : public runnable_args_base { + public: + runnable_args_nm_14(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13) : + m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12), a13_(a13) {} + + NS_IMETHOD Run() { + m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_, a13_); + return NS_OK; + } + + private: + M m_; + A0 a0_; + A1 a1_; + A2 a2_; + A3 a3_; + A4 a4_; + A5 a5_; + A6 a6_; + A7 a7_; + A8 a8_; + A9 a9_; + A10 a10_; + A11 a11_; + A12 a12_; + A13 a13_; +}; + + + +// 14 arguments -- +template class runnable_args_nm_14_ret : public runnable_args_base { + public: + runnable_args_nm_14_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, R *r) : + m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12), a13_(a13) {} + + NS_IMETHOD Run() { + *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_, a13_); + return NS_OK; + } + + private: + M m_; + R* r_; + A0 a0_; + A1 a1_; + A2 a2_; + A3 a3_; + A4 a4_; + A5 a5_; + A6 a6_; + A7 a7_; + A8 a8_; + A9 a9_; + A10 a10_; + A11 a11_; + A12 a12_; + A13 a13_; +}; + + + +// 14 arguments -- +template class runnable_args_m_14 : public runnable_args_base { + public: + runnable_args_m_14(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13) : + o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12), a13_(a13) {} + + NS_IMETHOD Run() { + ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_, a13_); + return NS_OK; + } + + private: + C o_; + M m_; + A0 a0_; + A1 a1_; + A2 a2_; + A3 a3_; + A4 a4_; + A5 a5_; + A6 a6_; + A7 a7_; + A8 a8_; + A9 a9_; + A10 a10_; + A11 a11_; + A12 a12_; + A13 a13_; +}; + + + +// 14 arguments -- +template class runnable_args_m_14_ret : public runnable_args_base { + public: + runnable_args_m_14_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, R *r) : + o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12), a13_(a13) {} + + NS_IMETHOD Run() { + *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_, a13_); + return NS_OK; + } + + private: + C o_; + M m_; + R* r_; + A0 a0_; + A1 a1_; + A2 a2_; + A3 a3_; + A4 a4_; + A5 a5_; + A6 a6_; + A7 a7_; + A8 a8_; + A9 a9_; + A10 a10_; + A11 a11_; + A12 a12_; + A13 a13_; +}; + + + @@ -1186,3 +1786,143 @@ runnable_args_m_9_ret* WrapRunnable (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, r); } +// 10 arguments -- +template +runnable_args_nm_10* WrapRunnableNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) { + return new runnable_args_nm_10 + (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); +} + +// 10 arguments -- +template +runnable_args_nm_10_ret* WrapRunnableNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, R* r) { + return new runnable_args_nm_10_ret + (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, r); +} + +// 10 arguments -- +template +runnable_args_m_10* WrapRunnable(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) { + return new runnable_args_m_10 + (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); +} + +// 10 arguments -- +template +runnable_args_m_10_ret* WrapRunnableRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, R* r) { + return new runnable_args_m_10_ret + (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, r); +} + +// 11 arguments -- +template +runnable_args_nm_11* WrapRunnableNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) { + return new runnable_args_nm_11 + (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); +} + +// 11 arguments -- +template +runnable_args_nm_11_ret* WrapRunnableNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, R* r) { + return new runnable_args_nm_11_ret + (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, r); +} + +// 11 arguments -- +template +runnable_args_m_11* WrapRunnable(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) { + return new runnable_args_m_11 + (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); +} + +// 11 arguments -- +template +runnable_args_m_11_ret* WrapRunnableRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, R* r) { + return new runnable_args_m_11_ret + (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, r); +} + +// 12 arguments -- +template +runnable_args_nm_12* WrapRunnableNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11) { + return new runnable_args_nm_12 + (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); +} + +// 12 arguments -- +template +runnable_args_nm_12_ret* WrapRunnableNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, R* r) { + return new runnable_args_nm_12_ret + (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, r); +} + +// 12 arguments -- +template +runnable_args_m_12* WrapRunnable(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11) { + return new runnable_args_m_12 + (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); +} + +// 12 arguments -- +template +runnable_args_m_12_ret* WrapRunnableRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, R* r) { + return new runnable_args_m_12_ret + (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, r); +} + +// 13 arguments -- +template +runnable_args_nm_13* WrapRunnableNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12) { + return new runnable_args_nm_13 + (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); +} + +// 13 arguments -- +template +runnable_args_nm_13_ret* WrapRunnableNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, R* r) { + return new runnable_args_nm_13_ret + (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, r); +} + +// 13 arguments -- +template +runnable_args_m_13* WrapRunnable(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12) { + return new runnable_args_m_13 + (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); +} + +// 13 arguments -- +template +runnable_args_m_13_ret* WrapRunnableRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, R* r) { + return new runnable_args_m_13_ret + (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, r); +} + +// 14 arguments -- +template +runnable_args_nm_14* WrapRunnableNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13) { + return new runnable_args_nm_14 + (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); +} + +// 14 arguments -- +template +runnable_args_nm_14_ret* WrapRunnableNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, R* r) { + return new runnable_args_nm_14_ret + (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, r); +} + +// 14 arguments -- +template +runnable_args_m_14* WrapRunnable(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13) { + return new runnable_args_m_14 + (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); +} + +// 14 arguments -- +template +runnable_args_m_14_ret* WrapRunnableRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, R* r) { + return new runnable_args_m_14_ret + (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, r); +} + diff --git a/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp b/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp index 7d0e9ee0abd..566fcac031e 100644 --- a/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp +++ b/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp @@ -60,9 +60,10 @@ typedef enum { using namespace CSF; -VcmSIPCCBinding * VcmSIPCCBinding::_pSelf = NULL; -int VcmSIPCCBinding::mAudioCodecMask = 0; -int VcmSIPCCBinding::mVideoCodecMask = 0; +VcmSIPCCBinding * VcmSIPCCBinding::gSelf = NULL; +int VcmSIPCCBinding::gAudioCodecMask = 0; +int VcmSIPCCBinding::gVideoCodecMask = 0; +nsIThread *VcmSIPCCBinding::gMainThread = NULL; static mozilla::RefPtr vcmCreateTransportFlow(sipcc::PeerConnectionImpl *pc, int level, bool rtcp, @@ -70,17 +71,27 @@ static mozilla::RefPtr vcmCreateTransportFlow(sipcc::PeerConnecti const char *fingerprint ); +// Convenience macro to acquire PC + +#define ENSURE_PC(pc, errval) \ + do { \ + if (!pc.impl()) { \ + CSFLogDebug(logTag, "%s: couldn't acquire peerconnection %s", __FUNCTION__, peerconnection); \ + return errval; \ + } \ + } while(0) + VcmSIPCCBinding::VcmSIPCCBinding () : streamObserver(NULL) { - delete _pSelf;//delete is NULL safe, so I don't need to check if it's NULL - _pSelf = this; + delete gSelf;//delete is NULL safe, so I don't need to check if it's NULL + gSelf = this; } VcmSIPCCBinding::~VcmSIPCCBinding () { - assert(_pSelf != NULL); - _pSelf = NULL; + assert(gSelf); + gSelf = NULL; } void VcmSIPCCBinding::setStreamObserver(StreamObserver* obs) @@ -91,8 +102,8 @@ void VcmSIPCCBinding::setStreamObserver(StreamObserver* obs) /* static */ StreamObserver * VcmSIPCCBinding::getStreamObserver() { - if (_pSelf != NULL) - return _pSelf->streamObserver; + if (gSelf != NULL) + return gSelf->streamObserver; return NULL; } @@ -105,8 +116,8 @@ void VcmSIPCCBinding::setMediaProviderObserver(MediaProviderObserver* obs) MediaProviderObserver * VcmSIPCCBinding::getMediaProviderObserver() { - if (_pSelf != NULL) - return _pSelf->mediaProviderObserver; + if (gSelf != NULL) + return gSelf->mediaProviderObserver; return NULL; } @@ -114,25 +125,34 @@ MediaProviderObserver * VcmSIPCCBinding::getMediaProviderObserver() void VcmSIPCCBinding::setAudioCodecs(int codecMask) { CSFLogDebugS(logTag, "SETTING AUDIO: " << codecMask); - VcmSIPCCBinding::mAudioCodecMask = codecMask; + VcmSIPCCBinding::gAudioCodecMask = codecMask; } void VcmSIPCCBinding::setVideoCodecs(int codecMask) { CSFLogDebugS(logTag, "SETTING VIDEO: " << codecMask); - VcmSIPCCBinding::mVideoCodecMask = codecMask; + VcmSIPCCBinding::gVideoCodecMask = codecMask; } int VcmSIPCCBinding::getAudioCodecs() { - return VcmSIPCCBinding::mAudioCodecMask; + return VcmSIPCCBinding::gAudioCodecMask; } int VcmSIPCCBinding::getVideoCodecs() { - return VcmSIPCCBinding::mVideoCodecMask; + return VcmSIPCCBinding::gVideoCodecMask; } +void VcmSIPCCBinding::setMainThread(nsIThread *thread) +{ + gMainThread = thread; +} + +nsIThread* VcmSIPCCBinding::getMainThread() +{ + return gMainThread; +} /* static */ AudioTermination * VcmSIPCCBinding::getAudioTermination() @@ -393,16 +413,16 @@ void vcmRxAllocPort(cc_mcapid_t mcap_id, * @return void * */ -void vcmRxAllocICE(cc_mcapid_t mcap_id, - cc_groupid_t group_id, - cc_streamid_t stream_id, - cc_call_handle_t call_handle, - const char *peerconnection, - uint16_t level, - char **default_addrp, /* Out */ - int *default_portp, /* Out */ - char ***candidatesp, /* Out */ - int *candidate_ctp /* Out */ +static void vcmRxAllocICE_m(cc_mcapid_t mcap_id, + cc_groupid_t group_id, + cc_streamid_t stream_id, + cc_call_handle_t call_handle, + const char *peerconnection, + uint16_t level, + char **default_addrp, /* Out */ + int *default_portp, /* Out */ + char ***candidatesp, /* Out */ + int *candidate_ctp /* Out */ ) { *default_portp = -1; @@ -413,17 +433,11 @@ void vcmRxAllocICE(cc_mcapid_t mcap_id, // Note: we don't acquire any media resources here, and we assume that the // ICE streams already exist, so we're just acquiring them. Any logic // to make them on demand is elsewhere. - CSFLogDebug( logTag, "%s: acquiring peerconnection %s", __FUNCTION__, peerconnection); - mozilla::ScopedDeletePtr pc( - sipcc::PeerConnectionImpl::AcquireInstance(peerconnection)); - MOZ_ASSERT(pc); - if (!pc) { - CSFLogError(logTag, "%s: AcquireInstance returned NULL", __FUNCTION__); - return; - } + sipcc::PeerConnectionWrapper pc(peerconnection); + ENSURE_PC(pc, /**/); CSFLogDebug( logTag, "%s: Getting stream %d", __FUNCTION__, level); - mozilla::RefPtr stream = pc->impl()->media()-> + mozilla::RefPtr stream = pc.impl()->media()-> ice_media_stream(level-1); MOZ_ASSERT(stream); if (!stream) { @@ -465,6 +479,50 @@ void vcmRxAllocICE(cc_mcapid_t mcap_id, } +/** + * Gets the ICE parameters for a stream. Called "alloc" for style consistency + * + * This is a thunk to vcmRxAllocICE_m + * + * @param[in] group_id - group identifier to which stream belongs. + * @param[in] stream_id - stream identifier + * @param[in] call_handle - call identifier + * @param[in] peerconnection - the peerconnection in use + * @param[out] default_addrp - the ICE default addr + * @param[out] port_allocatedp - the ICE default port + * @param[out] candidatesp - the ICE candidate array + * @param[out] candidate_ctp length of the array + * + * @return void + * + */ +void vcmRxAllocICE(cc_mcapid_t mcap_id, + cc_groupid_t group_id, + cc_streamid_t stream_id, + cc_call_handle_t call_handle, + const char *peerconnection, + uint16_t level, + char **default_addrp, /* Out */ + int *default_portp, /* Out */ + char ***candidatesp, /* Out */ + int *candidate_ctp /* Out */ + ) +{ + VcmSIPCCBinding::getMainThread()->Dispatch( + WrapRunnableNM(&vcmRxAllocICE_m, + mcap_id, + group_id, + stream_id, + call_handle, + peerconnection, + level, + default_addrp, + default_portp, + candidatesp, + candidate_ctp), + NS_DISPATCH_SYNC); +} + /* Get ICE global parameters (ufrag and pwd) * @param[in] peerconnection - the peerconnection in use * @param[out] ufragp - where to put the ufrag @@ -472,7 +530,9 @@ void vcmRxAllocICE(cc_mcapid_t mcap_id, * * @return void */ -void vcmGetIceParams(const char *peerconnection, char **ufragp, char **pwdp) +static void vcmGetIceParams_m(const char *peerconnection, + char **ufragp, + char **pwdp) { CSFLogDebug( logTag, "%s: PC = %s", __FUNCTION__, peerconnection); @@ -481,15 +541,10 @@ void vcmGetIceParams(const char *peerconnection, char **ufragp, char **pwdp) // Note: we don't acquire any media resources here, and we assume that the // ICE streams already exist, so we're just acquiring them. Any logic // to make them on demand is elsewhere. - CSFLogDebug( logTag, "%s: acquiring peerconnection %s", __FUNCTION__, peerconnection); - mozilla::ScopedDeletePtr pc( - sipcc::PeerConnectionImpl::AcquireInstance(peerconnection)); - MOZ_ASSERT(pc); - if (!pc) { - return; - } + sipcc::PeerConnectionWrapper pc(peerconnection); + ENSURE_PC(pc, /**/); - std::vector attrs = pc->impl()->media()-> + std::vector attrs = pc.impl()->media()-> ice_ctx()->GetGlobalAttributes(); // Now fish through these looking for a ufrag and passwd @@ -530,6 +585,27 @@ void vcmGetIceParams(const char *peerconnection, char **ufragp, char **pwdp) return; } +/* Get ICE global parameters (ufrag and pwd) + * + * This is a thunk to vcmGetIceParams_m. + * + * @param[in] peerconnection - the peerconnection in use + * @param[out] ufragp - where to put the ufrag + * @param[out] pwdp - where to put the pwd + * + * @return void + */ +void vcmGetIceParams(const char *peerconnection, + char **ufragp, + char **pwdp) +{ + VcmSIPCCBinding::getMainThread()->Dispatch( + WrapRunnableNM(&vcmGetIceParams_m, + peerconnection, + ufragp, + pwdp), + NS_DISPATCH_SYNC); +} /* Set remote ICE global parameters. @@ -540,17 +616,14 @@ void vcmGetIceParams(const char *peerconnection, char **ufragp, char **pwdp) * * @return 0 success, error failure */ -short vcmSetIceSessionParams(const char *peerconnection, char *ufrag, char *pwd) +static short vcmSetIceSessionParams_m(const char *peerconnection, + char *ufrag, + char *pwd) { CSFLogDebug( logTag, "%s: PC = %s", __FUNCTION__, peerconnection); - CSFLogDebug( logTag, "%s: acquiring peerconnection %s", __FUNCTION__, peerconnection); - mozilla::ScopedDeletePtr pc( - sipcc::PeerConnectionImpl::AcquireInstance(peerconnection)); - MOZ_ASSERT(pc); - if (!pc) { - return VCM_ERROR; - } + sipcc::PeerConnectionWrapper pc(peerconnection); + ENSURE_PC(pc, VCM_ERROR); std::vector attributes; @@ -559,7 +632,7 @@ short vcmSetIceSessionParams(const char *peerconnection, char *ufrag, char *pwd) if (pwd) attributes.push_back(pwd); - nsresult res = pc->impl()->media()->ice_ctx()-> + nsresult res = pc.impl()->media()->ice_ctx()-> ParseGlobalAttributes(attributes); if (!NS_SUCCEEDED(res)) { @@ -570,6 +643,33 @@ short vcmSetIceSessionParams(const char *peerconnection, char *ufrag, char *pwd) return 0; } +/* Set remote ICE global parameters. + * + * This is a thunk to vcmSetIceSessionParams_m. + * + * @param[in] peerconnection - the peerconnection in use + * @param[in] ufrag - the ufrag + * @param[in] pwd - the pwd + * + * @return 0 success, error failure + */ +short vcmSetIceSessionParams(const char *peerconnection, + char *ufrag, + char *pwd) +{ + short ret; + + VcmSIPCCBinding::getMainThread()->Dispatch( + WrapRunnableNMRet(&vcmSetIceSessionParams_m, + peerconnection, + ufrag, + pwd, + &ret), + NS_DISPATCH_SYNC); + + return ret; +} + /* Set ice candidate for trickle ICE. * * @param[in] peerconnection - the peerconnection in use @@ -578,26 +678,23 @@ short vcmSetIceSessionParams(const char *peerconnection, char *ufrag, char *pwd) * * @return 0 success, error failure */ -short vcmSetIceCandidate(const char *peerconnection, const char *icecandidate, uint16_t level) +static short vcmSetIceCandidate_m(const char *peerconnection, + const char *icecandidate, + uint16_t level) { CSFLogDebug( logTag, "%s: PC = %s", __FUNCTION__, peerconnection); - CSFLogDebug( logTag, "%s: acquiring peerconnection %s", __FUNCTION__, peerconnection); - mozilla::ScopedDeletePtr pc( - sipcc::PeerConnectionImpl::AcquireInstance(peerconnection)); - MOZ_ASSERT(pc); - if (!pc) { - return VCM_ERROR; - } + sipcc::PeerConnectionWrapper pc(peerconnection); + ENSURE_PC(pc, VCM_ERROR); CSFLogDebug( logTag, "%s(): Getting stream %d", __FUNCTION__, level); - mozilla::RefPtr stream = pc->impl()->media()-> + mozilla::RefPtr stream = pc.impl()->media()-> ice_media_stream(level-1); if (!stream) return VCM_ERROR; nsresult res; - nsresult rv = pc->impl()->media()->ice_ctx()->thread()->Dispatch( + nsresult rv = pc.impl()->media()->ice_ctx()->thread()->Dispatch( WrapRunnableRet(stream, &NrIceMediaStream::ParseTrickleCandidate, icecandidate, &res), NS_DISPATCH_SYNC); @@ -614,25 +711,48 @@ short vcmSetIceCandidate(const char *peerconnection, const char *icecandidate, u return 0; } +/* Set ice candidate for trickle ICE. + * + * This is a thunk to vcmSetIceCandidate_m + * + * @param[in] peerconnection - the peerconnection in use + * @param[in] icecandidate - the icecandidate + * @param[in] level - the m line level + * + * @return 0 success, error failure + */ +short vcmSetIceCandidate(const char *peerconnection, + const char *icecandidate, + uint16_t level) +{ + short ret; + + VcmSIPCCBinding::getMainThread()->Dispatch( + WrapRunnableNMRet(&vcmSetIceCandidate_m, + peerconnection, + icecandidate, + level, + &ret), + NS_DISPATCH_SYNC); + + return ret; +} + + /* Start ICE checks * @param[in] peerconnection - the peerconnection in use * @return 0 success, error failure */ -short vcmStartIceChecks(const char *peerconnection) +static short vcmStartIceChecks_m(const char *peerconnection) { CSFLogDebug( logTag, "%s: PC = %s", __FUNCTION__, peerconnection); - CSFLogDebug( logTag, "%s: acquiring peerconnection %s", __FUNCTION__, peerconnection); - mozilla::ScopedDeletePtr pc( - sipcc::PeerConnectionImpl::AcquireInstance(peerconnection)); - MOZ_ASSERT(pc); - if (!pc) { - return VCM_ERROR; - } + sipcc::PeerConnectionWrapper pc(peerconnection); + ENSURE_PC(pc, VCM_ERROR); nsresult res; - nsresult rv = pc->impl()->media()->ice_ctx()->thread()->Dispatch( - WrapRunnableRet(pc->impl()->media()->ice_ctx(), &NrIceCtx::StartChecks, &res), + nsresult rv = pc.impl()->media()->ice_ctx()->thread()->Dispatch( + WrapRunnableRet(pc.impl()->media()->ice_ctx(), &NrIceCtx::StartChecks, &res), NS_DISPATCH_SYNC); if (!NS_SUCCEEDED(rv)) { @@ -649,6 +769,26 @@ short vcmStartIceChecks(const char *peerconnection) } +/* Start ICE checks + * + * This is a thunk to vcmStartIceChecks_m + * + * @param[in] peerconnection - the peerconnection in use + * @return 0 success, error failure + */ +short vcmStartIceChecks(const char *peerconnection) +{ + short ret; + + VcmSIPCCBinding::getMainThread()->Dispatch( + WrapRunnableNMRet(&vcmStartIceChecks_m, + peerconnection, + &ret), + NS_DISPATCH_SYNC); + + return ret; +} + /* Set remote ICE media-level parameters. * * @param[in] peerconnection - the peerconnection in use @@ -659,21 +799,20 @@ short vcmStartIceChecks(const char *peerconnection) * @param[i] candidate_ct - the number of candidates * @return 0 success, error failure */ -short vcmSetIceMediaParams(const char *peerconnection, int level, char *ufrag, char *pwd, - char **candidates, int candidate_ct) +static short vcmSetIceMediaParams_m(const char *peerconnection, + int level, + char *ufrag, + char *pwd, + char **candidates, + int candidate_ct) { CSFLogDebug( logTag, "%s: PC = %s", __FUNCTION__, peerconnection); - CSFLogDebug( logTag, "%s: acquiring peerconnection %s", __FUNCTION__, peerconnection); - mozilla::ScopedDeletePtr pc( - sipcc::PeerConnectionImpl::AcquireInstance(peerconnection)); - MOZ_ASSERT(pc); - if (!pc) { - return VCM_ERROR; - } + sipcc::PeerConnectionWrapper pc(peerconnection); + ENSURE_PC(pc, VCM_ERROR); CSFLogDebug( logTag, "%s(): Getting stream %d", __FUNCTION__, level); - mozilla::RefPtr stream = pc->impl()->media()-> + mozilla::RefPtr stream = pc.impl()->media()-> ice_media_stream(level-1); if (!stream) return VCM_ERROR; @@ -699,6 +838,42 @@ short vcmSetIceMediaParams(const char *peerconnection, int level, char *ufrag, c return 0; } +/* Set remote ICE media-level parameters. + * + * This is a thunk to vcmSetIceMediaParams_w + * + * @param[in] peerconnection - the peerconnection in use + * @param[in] level - the m-line + * @param[in] ufrag - the ufrag + * @param[in] pwd - the pwd + * @param[in] candidates - the candidates + * @param[i] candidate_ct - the number of candidates + * @return 0 success, error failure + */ +short vcmSetIceMediaParams(const char *peerconnection, + int level, + char *ufrag, + char *pwd, + char **candidates, + int candidate_ct) +{ + short ret; + + VcmSIPCCBinding::getMainThread()->Dispatch( + WrapRunnableNMRet(&vcmSetIceMediaParams_m, + peerconnection, + level, + ufrag, + pwd, + candidates, + candidate_ct, + &ret), + NS_DISPATCH_SYNC); + + return ret; +} + + /* * Create a remote stream * @@ -711,7 +886,7 @@ short vcmSetIceMediaParams(const char *peerconnection, int level, char *ufrag, c * * Returns: zero(0) for success; otherwise, ERROR for failure */ -short vcmCreateRemoteStream( +static short vcmCreateRemoteStream_m( cc_mcapid_t mcap_id, const char *peerconnection, int *pc_stream_id) { @@ -719,13 +894,8 @@ short vcmCreateRemoteStream( nsresult res; CSFLogDebug( logTag, "%s", __FUNCTION__); - - mozilla::ScopedDeletePtr pc( - sipcc::PeerConnectionImpl::AcquireInstance(peerconnection)); - MOZ_ASSERT(pc); - if (!pc) { - return VCM_ERROR; - } + sipcc::PeerConnectionWrapper pc(peerconnection); + ENSURE_PC(pc, VCM_ERROR); if (CC_IS_AUDIO(mcap_id)) { hints |= nsDOMMediaStream::HINT_CONTENTS_AUDIO; @@ -735,12 +905,12 @@ short vcmCreateRemoteStream( } sipcc::RemoteSourceStreamInfo* info; - res = pc->impl()->CreateRemoteSourceStreamInfo(hints, &info); + res = pc.impl()->CreateRemoteSourceStreamInfo(hints, &info); if (NS_FAILED(res)) { return VCM_ERROR; } - res = pc->impl()->media()->AddRemoteStream(info, pc_stream_id); + res = pc.impl()->media()->AddRemoteStream(info, pc_stream_id); if (NS_FAILED(res)) { return VCM_ERROR; } @@ -765,6 +935,37 @@ short vcmCreateRemoteStream( return 0; } +/* + * Create a remote stream + * + * This is a thunk to vcmCreateRemoteStream_m + * + * @param[in] mcap_id - group identifier to which stream belongs. + * @param[in] peerconnection - the peerconnection in use + * @param[out] pc_stream_id - the id of the allocated stream + * + * TODO(ekr@rtfm.com): Revise along with everything else for the + * new stream model. + * + * Returns: zero(0) for success; otherwise, ERROR for failure + */ +short vcmCreateRemoteStream(cc_mcapid_t mcap_id, + const char *peerconnection, + int *pc_stream_id) +{ + short ret; + + VcmSIPCCBinding::getMainThread()->Dispatch( + WrapRunnableNMRet(&vcmCreateRemoteStream_m, + mcap_id, + peerconnection, + pc_stream_id, + &ret), + NS_DISPATCH_SYNC); + + return ret; +} + /* * Get DTLS key data @@ -777,23 +978,18 @@ short vcmCreateRemoteStream( * * Returns: zero(0) for success; otherwise, ERROR for failure */ -short vcmGetDtlsIdentity(const char *peerconnection, - char *digest_algp, - size_t max_digest_alg_len, - char *digestp, - size_t max_digest_len) { - CSFLogDebug( logTag, "%s: acquiring peerconnection %s", __FUNCTION__, peerconnection); - mozilla::ScopedDeletePtr pc( - sipcc::PeerConnectionImpl::AcquireInstance(peerconnection)); - MOZ_ASSERT(pc); - if (!pc) { - return VCM_ERROR; - } +static short vcmGetDtlsIdentity_m(const char *peerconnection, + char *digest_algp, + size_t max_digest_alg_len, + char *digestp, + size_t max_digest_len) { + sipcc::PeerConnectionWrapper pc(peerconnection); + ENSURE_PC(pc, VCM_ERROR); unsigned char digest[TransportLayerDtls::kMaxDigestLength]; size_t digest_len; - nsresult res = pc->impl()->GetIdentity()->ComputeFingerprint("sha-256", digest, + nsresult res = pc.impl()->GetIdentity()->ComputeFingerprint("sha-256", digest, sizeof(digest), &digest_len); if (!NS_SUCCEEDED(res)) { @@ -816,6 +1012,39 @@ short vcmGetDtlsIdentity(const char *peerconnection, return 0; } +/* + * Get DTLS key data + * + * This is a thunk to vcmGetDtlsIdentity_m + * + * @param[in] peerconnection - the peerconnection in use + * @param[out] digest_algp - the digest algorithm e.g. 'SHA-1' + * @param[in] max_digest_alg_len - length of string + * @param[out] digestp - the digest string + * @param[in] max_digest_len - length of string + * + * Returns: zero(0) for success; otherwise, ERROR for failure + */ +short vcmGetDtlsIdentity(const char *peerconnection, + char *digest_algp, + size_t max_digest_alg_len, + char *digestp, + size_t max_digest_len) { + short ret; + + VcmSIPCCBinding::getMainThread()->Dispatch( + WrapRunnableNMRet(&vcmGetDtlsIdentity_m, + peerconnection, + digest_algp, + max_digest_alg_len, + digestp, + max_digest_len, + &ret), + NS_DISPATCH_SYNC); + + return ret; +} + /* Set negotiated DataChannel parameters. * * @param[in] peerconnection - the peerconnection in use @@ -829,15 +1058,6 @@ short vcmSetDataChannelParameters(const char *peerconnection, cc_uint16_t stream { CSFLogDebug( logTag, "%s: PC = %s", __FUNCTION__, peerconnection); - CSFLogDebug( logTag, "%s: acquiring peerconnection %s", __FUNCTION__, peerconnection); - mozilla::ScopedDeletePtr pc( - sipcc::PeerConnectionImpl::AcquireInstance(peerconnection)); - PR_ASSERT(pc); - if (!pc) { - return VCM_ERROR; - } - - return 0; } @@ -1030,7 +1250,7 @@ int vcmRxStart(cc_mcapid_t mcap_id, * Returns: zero(0) for success; otherwise, ERROR for failure */ -int vcmRxStartICE(cc_mcapid_t mcap_id, +static int vcmRxStartICE_m(cc_mcapid_t mcap_id, cc_groupid_t group_id, cc_streamid_t stream_id, int level, @@ -1046,13 +1266,9 @@ int vcmRxStartICE(cc_mcapid_t mcap_id, { CSFLogDebug( logTag, "%s(%s)", __FUNCTION__, peerconnection); - // Find the PC and get the stream - mozilla::ScopedDeletePtr pc( - sipcc::PeerConnectionImpl::AcquireInstance(peerconnection)); - PR_ASSERT(pc); - if (!pc) { - return VCM_ERROR; - } + // Find the PC. + sipcc::PeerConnectionWrapper pc(peerconnection); + ENSURE_PC(pc, VCM_ERROR); if(!payloads) { CSFLogError( logTag, "Unitialized payload list"); @@ -1061,7 +1277,7 @@ int vcmRxStartICE(cc_mcapid_t mcap_id, // Find the stream we need nsRefPtr stream = - pc->impl()->media()->GetRemoteStream(pc_stream_id); + pc.impl()->media()->GetRemoteStream(pc_stream_id); if (!stream) { // This should never happen PR_ASSERT(PR_FALSE); @@ -1069,14 +1285,14 @@ int vcmRxStartICE(cc_mcapid_t mcap_id, } // Create the transport flows mozilla::RefPtr rtp_flow = - vcmCreateTransportFlow(pc->impl(), level, false, + vcmCreateTransportFlow(pc.impl(), level, false, fingerprint_alg, fingerprint); if (!rtp_flow) { CSFLogError( logTag, "Could not create RTP flow"); return VCM_ERROR; } mozilla::RefPtr rtcp_flow = - vcmCreateTransportFlow(pc->impl(), level, true, + vcmCreateTransportFlow(pc.impl(), level, true, fingerprint_alg, fingerprint); if (!rtcp_flow) { CSFLogError( logTag, "Could not create RTCP flow"); @@ -1111,8 +1327,8 @@ int vcmRxStartICE(cc_mcapid_t mcap_id, // Now we have all the pieces, create the pipeline stream->StorePipeline(pc_track_id, new mozilla::MediaPipelineReceiveAudio( - pc->impl()->GetMainThread().get(), - pc->impl()->GetSTSThread(), + pc.impl()->GetMainThread().get(), + pc.impl()->GetSTSThread(), stream->GetMediaStream(), conduit, rtp_flow, rtcp_flow)); @@ -1143,8 +1359,8 @@ int vcmRxStartICE(cc_mcapid_t mcap_id, // Now we have all the pieces, create the pipeline stream->StorePipeline(pc_track_id, new mozilla::MediaPipelineReceiveVideo( - pc->impl()->GetMainThread().get(), - pc->impl()->GetSTSThread(), + pc.impl()->GetMainThread().get(), + pc.impl()->GetSTSThread(), stream->GetMediaStream(), conduit, rtp_flow, rtcp_flow)); @@ -1158,6 +1374,67 @@ int vcmRxStartICE(cc_mcapid_t mcap_id, } +/** + * start rx stream + * Same concept as vcmRxStart but for ICE/PeerConnection-based flows + * + * This is a thunk to vcmRxStartICE_m + * + * @param[in] mcap_id - media cap id + * @param[in] group_id - group identifier to which the stream belongs + * @param[in] stream_id - stream id of the given media type. + * @param[in] level - the m-line index + * @param[in] pc_stream_id - the media stream index (from PC.addStream()) + * @param[i]n pc_track_id - the track within the media stream + * @param[in] call_handle - call handle + * @param[in] peerconnection - the peerconnection in use + * @param[in] num_payloads - number of negotiated payloads + * @param[in] payloads - negotiated codec details list + * @param[in] fingerprint_alg - the DTLS fingerprint algorithm + * @param[in] fingerprint - the DTLS fingerprint + * @param[in] attrs - media attributes + * + * Returns: zero(0) for success; otherwise, ERROR for failure + */ + +int vcmRxStartICE(cc_mcapid_t mcap_id, + cc_groupid_t group_id, + cc_streamid_t stream_id, + int level, + int pc_stream_id, + int pc_track_id, + cc_call_handle_t call_handle, + const char *peerconnection, + int num_payloads, + const vcm_payload_info_t* payloads, + const char *fingerprint_alg, + const char *fingerprint, + vcm_mediaAttrs_t *attrs) +{ + int ret; + + VcmSIPCCBinding::getMainThread()->Dispatch( + WrapRunnableNMRet(&vcmRxStartICE_m, + mcap_id, + group_id, + stream_id, + level, + pc_stream_id, + pc_track_id, + call_handle, + peerconnection, + num_payloads, + payloads, + fingerprint_alg, + fingerprint, + attrs, + &ret), + NS_DISPATCH_SYNC); + + return ret; +} + + /** * Close the receive stream. * @@ -1596,7 +1873,7 @@ int vcmTxStart(cc_mcapid_t mcap_id, */ #define EXTRACT_DYNAMIC_PAYLOAD_TYPE(PTYPE) ((PTYPE)>>16) -int vcmTxStartICE(cc_mcapid_t mcap_id, +static int vcmTxStartICE_m(cc_mcapid_t mcap_id, cc_groupid_t group_id, cc_streamid_t stream_id, int level, @@ -1613,25 +1890,21 @@ int vcmTxStartICE(cc_mcapid_t mcap_id, CSFLogDebug( logTag, "%s(%s)", __FUNCTION__, peerconnection); // Find the PC and get the stream - mozilla::ScopedDeletePtr pc( - sipcc::PeerConnectionImpl::AcquireInstance(peerconnection)); - PR_ASSERT(pc); - if (!pc) { - return VCM_ERROR; - } - nsRefPtr stream = pc->impl()->media()-> + sipcc::PeerConnectionWrapper pc(peerconnection); + ENSURE_PC(pc, VCM_ERROR); + nsRefPtr stream = pc.impl()->media()-> GetLocalStream(pc_stream_id); // Create the transport flows mozilla::RefPtr rtp_flow = - vcmCreateTransportFlow(pc->impl(), level, false, + vcmCreateTransportFlow(pc.impl(), level, false, fingerprint_alg, fingerprint); if (!rtp_flow) { CSFLogError( logTag, "Could not create RTP flow"); return VCM_ERROR; } mozilla::RefPtr rtcp_flow = - vcmCreateTransportFlow(pc->impl(), level, true, + vcmCreateTransportFlow(pc.impl(), level, true, fingerprint_alg, fingerprint); if (!rtcp_flow) { CSFLogError( logTag, "Could not create RTCP flow"); @@ -1660,8 +1933,8 @@ int vcmTxStartICE(cc_mcapid_t mcap_id, mozilla::RefPtr pipeline = new mozilla::MediaPipelineTransmit( - pc->impl()->GetMainThread().get(), - pc->impl()->GetSTSThread(), + pc.impl()->GetMainThread().get(), + pc.impl()->GetSTSThread(), stream->GetMediaStream(), conduit, rtp_flow, rtcp_flow); @@ -1693,8 +1966,8 @@ int vcmTxStartICE(cc_mcapid_t mcap_id, // Create the pipeline mozilla::RefPtr pipeline = new mozilla::MediaPipelineTransmit( - pc->impl()->GetMainThread().get(), - pc->impl()->GetSTSThread(), + pc.impl()->GetMainThread().get(), + pc.impl()->GetSTSThread(), stream->GetMediaStream(), conduit, rtp_flow, rtcp_flow); @@ -1712,6 +1985,68 @@ int vcmTxStartICE(cc_mcapid_t mcap_id, return 0; } +/** + * start tx stream + * Same concept as vcmTxStart but for ICE/PeerConnection-based flows + * + * This is a thunk to vcmTxStartICE_m + * + * @param[in] mcap_id - media cap id + * @param[in] group_id - group identifier to which the stream belongs + * @param[in] stream_id - stream id of the given media type. + * @param[in] level - the m-line index + * @param[in] pc_stream_id - the media stream index (from PC.addStream()) + * @param[i]n pc_track_id - the track within the media stream + * @param[in] call_handle - call handle + * @param[in] peerconnection - the peerconnection in use + * @param[in] payload - payload type + * @param[in] tos - bit marking + * @param[in] fingerprint_alg - the DTLS fingerprint algorithm + * @param[in] fingerprint - the DTLS fingerprint + * @param[in] attrs - media attributes + * + * Returns: zero(0) for success; otherwise, ERROR for failure + * + */ +#define EXTRACT_DYNAMIC_PAYLOAD_TYPE(PTYPE) ((PTYPE)>>16) + +int vcmTxStartICE(cc_mcapid_t mcap_id, + cc_groupid_t group_id, + cc_streamid_t stream_id, + int level, + int pc_stream_id, + int pc_track_id, + cc_call_handle_t call_handle, + const char *peerconnection, + const vcm_payload_info_t *payload, + short tos, + const char *fingerprint_alg, + const char *fingerprint, + vcm_mediaAttrs_t *attrs) +{ + int ret; + + VcmSIPCCBinding::getMainThread()->Dispatch( + WrapRunnableNMRet(&vcmTxStartICE_m, + mcap_id, + group_id, + stream_id, + level, + pc_stream_id, + pc_track_id, + call_handle, + peerconnection, + payload, + tos, + fingerprint_alg, + fingerprint, + attrs, + &ret), + NS_DISPATCH_SYNC); + + return ret; +} + /** * Close the transmit stream diff --git a/media/webrtc/signaling/src/media/VcmSIPCCBinding.h b/media/webrtc/signaling/src/media/VcmSIPCCBinding.h index 678413ccd65..4167e022730 100644 --- a/media/webrtc/signaling/src/media/VcmSIPCCBinding.h +++ b/media/webrtc/signaling/src/media/VcmSIPCCBinding.h @@ -10,6 +10,8 @@ extern "C" #include "ccapi_types.h" } +class nsIThread; + namespace CSF { class AudioTermination; @@ -53,12 +55,16 @@ namespace CSF static int getAudioCodecs(); static int getVideoCodecs(); + static void setMainThread(nsIThread *thread); + static nsIThread *getMainThread(); + private: - static VcmSIPCCBinding * _pSelf; + static VcmSIPCCBinding * gSelf; StreamObserver* streamObserver; MediaProviderObserver *mediaProviderObserver; - static int mAudioCodecMask; - static int mVideoCodecMask; + static int gAudioCodecMask; + static int gVideoCodecMask; + static nsIThread *gMainThread; }; } diff --git a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp index f6396715256..b8c90101bf8 100644 --- a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp +++ b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp @@ -442,10 +442,13 @@ nsresult MediaPipelineTransmit::Init() { "audio" : "video") << " hints=" << stream_->GetHintContents()); - return RUN_ON_THREAD(main_thread_, WrapRunnable(stream_->GetStream(), + // Force this to be a refptr so that we are holding a strong reference + // to the media stream. + nsRefPtr stream (stream_->GetStream()); + return RUN_ON_THREAD(main_thread_, WrapRunnable(stream, &MediaStream::AddListener, listener_), - NS_DISPATCH_SYNC); + NS_DISPATCH_NORMAL); } nsresult MediaPipeline::PipelineTransport::SendRtpPacket( @@ -665,10 +668,14 @@ void MediaPipelineTransmit::ProcessVideoChunk(VideoSessionConduit *conduit, nsresult MediaPipelineReceiveAudio::Init() { MOZ_MTLOG(PR_LOG_DEBUG, __FUNCTION__); - return RUN_ON_THREAD(main_thread_, WrapRunnable(stream_->GetStream(), - &MediaStream::AddListener, - listener_), - NS_DISPATCH_SYNC); + + // Force this to be a refptr so that we are holding a strong reference + // to the media stream. + nsRefPtr stream (stream_->GetStream()); + return RUN_ON_THREAD(main_thread_, WrapRunnable(stream, + &MediaStream::AddListener, + listener_), + NS_DISPATCH_NORMAL); } void MediaPipelineReceiveAudio::PipelineListener:: diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.cpp b/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.cpp index 4e2ad32d00c..974905d845b 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.cpp +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.cpp @@ -13,39 +13,64 @@ #include "CC_SIPCCDeviceInfo.h" #include "CSFLog.h" #include "vcm.h" +#include "VcmSIPCCBinding.h" #include "PeerConnectionImpl.h" #include "PeerConnectionCtx.h" +#include "runnable_utils.h" #include "cpr_socket.h" static const char* logTag = "PeerConnectionCtx"; namespace sipcc { -PeerConnectionCtx* PeerConnectionCtx::instance; +PeerConnectionCtx* PeerConnectionCtx::gInstance; +nsIThread* PeerConnectionCtx::gMainThread; + +nsresult PeerConnectionCtx::InitializeGlobal(nsIThread *mainThread) { + if (!gMainThread) { + gMainThread = mainThread; + CSF::VcmSIPCCBinding::setMainThread(gMainThread); + } else { + MOZ_ASSERT(gMainThread == mainThread); + } + bool on; + + nsresult res; + +#ifdef MOZILLA_INTERNAL_API + // This check fails on the unit tests because they do not + // have the right thread behavior. + res = gMainThread->IsOnCurrentThread(&on); + NS_ENSURE_SUCCESS(res, res); + MOZ_ASSERT(on); +#endif + + if (!gInstance) { + CSFLogDebug(logTag, "Creating PeerConnectionCtx"); + PeerConnectionCtx *ctx = new PeerConnectionCtx(); + + res = ctx->Initialize(); + PR_ASSERT(NS_SUCCEEDED(res)); + if (!NS_SUCCEEDED(res)) + return res; + + gInstance = ctx; + } + + return NS_OK; +} PeerConnectionCtx* PeerConnectionCtx::GetInstance() { - if (instance) - return instance; - - CSFLogDebug(logTag, "Creating PeerConnectionCtx"); - PeerConnectionCtx *ctx = new PeerConnectionCtx(); - - nsresult res = ctx->Initialize(); - PR_ASSERT(NS_SUCCEEDED(res)); - if (!NS_SUCCEEDED(res)) - return NULL; - - instance = ctx; - - return instance; + MOZ_ASSERT(gInstance); + return gInstance; } void PeerConnectionCtx::Destroy() { CSFLogDebug(logTag, "%s", __FUNCTION__); - instance->Cleanup(); - delete instance; - instance = NULL; + gInstance->Cleanup(); + delete gInstance; + gInstance = NULL; } nsresult PeerConnectionCtx::Initialize() { @@ -118,20 +143,34 @@ void PeerConnectionCtx::onDeviceEvent(ccapi_device_event_e aDeviceEvent, } } -// Demux the call event to the right PeerConnection void PeerConnectionCtx::onCallEvent(ccapi_call_event_e aCallEvent, - CSF::CC_CallPtr aCall, - CSF::CC_CallInfoPtr aInfo) { - CSFLogDebug(logTag, "onCallEvent()"); - mozilla::ScopedDeletePtr pc( - PeerConnectionImpl::AcquireInstance( - aCall->getPeerConnection())); + CSF::CC_CallPtr aCall, + CSF::CC_CallInfoPtr aInfo) { + // This is called on a SIPCC thread. + // WARNING: Do not make this NS_DISPATCH_NORMAL. + // CC_*Ptr is not thread-safe so we must not manipulate + // the ref count on multiple threads at once. + // NS_DISPATCH_SYNC enforces this and because this is + // not a real nsThread, we don't have to worry about + // reentrancy. + RUN_ON_THREAD(gMainThread, + WrapRunnable(this, + &PeerConnectionCtx::onCallEvent_m, + aCallEvent, aCall, aInfo), + NS_DISPATCH_SYNC); +} - if (!pc) // This must be an event on a dead PC. Ignore +// Demux the call event to the right PeerConnection +void PeerConnectionCtx::onCallEvent_m(ccapi_call_event_e aCallEvent, + CSF::CC_CallPtr aCall, + CSF::CC_CallInfoPtr aInfo) { + CSFLogDebug(logTag, "onCallEvent()"); + PeerConnectionWrapper pc(aCall->getPeerConnection()); + if (!pc.impl()) // This must be an event on a dead PC. Ignore return; CSFLogDebug(logTag, "Calling PC"); - pc->impl()->onCallEvent(aCallEvent, aCall, aInfo); + pc.impl()->onCallEvent(aCallEvent, aCall, aInfo); } } // namespace sipcc diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.h b/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.h index e8ef9de1e03..cb50690b309 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.h +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.h @@ -17,12 +17,14 @@ namespace sipcc { -// Currently SIPCC only allows a single stack instance to exist in a process -// at once. This class implements a singleton object that wraps that -// instance. It also hosts the observer class that demuxes events onto -// individual PCs. +// A class to hold some of the singleton objects we need: +// * The global PeerConnectionImpl table and its associated lock. +// * Currently SIPCC only allows a single stack instance to exist in a process +// at once. This class implements a singleton object that wraps that. +// * The observer class that demuxes events onto individual PCs. class PeerConnectionCtx : public CSF::CC_Observer { public: + static nsresult InitializeGlobal(nsIThread *mainThread); static PeerConnectionCtx* GetInstance(); static void Destroy(); @@ -37,7 +39,14 @@ class PeerConnectionCtx : public CSF::CC_Observer { PeerConnectionImpl::SipccState sipcc_state() { return mSipccState; } + // Make these classes friend so that they can access mPeerconnections. + friend class PeerConnectionImpl; + friend class PeerConnectionWrapper; + private: + // We could make these available only via accessors but it's too much trouble. + std::map mPeerConnections; + PeerConnectionCtx() : mSipccState(PeerConnectionImpl::kIdle), mCCM(NULL), mDevice(NULL) {} // This is a singleton, so don't copy construct it, etc. @@ -52,12 +61,17 @@ class PeerConnectionCtx : public CSF::CC_Observer { mSipccState = aState; } + virtual void onCallEvent_m(ccapi_call_event_e callEvent, + CSF::CC_CallPtr call, + CSF::CC_CallInfoPtr info); + // SIPCC objects PeerConnectionImpl::SipccState mSipccState; // TODO(ekr@rtfm.com): refactor this out? What does it do? CSF::CallControlManagerPtr mCCM; CSF::CC_DevicePtr mDevice; - static PeerConnectionCtx *instance; + static PeerConnectionCtx *gInstance; + static nsIThread *gMainThread; }; } // namespace sipcc diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp index 063df524e55..ac49b8a9e12 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp @@ -106,162 +106,104 @@ void MediaConstraints::buildArray(cc_media_constraints_t** constraintarray) { (*constraintarray)->constraint_count = i; } -typedef enum { - PC_OBSERVER_CALLBACK, - PC_OBSERVER_CONNECTION, - PC_OBSERVER_CLOSEDCONNECTION, - PC_OBSERVER_DATACHANNEL, - PC_OBSERVER_ICE, - PC_OBSERVER_READYSTATE -} PeerConnectionObserverType; - -// TODO: Refactor this. class PeerConnectionObserverDispatch : public nsRunnable { public: PeerConnectionObserverDispatch(CSF::CC_CallInfoPtr aInfo, nsRefPtr aPC, - IPeerConnectionObserver* aObserver) : - mType(PC_OBSERVER_CALLBACK), mInfo(aInfo), mChannel(nullptr), mPC(aPC), mObserver(aObserver) {} - - PeerConnectionObserverDispatch(PeerConnectionObserverType aType, - nsRefPtr aChannel, - nsRefPtr aPC, - IPeerConnectionObserver* aObserver) : - mType(aType), mInfo(nullptr), mChannel(aChannel), mPC(aPC), mObserver(aObserver) {} - - PeerConnectionObserverDispatch(PeerConnectionObserverType aType, - nsRefPtr aPC, - IPeerConnectionObserver* aObserver) : - mType(aType), mInfo(nullptr), mPC(aPC), mObserver(aObserver) {} + IPeerConnectionObserver* aObserver) + : mPC(aPC), + mObserver(aObserver), + mCode(static_cast(aInfo->getStatusCode())), + mSdpStr(), + mCallState(aInfo->getCallState()), + mStateStr(aInfo->callStateToString(mCallState)) { + if (mCallState == REMOTESTREAMADD) { + MediaStreamTable *streams = NULL; + streams = aInfo->getMediaStreams(); + mRemoteStream = mPC->media()->GetRemoteStream(streams->media_stream_id); + MOZ_ASSERT(mRemoteStream); + } + if ((mCallState == CREATEOFFER) || (mCallState == CREATEANSWER)) { + mSdpStr = aInfo->getSDP(); + } + } ~PeerConnectionObserverDispatch(){} - NS_IMETHOD Run() - { - switch (mType) { - case PC_OBSERVER_CALLBACK: + NS_IMETHOD Run() { + switch (mCallState) { + case CREATEOFFER: + mObserver->OnCreateOfferSuccess(mSdpStr.c_str()); + break; + + case CREATEANSWER: + mObserver->OnCreateAnswerSuccess(mSdpStr.c_str()); + break; + + case CREATEOFFERERROR: + mObserver->OnCreateOfferError(mCode); + break; + + case CREATEANSWERERROR: + mObserver->OnCreateAnswerError(mCode); + break; + + case SETLOCALDESC: + mObserver->OnSetLocalDescriptionSuccess(mCode); + break; + + case SETREMOTEDESC: + mObserver->OnSetRemoteDescriptionSuccess(mCode); + break; + + case SETLOCALDESCERROR: + mObserver->OnSetLocalDescriptionError(mCode); + break; + + case SETREMOTEDESCERROR: + mObserver->OnSetRemoteDescriptionError(mCode); + break; + + case REMOTESTREAMADD: { - StatusCode code; - std::string s_sdpstr; - MediaStreamTable *streams = NULL; - - cc_call_state_t state = mInfo->getCallState(); - std::string statestr = mInfo->callStateToString(state); - nsDOMMediaStream* stream; uint32_t hint; - switch (state) { - case CREATEOFFER: - s_sdpstr = mInfo->getSDP(); - mObserver->OnCreateOfferSuccess(s_sdpstr.c_str()); - break; - - case CREATEANSWER: - s_sdpstr = mInfo->getSDP(); - mObserver->OnCreateAnswerSuccess(s_sdpstr.c_str()); - break; - - case CREATEOFFERERROR: - code = (StatusCode)mInfo->getStatusCode(); - mObserver->OnCreateOfferError(code); - break; - - case CREATEANSWERERROR: - code = (StatusCode)mInfo->getStatusCode(); - mObserver->OnCreateAnswerError(code); - break; - - case SETLOCALDESC: - code = (StatusCode)mInfo->getStatusCode(); - mObserver->OnSetLocalDescriptionSuccess(code); - break; - - case SETREMOTEDESC: - code = (StatusCode)mInfo->getStatusCode(); - mObserver->OnSetRemoteDescriptionSuccess(code); - break; - - case SETLOCALDESCERROR: - code = (StatusCode)mInfo->getStatusCode(); - mObserver->OnSetLocalDescriptionError(code); - break; - - case SETREMOTEDESCERROR: - code = (StatusCode)mInfo->getStatusCode(); - mObserver->OnSetRemoteDescriptionError(code); - break; - - case REMOTESTREAMADD: - { - streams = mInfo->getMediaStreams(); - nsRefPtr remoteStream = mPC->media()-> - GetRemoteStream(streams->media_stream_id); - - MOZ_ASSERT(remoteStream); - if (!remoteStream) - { - CSFLogErrorS(logTag, __FUNCTION__ << " GetRemoteStream returned NULL"); - } - else - { - stream = remoteStream->GetMediaStream(); - hint = stream->GetHintContents(); - if (hint == nsDOMMediaStream::HINT_CONTENTS_AUDIO) { - mObserver->OnAddStream(stream, "audio"); - } else if (hint == nsDOMMediaStream::HINT_CONTENTS_VIDEO) { - mObserver->OnAddStream(stream, "video"); - } else { - CSFLogErrorS(logTag, __FUNCTION__ << "Audio & Video not supported"); - MOZ_ASSERT(PR_FALSE); - } - } - break; + if (!mRemoteStream) { + CSFLogErrorS(logTag, __FUNCTION__ << " GetRemoteStream returned NULL"); + } else { + stream = mRemoteStream->GetMediaStream(); + hint = stream->GetHintContents(); + if (hint == nsDOMMediaStream::HINT_CONTENTS_AUDIO) { + mObserver->OnAddStream(stream, "audio"); + } else if (hint == nsDOMMediaStream::HINT_CONTENTS_VIDEO) { + mObserver->OnAddStream(stream, "video"); + } else { + CSFLogErrorS(logTag, __FUNCTION__ << "Audio & Video not supported"); + MOZ_ASSERT(PR_FALSE); } - default: - CSFLogDebugS(logTag, ": **** UNHANDLED CALL STATE : " << statestr); - break; } break; } - case PC_OBSERVER_CONNECTION: - CSFLogDebugS(logTag, __FUNCTION__ << ": Delivering PeerConnection onconnection"); - mObserver->NotifyConnection(); + default: + CSFLogDebugS(logTag, ": **** UNHANDLED CALL STATE : " << mStateStr); break; - case PC_OBSERVER_CLOSEDCONNECTION: - CSFLogDebugS(logTag, __FUNCTION__ << ": Delivering PeerConnection onclosedconnection"); - mObserver->NotifyClosedConnection(); - break; - case PC_OBSERVER_DATACHANNEL: - CSFLogDebugS(logTag, __FUNCTION__ << ": Delivering PeerConnection ondatachannel"); - mObserver->NotifyDataChannel(mChannel); -#ifdef MOZILLA_INTERNAL_API - NS_DataChannelAppReady(mChannel); -#endif - break; - case PC_OBSERVER_ICE: - CSFLogDebugS(logTag, __FUNCTION__ << ": Delivering PeerConnection ICE callback "); - mObserver->OnStateChange(IPeerConnectionObserver::kIceState); - break; - case PC_OBSERVER_READYSTATE: - CSFLogDebugS(logTag, __FUNCTION__ << ": Delivering PeerConnection Ready State callback "); - mObserver->OnStateChange(IPeerConnectionObserver::kReadyState); } + return NS_OK; } private: - PeerConnectionObserverType mType; - CSF::CC_CallInfoPtr mInfo; - nsRefPtr mChannel; nsRefPtr mPC; nsCOMPtr mObserver; + StatusCode mCode; + std::string mSdpStr; + cc_call_state_t mCallState; + std::string mStateStr; + nsRefPtr mRemoteStream; }; -std::map - PeerConnectionImpl::peerconnections; - NS_IMPL_THREADSAFE_ISUPPORTS1(PeerConnectionImpl, IPeerConnection) PeerConnectionImpl::PeerConnectionImpl() @@ -273,19 +215,27 @@ PeerConnectionImpl::PeerConnectionImpl() , mWindow(NULL) , mIdentity(NULL) , mSTSThread(NULL) - , mMedia(new PeerConnectionMedia(this)) - {} + , mMedia(new PeerConnectionMedia(this)) { + MOZ_ASSERT(NS_IsMainThread()); +} PeerConnectionImpl::~PeerConnectionImpl() { - Close(false); + PC_AUTO_ENTER_API_CALL_NO_CHECK(); + PeerConnectionCtx::GetInstance()->mPeerConnections.erase(mHandle); + CloseInt(false); + +#if 0 + // TODO(ekr@rtfm.com): figure out how to shut down PCCtx. + // bug 820011. + // Since this and Initialize() occur on MainThread, they can't both be // running at once // Might be more optimal to release off a timer (and XPCOM Shutdown) // to avoid churn - peerconnections.erase(mHandle); - if (peerconnections.empty()) + if (PeerConnectionCtx::GetInstance()->mPeerConnections.empty()) Shutdown(); +#endif /* We should release mPCObserver on the main thread, but also prevent a double free. nsCOMPtr mainThread; @@ -303,8 +253,7 @@ PeerConnectionImpl::MakeMediaStream(uint32_t aHint, nsIDOMMediaStream** aRetval) nsRefPtr stream = nsDOMMediaStream::CreateSourceStream(aHint); NS_ADDREF(*aRetval = stream); - CSFLogDebugS(logTag, "PeerConnection " << static_cast(this) - << ": Created media stream " << static_cast(stream) + CSFLogDebugS(logTag, "Created media stream " << static_cast(stream) << " inner: " << static_cast(stream->GetStream())); return NS_OK; @@ -326,18 +275,11 @@ nsresult PeerConnectionImpl::CreateRemoteSourceStreamInfo(uint32_t aHint, RemoteSourceStreamInfo** aInfo) { MOZ_ASSERT(aInfo); + PC_AUTO_ENTER_API_CALL_NO_CHECK(); nsIDOMMediaStream* stream; - - nsresult res; - if (!mThread || NS_IsMainThread()) { - res = MakeMediaStream(aHint, &stream); - } else { - mThread->Dispatch(WrapRunnableRet( - this, &PeerConnectionImpl::MakeMediaStream, aHint, &stream, &res - ), NS_DISPATCH_SYNC); - } - + + nsresult res = MakeMediaStream(aHint, &stream); if (NS_FAILED(res)) { return res; } @@ -352,8 +294,8 @@ PeerConnectionImpl::CreateRemoteSourceStreamInfo(uint32_t aHint, RemoteSourceStr return NS_OK; } - mThread->Dispatch(WrapRunnableRet( - this, &PeerConnectionImpl::MakeRemoteSource, comstream, aInfo, &res + mThread->Dispatch(WrapRunnableNMRet( + &PeerConnectionImpl::MakeRemoteSource, comstream, aInfo, &res ), NS_DISPATCH_SYNC); if (NS_FAILED(res)) { @@ -369,6 +311,7 @@ PeerConnectionImpl::Initialize(IPeerConnectionObserver* aObserver, nsIThread* aThread) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aObserver); + MOZ_ASSERT(aThread); mPCObserver = aObserver; nsresult res; @@ -379,6 +322,8 @@ PeerConnectionImpl::Initialize(IPeerConnectionObserver* aObserver, NS_ENSURE_SUCCESS(res, res); #endif + mThread = aThread; + #ifdef MOZILLA_INTERNAL_API // Currently no standalone unit tests for DataChannel, // which is the user of mWindow @@ -387,8 +332,8 @@ PeerConnectionImpl::Initialize(IPeerConnectionObserver* aObserver, NS_ENSURE_STATE(mWindow); #endif - // The thread parameter can be passed in as NULL - mThread = aThread; + res = PeerConnectionCtx::InitializeGlobal(mThread); + NS_ENSURE_SUCCESS(res, res); PeerConnectionCtx *pcctx = PeerConnectionCtx::GetInstance(); MOZ_ASSERT(pcctx); @@ -429,7 +374,7 @@ PeerConnectionImpl::Initialize(IPeerConnectionObserver* aObserver, // Store under mHandle mCall->setPeerConnection(mHandle); - peerconnections[mHandle] = this; + PeerConnectionCtx::GetInstance()->mPeerConnections[mHandle] = this; // Create the DTLS Identity mIdentity = DtlsIdentity::Generate(); @@ -481,6 +426,7 @@ nsresult PeerConnectionImpl::CreateFakeMediaStream(uint32_t aHint, nsIDOMMediaStream** aRetval) { MOZ_ASSERT(aRetval); + PC_AUTO_ENTER_API_CALL(false); bool mute = false; @@ -494,8 +440,8 @@ PeerConnectionImpl::CreateFakeMediaStream(uint32_t aHint, nsIDOMMediaStream** aR if (!mThread || NS_IsMainThread()) { res = MakeMediaStream(aHint, aRetval); } else { - mThread->Dispatch(WrapRunnableRet( - this, &PeerConnectionImpl::MakeMediaStream, aHint, aRetval, &res + mThread->Dispatch(WrapRunnableNMRet( + &PeerConnectionImpl::MakeMediaStream, aHint, aRetval, &res ), NS_DISPATCH_SYNC); } @@ -524,6 +470,8 @@ PeerConnectionImpl::ConnectDataConnection(uint16_t aLocalport, uint16_t aRemoteport, uint16_t aNumstreams) { + PC_AUTO_ENTER_API_CALL_NO_CHECK(); + #ifdef MOZILLA_INTERNAL_API mDataConnection = new mozilla::DataChannelConnection(this); NS_ENSURE_TRUE(mDataConnection,NS_ERROR_FAILURE); @@ -551,6 +499,7 @@ PeerConnectionImpl::CreateDataChannel(const nsACString& aLabel, uint16_t aMaxNum, nsIDOMDataChannel** aRetval) { + PC_AUTO_ENTER_API_CALL_NO_CHECK(); MOZ_ASSERT(aRetval); #ifdef MOZILLA_INTERNAL_API @@ -580,68 +529,65 @@ PeerConnectionImpl::CreateDataChannel(const nsACString& aLabel, void PeerConnectionImpl::NotifyConnection() { - MOZ_ASSERT(NS_IsMainThread()); + PC_AUTO_ENTER_API_CALL_NO_CHECK(); CSFLogDebugS(logTag, __FUNCTION__); #ifdef MOZILLA_INTERNAL_API - if (mPCObserver) { - PeerConnectionObserverDispatch* runnable = - new PeerConnectionObserverDispatch(PC_OBSERVER_CONNECTION, nullptr, - this, mPCObserver); - if (mThread) { - mThread->Dispatch(runnable, NS_DISPATCH_NORMAL); - return; - } - runnable->Run(); - } + RUN_ON_THREAD(mThread, + WrapRunnable(mPCObserver, + &IPeerConnectionObserver::NotifyConnection), + NS_DISPATCH_NORMAL); #endif } void PeerConnectionImpl::NotifyClosedConnection() { - MOZ_ASSERT(NS_IsMainThread()); + PC_AUTO_ENTER_API_CALL_NO_CHECK(); CSFLogDebugS(logTag, __FUNCTION__); #ifdef MOZILLA_INTERNAL_API - if (mPCObserver) { - PeerConnectionObserverDispatch* runnable = - new PeerConnectionObserverDispatch(PC_OBSERVER_CLOSEDCONNECTION, nullptr, - this, mPCObserver); - if (mThread) { - mThread->Dispatch(runnable, NS_DISPATCH_NORMAL); - return; - } - runnable->Run(); - } + RUN_ON_THREAD(mThread, + WrapRunnable(mPCObserver, + &IPeerConnectionObserver::NotifyClosedConnection), + NS_DISPATCH_NORMAL); #endif } + +#ifdef MOZILLA_INTERNAL_API +// Not a member function so that we don't need to keep the PC live. +static void NotifyDataChannel_m(nsRefPtr aChannel, + nsCOMPtr aObserver) +{ + MOZ_ASSERT(NS_IsMainThread()); + + aObserver->NotifyDataChannel(aChannel); + NS_DataChannelAppReady(aChannel); +} +#endif + void PeerConnectionImpl::NotifyDataChannel(mozilla::DataChannel *aChannel) { - MOZ_ASSERT(NS_IsMainThread()); + PC_AUTO_ENTER_API_CALL_NO_CHECK(); MOZ_ASSERT(aChannel); CSFLogDebugS(logTag, __FUNCTION__ << ": channel: " << static_cast(aChannel)); #ifdef MOZILLA_INTERNAL_API - nsCOMPtr domchannel; - nsresult rv = NS_NewDOMDataChannel(aChannel, mWindow, - getter_AddRefs(domchannel)); + nsCOMPtr domchannel; + nsresult rv = NS_NewDOMDataChannel(aChannel, mWindow, + getter_AddRefs(domchannel)); NS_ENSURE_SUCCESS(rv,); - if (mPCObserver) { - PeerConnectionObserverDispatch* runnable = - new PeerConnectionObserverDispatch(PC_OBSERVER_DATACHANNEL, domchannel.get(), - this, mPCObserver); - if (mThread) { - mThread->Dispatch(runnable, NS_DISPATCH_NORMAL); - return; - } - runnable->Run(); - } + + RUN_ON_THREAD(mThread, + WrapRunnableNM(NotifyDataChannel_m, + domchannel.get(), + mPCObserver), + NS_DISPATCH_NORMAL); #endif } @@ -714,21 +660,23 @@ PeerConnectionImpl::ConvertConstraints( NS_IMETHODIMP PeerConnectionImpl::CreateOffer(const JS::Value& aConstraints, JSContext* aCx) { - CheckIceState(); + PC_AUTO_ENTER_API_CALL(true); - MediaConstraints* cs = new MediaConstraints(); - nsresult rv = ConvertConstraints(aConstraints, cs, aCx); + MediaConstraints cs; + nsresult rv = ConvertConstraints(aConstraints, &cs, aCx); if (rv != NS_OK) { return rv; } - return CreateOffer(*cs); + return CreateOffer(cs); } // Used by unit tests and the IDL CreateOffer. NS_IMETHODIMP PeerConnectionImpl::CreateOffer(MediaConstraints& constraints) { + PC_AUTO_ENTER_API_CALL(true); + mRole = kRoleOfferer; // TODO(ekr@rtfm.com): Interrogate SIPCC here? cc_media_constraints_t* cc_constraints = nullptr; @@ -741,21 +689,22 @@ PeerConnectionImpl::CreateOffer(MediaConstraints& constraints) NS_IMETHODIMP PeerConnectionImpl::CreateAnswer(const JS::Value& aConstraints, JSContext* aCx) { - CheckIceState(); + PC_AUTO_ENTER_API_CALL(true); - MediaConstraints* cs = new MediaConstraints(); - nsresult rv = ConvertConstraints(aConstraints, cs, aCx); + MediaConstraints cs; + nsresult rv = ConvertConstraints(aConstraints, &cs, aCx); if (rv != NS_OK) { return rv; } - CreateAnswer(*cs); - return NS_OK; + return CreateAnswer(cs); } NS_IMETHODIMP PeerConnectionImpl::CreateAnswer(MediaConstraints& constraints) { + PC_AUTO_ENTER_API_CALL(true); + mRole = kRoleAnswerer; // TODO(ekr@rtfm.com): Interrogate SIPCC here? cc_media_constraints_t* cc_constraints = nullptr; @@ -768,12 +717,13 @@ PeerConnectionImpl::CreateAnswer(MediaConstraints& constraints) NS_IMETHODIMP PeerConnectionImpl::SetLocalDescription(int32_t aAction, const char* aSDP) { + PC_AUTO_ENTER_API_CALL(true); + if (!aSDP) { CSFLogError(logTag, "%s - aSDP is NULL", __FUNCTION__); return NS_ERROR_FAILURE; } - CheckIceState(); mLocalRequestedSDP = aSDP; mCall->setLocalDescription((cc_jsep_action_t)aAction, mLocalRequestedSDP); return NS_OK; @@ -782,27 +732,30 @@ PeerConnectionImpl::SetLocalDescription(int32_t aAction, const char* aSDP) NS_IMETHODIMP PeerConnectionImpl::SetRemoteDescription(int32_t action, const char* aSDP) { + PC_AUTO_ENTER_API_CALL(true); + if (!aSDP) { CSFLogError(logTag, "%s - aSDP is NULL", __FUNCTION__); return NS_ERROR_FAILURE; } - CheckIceState(); mRemoteRequestedSDP = aSDP; mCall->setRemoteDescription((cc_jsep_action_t)action, mRemoteRequestedSDP); return NS_OK; } - NS_IMETHODIMP PeerConnectionImpl::AddIceCandidate(const char* aCandidate, const char* aMid, unsigned short aLevel) { - CheckIceState(); + PC_AUTO_ENTER_API_CALL(true); + mCall->addICECandidate(aCandidate, aMid, aLevel); return NS_OK; } NS_IMETHODIMP PeerConnectionImpl::CloseStreams() { + PC_AUTO_ENTER_API_CALL(false); + if (mReadyState != PeerConnectionImpl::kClosed) { ChangeReadyState(PeerConnectionImpl::kClosing); } @@ -813,6 +766,8 @@ PeerConnectionImpl::CloseStreams() { NS_IMETHODIMP PeerConnectionImpl::AddStream(nsIDOMMediaStream* aMediaStream) { + PC_AUTO_ENTER_API_CALL(true); + uint32_t stream_id; nsresult res = mMedia->AddStream(aMediaStream, &stream_id); if (NS_FAILED(res)) @@ -835,6 +790,8 @@ PeerConnectionImpl::AddStream(nsIDOMMediaStream* aMediaStream) { NS_IMETHODIMP PeerConnectionImpl::RemoveStream(nsIDOMMediaStream* aMediaStream) { + PC_AUTO_ENTER_API_CALL(true); + uint32_t stream_id; nsresult res = mMedia->RemoveStream(aMediaStream, &stream_id); @@ -893,6 +850,7 @@ PeerConnectionImpl::GetFingerprint(char** fingerprint) NS_IMETHODIMP PeerConnectionImpl::GetLocalDescription(char** aSDP) { + PC_AUTO_ENTER_API_CALL(true); MOZ_ASSERT(aSDP); char* tmp = new char[mLocalSDP.size() + 1]; @@ -906,6 +864,7 @@ PeerConnectionImpl::GetLocalDescription(char** aSDP) NS_IMETHODIMP PeerConnectionImpl::GetRemoteDescription(char** aSDP) { + PC_AUTO_ENTER_API_CALL(true); MOZ_ASSERT(aSDP); char* tmp = new char[mRemoteSDP.size() + 1]; @@ -919,6 +878,7 @@ PeerConnectionImpl::GetRemoteDescription(char** aSDP) NS_IMETHODIMP PeerConnectionImpl::GetReadyState(uint32_t* aState) { + PC_AUTO_ENTER_API_CALL_NO_CHECK(); MOZ_ASSERT(aState); *aState = mReadyState; @@ -928,6 +888,7 @@ PeerConnectionImpl::GetReadyState(uint32_t* aState) NS_IMETHODIMP PeerConnectionImpl::GetSipccState(uint32_t* aState) { + PC_AUTO_ENTER_API_CALL_NO_CHECK(); MOZ_ASSERT(aState); PeerConnectionCtx* pcctx = PeerConnectionCtx::GetInstance(); @@ -938,19 +899,42 @@ PeerConnectionImpl::GetSipccState(uint32_t* aState) NS_IMETHODIMP PeerConnectionImpl::GetIceState(uint32_t* aState) { + PC_AUTO_ENTER_API_CALL_NO_CHECK(); MOZ_ASSERT(aState); *aState = mIceState; return NS_OK; } +nsresult +PeerConnectionImpl::CheckApiState(bool assert_ice_ready) const +{ + PC_AUTO_ENTER_API_CALL_NO_CHECK(); + PR_ASSERT(!assert_ice_ready || (mIceState != kIceGathering)); + + if (mReadyState == kClosed) + return NS_ERROR_FAILURE; + return NS_OK; +} + NS_IMETHODIMP PeerConnectionImpl::Close(bool aIsSynchronous) { - if (mCall != NULL) + PC_AUTO_ENTER_API_CALL(false); + + return CloseInt(aIsSynchronous); +} + + +nsresult +PeerConnectionImpl::CloseInt(bool aIsSynchronous) +{ + PC_AUTO_ENTER_API_CALL(true); + + if (mCall != nullptr) mCall->endCall(); #ifdef MOZILLA_INTERNAL_API - if (mDataConnection != NULL) + if (mDataConnection) mDataConnection->CloseAll(); #endif @@ -964,13 +948,7 @@ PeerConnectionImpl::Close(bool aIsSynchronous) void PeerConnectionImpl::ShutdownMedia(bool aIsSynchronous) { - // Check that we are on the main thread. - if (mThread) { - bool on; - - MOZ_ASSERT(NS_SUCCEEDED(mThread->IsOnCurrentThread(&on))); - MOZ_ASSERT(on); - } + PC_AUTO_ENTER_API_CALL_NO_CHECK(); if (!mMedia) return; @@ -1000,6 +978,7 @@ void PeerConnectionImpl::onCallEvent(ccapi_call_event_e aCallEvent, CSF::CC_CallPtr aCall, CSF::CC_CallInfoPtr aInfo) { + PC_AUTO_ENTER_API_CALL_NO_CHECK(); MOZ_ASSERT(aCall.get()); MOZ_ASSERT(aInfo.get()); @@ -1042,47 +1021,50 @@ PeerConnectionImpl::onCallEvent(ccapi_call_event_e aCallEvent, void PeerConnectionImpl::ChangeReadyState(PeerConnectionImpl::ReadyState aReadyState) { + PC_AUTO_ENTER_API_CALL_NO_CHECK(); mReadyState = aReadyState; - // FIXME: Dispatch on main thread. - if (mPCObserver) { - PeerConnectionObserverDispatch* runnable = - new PeerConnectionObserverDispatch(PC_OBSERVER_READYSTATE, this, mPCObserver); - if (mThread) { - mThread->Dispatch(runnable, NS_DISPATCH_NORMAL); - return; - } - runnable->Run(); - } + // Note that we are passing an nsRefPtr which + // keeps the observer live. + RUN_ON_THREAD(mThread, WrapRunnable(mPCObserver, + &IPeerConnectionObserver::OnStateChange, + IPeerConnectionObserver::kReadyState), + NS_DISPATCH_NORMAL); } -PeerConnectionWrapper *PeerConnectionImpl::AcquireInstance(const std::string& aHandle) -{ - if (peerconnections.find(aHandle) == peerconnections.end()) { - return NULL; +PeerConnectionWrapper::PeerConnectionWrapper(const std::string& handle) + : impl_(nullptr) { + if (PeerConnectionCtx::GetInstance()->mPeerConnections.find(handle) == + PeerConnectionCtx::GetInstance()->mPeerConnections.end()) { + return; } - PeerConnectionImpl *impl = peerconnections[aHandle]; - impl->AddRef(); - - return new PeerConnectionWrapper(impl); -} - -void -PeerConnectionImpl::ReleaseInstance() -{ - Release(); + impl_ = PeerConnectionCtx::GetInstance()->mPeerConnections[handle]; } const std::string& PeerConnectionImpl::GetHandle() { + PC_AUTO_ENTER_API_CALL_NO_CHECK(); return mHandle; } +// This is called from the STS thread and so we need to thunk +// to the main thread. void PeerConnectionImpl::IceGatheringCompleted(NrIceCtx *aCtx) { + RUN_ON_THREAD(mThread, + WrapRunnable(this, + &PeerConnectionImpl::IceGatheringCompleted_m, + aCtx), + NS_DISPATCH_SYNC); +} + +void +PeerConnectionImpl::IceGatheringCompleted_m(NrIceCtx *aCtx) +{ + PC_AUTO_ENTER_API_CALL_NO_CHECK(); MOZ_ASSERT(aCtx); CSFLogDebugS(logTag, __FUNCTION__ << ": ctx: " << static_cast(aCtx)); @@ -1091,13 +1073,11 @@ PeerConnectionImpl::IceGatheringCompleted(NrIceCtx *aCtx) #ifdef MOZILLA_INTERNAL_API if (mPCObserver) { - PeerConnectionObserverDispatch* runnable = - new PeerConnectionObserverDispatch(PC_OBSERVER_ICE, this, mPCObserver); - if (mThread) { - mThread->Dispatch(runnable, NS_DISPATCH_NORMAL); - return; - } - runnable->Run(); + RUN_ON_THREAD(mThread, + WrapRunnable(mPCObserver, + &IPeerConnectionObserver::OnStateChange, + IPeerConnectionObserver::kIceState), + NS_DISPATCH_NORMAL); } #endif } @@ -1105,6 +1085,17 @@ PeerConnectionImpl::IceGatheringCompleted(NrIceCtx *aCtx) void PeerConnectionImpl::IceCompleted(NrIceCtx *aCtx) { + RUN_ON_THREAD(mThread, + WrapRunnable(this, + &PeerConnectionImpl::IceCompleted_m, + aCtx), + NS_DISPATCH_SYNC); +} + +void +PeerConnectionImpl::IceCompleted_m(NrIceCtx *aCtx) +{ + PC_AUTO_ENTER_API_CALL_NO_CHECK(); MOZ_ASSERT(aCtx); CSFLogDebugS(logTag, __FUNCTION__ << ": ctx: " << static_cast(aCtx)); @@ -1113,13 +1104,11 @@ PeerConnectionImpl::IceCompleted(NrIceCtx *aCtx) #ifdef MOZILLA_INTERNAL_API if (mPCObserver) { - PeerConnectionObserverDispatch* runnable = - new PeerConnectionObserverDispatch(PC_OBSERVER_ICE, this, mPCObserver); - if (mThread) { - mThread->Dispatch(runnable, NS_DISPATCH_NORMAL); - return; - } - runnable->Run(); + RUN_ON_THREAD(mThread, + WrapRunnable(mPCObserver, + &IPeerConnectionObserver::OnStateChange, + IPeerConnectionObserver::kIceState), + NS_DISPATCH_NORMAL); } #endif } @@ -1127,6 +1116,7 @@ PeerConnectionImpl::IceCompleted(NrIceCtx *aCtx) void PeerConnectionImpl::IceStreamReady(NrIceMediaStream *aStream) { + PC_AUTO_ENTER_API_CALL_NO_CHECK(); MOZ_ASSERT(aStream); CSFLogDebugS(logTag, __FUNCTION__ << ": " << aStream->name().c_str()); @@ -1157,6 +1147,7 @@ GetStreams(JSContext* cx, PeerConnectionImpl* peerConnection, NS_IMETHODIMP PeerConnectionImpl::GetLocalStreams(JSContext* cx, JS::Value* streams) { + PC_AUTO_ENTER_API_CALL_NO_CHECK(); #ifdef MOZILLA_INTERNAL_API return GetStreams(cx, this, MediaStreamList::Local, streams); #else @@ -1167,6 +1158,7 @@ PeerConnectionImpl::GetLocalStreams(JSContext* cx, JS::Value* streams) NS_IMETHODIMP PeerConnectionImpl::GetRemoteStreams(JSContext* cx, JS::Value* streams) { + PC_AUTO_ENTER_API_CALL_NO_CHECK(); #ifdef MOZILLA_INTERNAL_API return GetStreams(cx, this, MediaStreamList::Remote, streams); #else diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h index ea3f1f296c8..57f9f523120 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h @@ -42,6 +42,8 @@ using namespace mozilla; namespace sipcc { +class PeerConnectionWrapper; + struct ConstraintInfo { std::string value; bool mandatory; @@ -60,6 +62,17 @@ private: class PeerConnectionWrapper; +// Enter an API call and check that the state is OK, +// the PC isn't closed, etc. +#define PC_AUTO_ENTER_API_CALL(assert_ice_ready) \ + do { \ + /* do/while prevents res from conflicting with locals */ \ + nsresult res = CheckApiState(assert_ice_ready); \ + if (NS_FAILED(res)) return res; \ + } while(0) +#define PC_AUTO_ENTER_API_CALL_NO_CHECK() CheckThread() + + class PeerConnectionImpl MOZ_FINAL : public IPeerConnection, #ifdef MOZILLA_INTERNAL_API public mozilla::DataChannelConnection::DataConnectionListener, @@ -103,8 +116,16 @@ public: static PeerConnectionImpl* CreatePeerConnection(); static void Shutdown(); + static nsresult ConvertConstraints( + const JS::Value& aConstraints, MediaConstraints* aObj, JSContext* aCx); + static nsresult MakeMediaStream(uint32_t aHint, nsIDOMMediaStream** aStream); + static nsresult MakeRemoteSource(nsDOMMediaStream* aStream, RemoteSourceStreamInfo** aInfo); + + Role GetRole() const { + PC_AUTO_ENTER_API_CALL_NO_CHECK(); + return mRole; + } - Role GetRole() const { return mRole; } nsresult CreateRemoteSourceStreamInfo(uint32_t aHint, RemoteSourceStreamInfo** aInfo); // Implementation of the only observer we need @@ -120,11 +141,12 @@ public: void NotifyDataChannel(mozilla::DataChannel *aChannel); // Get the media object - const nsRefPtr& media() const { return mMedia; } + const nsRefPtr& media() const { + PC_AUTO_ENTER_API_CALL_NO_CHECK(); + return mMedia; + } // Handle system to allow weak references to be passed through C code - static PeerConnectionWrapper *AcquireInstance(const std::string& aHandle); - virtual void ReleaseInstance(); virtual const std::string& GetHandle(); // ICE events @@ -136,23 +158,33 @@ public: static void ConnectThread(void *aData); // Get the main thread - nsCOMPtr GetMainThread() { return mThread; } + nsCOMPtr GetMainThread() { + PC_AUTO_ENTER_API_CALL_NO_CHECK(); + return mThread; + } // Get the STS thread - nsCOMPtr GetSTSThread() { return mSTSThread; } + nsCOMPtr GetSTSThread() { + PC_AUTO_ENTER_API_CALL_NO_CHECK(); + return mSTSThread; + } // Get the DTLS identity - mozilla::RefPtr const GetIdentity() { return mIdentity; } + mozilla::RefPtr const GetIdentity() { + PC_AUTO_ENTER_API_CALL_NO_CHECK(); + return mIdentity; + } // Create a fake media stream nsresult CreateFakeMediaStream(uint32_t hint, nsIDOMMediaStream** retval); - nsPIDOMWindow* GetWindow() const { return mWindow; } + nsPIDOMWindow* GetWindow() const { + PC_AUTO_ENTER_API_CALL_NO_CHECK(); + return mWindow; + } // Validate constraints and construct a MediaConstraints object // from a JS::Value. - nsresult ConvertConstraints( - const JS::Value& aConstraints, MediaConstraints* aObj, JSContext* aCx); NS_IMETHODIMP CreateOffer(MediaConstraints& aConstraints); NS_IMETHODIMP CreateAnswer(MediaConstraints& aConstraints); @@ -160,16 +192,33 @@ private: PeerConnectionImpl(const PeerConnectionImpl&rhs); PeerConnectionImpl& operator=(PeerConnectionImpl); + NS_IMETHODIMP CreateOfferInt(MediaConstraints& constraints); + NS_IMETHODIMP CreateAnswerInt(MediaConstraints& constraints); + + nsresult CloseInt(bool aIsSynchronous); void ChangeReadyState(ReadyState aReadyState); - void CheckIceState() { - PR_ASSERT(mIceState != kIceGathering); + nsresult CheckApiState(bool assert_ice_ready) const; + void CheckThread() const { + NS_ABORT_IF_FALSE(CheckThreadInt(), "Wrong thread"); + } + bool CheckThreadInt() const { +#ifdef MOZILLA_INTERNAL_API + // Thread assertions are disabled in the C++ unit tests because those + // make API calls off the main thread. + // TODO(ekr@rtfm.com): Fix the unit tests so they don't do that. + bool on; + NS_ENSURE_SUCCESS(mThread->IsOnCurrentThread(&on), false); + NS_ENSURE_TRUE(on, false); +#endif + return true; } // Shut down media. Called on any thread. void ShutdownMedia(bool isSynchronous); - nsresult MakeMediaStream(uint32_t aHint, nsIDOMMediaStream** aStream); - nsresult MakeRemoteSource(nsDOMMediaStream* aStream, RemoteSourceStreamInfo** aInfo); + // ICE callbacks run on the right thread. + void IceGatheringCompleted_m(NrIceCtx *aCtx); + void IceCompleted_m(NrIceCtx *aCtx); // The role we are adopting Role mRole; @@ -212,9 +261,6 @@ private: nsRefPtr mMedia; - // Singleton list of all the PeerConnections - static std::map peerconnections; - public: //these are temporary until the DataChannel Listen/Connect API is removed unsigned short listenPort; @@ -225,17 +271,12 @@ public: // This is what is returned when you acquire on a handle class PeerConnectionWrapper { public: - PeerConnectionWrapper(PeerConnectionImpl *impl) : impl_(impl) {} - - ~PeerConnectionWrapper() { - if (impl_) - impl_->ReleaseInstance(); - } + PeerConnectionWrapper(const std::string& handle); PeerConnectionImpl *impl() { return impl_; } private: - PeerConnectionImpl *impl_; + nsRefPtr impl_; }; } // end sipcc namespace diff --git a/media/webrtc/signaling/test/FakeMediaStreams.h b/media/webrtc/signaling/test/FakeMediaStreams.h index 2f1ec88be03..8c62e399984 100644 --- a/media/webrtc/signaling/test/FakeMediaStreams.h +++ b/media/webrtc/signaling/test/FakeMediaStreams.h @@ -48,15 +48,17 @@ public: // Note: only one listener supported class Fake_MediaStream { -public: - Fake_MediaStream () : mListeners() {} + public: + Fake_MediaStream () : mListeners(), mMutex("Fake MediaStream") {} virtual ~Fake_MediaStream() { Stop(); } void AddListener(Fake_MediaStreamListener *aListener) { + mozilla::MutexAutoLock lock(mMutex); mListeners.insert(aListener); } void RemoveListener(Fake_MediaStreamListener *aListener) { + mozilla::MutexAutoLock lock(mMutex); mListeners.erase(aListener); } @@ -67,8 +69,12 @@ public: virtual void Periodic() {} + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Fake_MediaStream); + protected: std::set mListeners; + mozilla::Mutex mMutex; // Lock to prevent the listener list from being modified while + // executing Periodic(). }; class Fake_MediaPeriodic : public nsITimerCallback { @@ -205,7 +211,7 @@ public: void SetHintContents(uint32_t aHintContents) { mHintContents = aHintContents; } private: - Fake_MediaStream *mMediaStream; + nsRefPtr mMediaStream; // tells the SDP generator about whether this // MediaStream probably has audio and/or video diff --git a/media/webrtc/signaling/test/FakeMediaStreamsImpl.h b/media/webrtc/signaling/test/FakeMediaStreamsImpl.h index a6187ee0849..d69791b8c7f 100644 --- a/media/webrtc/signaling/test/FakeMediaStreamsImpl.h +++ b/media/webrtc/signaling/test/FakeMediaStreamsImpl.h @@ -38,6 +38,7 @@ nsresult Fake_SourceMediaStream::Start() { } nsresult Fake_SourceMediaStream::Stop() { + mozilla::MutexAutoLock lock(mMutex); if (mTimer) mTimer->Cancel(); mPeriodic->Detach(); @@ -45,6 +46,7 @@ nsresult Fake_SourceMediaStream::Stop() { } void Fake_SourceMediaStream::Periodic() { + mozilla::MutexAutoLock lock(mMutex); // Pull more audio-samples iff pulling is enabled // and we are not asked by the signaling agent to stop //pulling data. @@ -69,6 +71,10 @@ nsresult Fake_MediaStreamBase::Start() { } nsresult Fake_MediaStreamBase::Stop() { + // Lock the mutex so that we know that after this + // has returned, periodic will not be firing again + // and so it's safe to destruct. + mozilla::MutexAutoLock lock(mMutex); mTimer->Cancel(); return NS_OK; @@ -76,6 +82,7 @@ nsresult Fake_MediaStreamBase::Stop() { // Fake_AudioStreamSource void Fake_AudioStreamSource::Periodic() { + mozilla::MutexAutoLock lock(mMutex); //Are we asked to stop pumping audio samples ? if(mStop) { return; diff --git a/media/webrtc/signaling/test/signaling_unittests.cpp b/media/webrtc/signaling/test/signaling_unittests.cpp index 7735243b64a..30eb3d814a8 100644 --- a/media/webrtc/signaling/test/signaling_unittests.cpp +++ b/media/webrtc/signaling/test/signaling_unittests.cpp @@ -297,20 +297,20 @@ TestObserver::OnAddStream(nsIDOMMediaStream *stream, const char *type) nsDOMMediaStream *ms = static_cast(stream); - cout << "OnAddStream called hints=" << ms->GetHintContents() << endl; - state = stateSuccess; + cout << "OnAddStream called hints=" << ms->GetHintContents() << " type=" << type << " thread=" << + PR_GetCurrentThread() << endl ; + onAddStreamCalled = true; + streams.push_back(ms); + // We know that the media stream is secretly a Fake_SourceMediaStream, // so now we can start it pulling from us Fake_SourceMediaStream *fs = static_cast(ms->GetStream()); - nsresult ret; test_utils->sts_target()->Dispatch( - WrapRunnableRet(fs, &Fake_SourceMediaStream::Start, &ret), - NS_DISPATCH_SYNC); - - streams.push_back(ms); + WrapRunnable(fs, &Fake_SourceMediaStream::Start), + NS_DISPATCH_NORMAL); return NS_OK; } @@ -475,14 +475,15 @@ class ParsedSDP { class SignalingAgent { public: - SignalingAgent() { - Init(); - } + SignalingAgent() : pc(nullptr) {} + ~SignalingAgent() { - Close(); + pc->GetMainThread()->Dispatch( + WrapRunnable(this, &SignalingAgent::Close), + NS_DISPATCH_SYNC); } - void Init() + void Init(nsCOMPtr thread) { size_t found = 2; ASSERT_TRUE(found > 0); @@ -493,7 +494,7 @@ class SignalingAgent { pObserver = new TestObserver(pc); ASSERT_TRUE(pObserver); - ASSERT_EQ(pc->Initialize(pObserver, nullptr, nullptr), NS_OK); + ASSERT_EQ(pc->Initialize(pObserver, nullptr, thread), NS_OK); ASSERT_TRUE_WAIT(sipcc_state() == sipcc::PeerConnectionImpl::kStarted, kDefaultTimeout); @@ -520,7 +521,10 @@ class SignalingAgent { void Close() { cout << "Close" << endl; + pc->Close(false); + pc = nullptr; + // Shutdown is synchronous evidently. // ASSERT_TRUE(pObserver->WaitForObserverCall()); // ASSERT_EQ(pc->sipcc_state(), sipcc::PeerConnectionInterface::kIdle); @@ -794,6 +798,24 @@ class SignalingEnvironment : public ::testing::Environment { class SignalingTest : public ::testing::Test { public: + static void SetUpTestCase() { + nsIThread *thread; + + nsresult rv = NS_NewThread(&thread); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + gThread = thread; + } + + void SetUp() { + a1_.Init(gThread); + a2_.Init(gThread); + } + + static void TearDownTestCase() { + gThread = nullptr; + } + void CreateOffer(sipcc::MediaConstraints& constraints, uint32_t offerFlags, uint32_t sdpCheck) { a1_.CreateOffer(constraints, offerFlags, sdpCheck); @@ -882,10 +904,13 @@ public: } protected: + static nsCOMPtr gThread; SignalingAgent a1_; // Canonically "caller" SignalingAgent a2_; // Canonically "callee" }; +nsCOMPtr SignalingTest::gThread; + TEST_F(SignalingTest, JustInit) { @@ -1232,6 +1257,7 @@ TEST_F(SignalingTest, FullCallTrickle) OfferAnswerTrickle(constraints, constraints, SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV); + std::cerr << "ICE handshake completed" << std::endl; PR_Sleep(kDefaultTimeout * 2); // Wait for some data to get written a1_.CloseSendStreams();