--- a/media/mtransport/build/moz.build
+++ b/media/mtransport/build/moz.build
@@ -4,16 +4,17 @@
# 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/.
include("/ipc/chromium/chromium-config.mozbuild")
EXPORTS.mtransport += [
'../dtlsidentity.h',
'../m_cpp_utils.h',
+ '../mediapacket.h',
'../nricectx.h',
'../nricemediastream.h',
'../nriceresolverfake.h',
'../nricestunaddr.h',
'../rlogconnector.h',
'../runnable_utils.h',
'../sigslot.h',
'../simpletokenbucket.h',
--- a/media/mtransport/common.build
+++ b/media/mtransport/common.build
@@ -1,16 +1,17 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
mtransport_lcppsrcs = [
'dtlsidentity.cpp',
+ 'mediapacket.cpp',
'nr_socket_prsock.cpp',
'nr_timer.cpp',
'nricectx.cpp',
'nricectxhandler.cpp',
'nricemediastream.cpp',
'nriceresolver.cpp',
'nriceresolverfake.cpp',
'nricestunaddr.cpp',
deleted file mode 100644
--- a/media/mtransport/databuffer.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* 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/. */
-
-// Original author: ekr@rtfm.com
-
-#ifndef databuffer_h__
-#define databuffer_h__
-#include <algorithm>
-#include <mozilla/UniquePtr.h>
-#include <m_cpp_utils.h>
-#include <nsISupportsImpl.h>
-
-namespace mozilla {
-
-class DataBuffer {
- public:
- DataBuffer() : data_(nullptr), len_(0), capacity_(0) {}
- DataBuffer(const uint8_t *data, size_t len) {
- Assign(data, len, len);
- }
- DataBuffer(const uint8_t *data, size_t len, size_t capacity) {
- Assign(data, len, capacity);
- }
-
- // to ensure extra space for expansion
- void Assign(const uint8_t *data, size_t len, size_t capacity) {
- MOZ_RELEASE_ASSERT(len <= capacity);
- Allocate(capacity); // sets len_ = capacity
- memcpy(static_cast<void *>(data_.get()),
- static_cast<const void *>(data), len);
- len_ = len;
- }
-
- void Allocate(size_t capacity) {
- data_.reset(new uint8_t[capacity ? capacity : 1]); // Don't depend on new [0].
- len_ = capacity_ = capacity;
- }
-
- void EnsureCapacity(size_t capacity) {
- if (capacity_ < capacity) {
- uint8_t *new_data = new uint8_t[ capacity ? capacity : 1];
- memcpy(static_cast<void *>(new_data),
- static_cast<const void *>(data_.get()), len_);
- data_.reset(new_data); // after copying! Deletes old data
- capacity_ = capacity;
- }
- }
-
- // used when something writes to the buffer (having checked
- // capacity() or used EnsureCapacity()) and increased the length.
- void SetLength(size_t len) {
- MOZ_RELEASE_ASSERT(len <= capacity_);
- len_ = len;
- }
-
- const uint8_t *data() const { return data_.get(); }
- uint8_t *data() { return data_.get(); }
- size_t len() const { return len_; }
- size_t capacity() const { return capacity_; }
-
-private:
- UniquePtr<uint8_t[]> data_;
- size_t len_;
- size_t capacity_;
-
- DISALLOW_COPY_ASSIGN(DataBuffer);
-};
-
-}
-
-#endif
new file mode 100644
--- /dev/null
+++ b/media/mtransport/mediapacket.cpp
@@ -0,0 +1,26 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#include "mediapacket.h"
+
+#include <cstring>
+
+namespace mozilla {
+
+void
+MediaPacket::Copy(const uint8_t* data, size_t len, size_t capacity)
+{
+ if (capacity < len) {
+ capacity = len;
+ }
+ data_.reset(new uint8_t[capacity]);
+ len_ = len;
+ capacity_ = capacity;
+ memcpy(data_.get(), data, len);
+}
+
+} // namespace mozilla
+
new file mode 100644
--- /dev/null
+++ b/media/mtransport/mediapacket.h
@@ -0,0 +1,117 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#ifndef mediapacket_h__
+#define mediapacket_h__
+
+#include <cstddef>
+#include <cstdint>
+#include "mozilla/UniquePtr.h"
+#include "mozilla/Maybe.h"
+
+namespace mozilla {
+
+// TODO: It might be worthwhile to teach this class how to "borrow" a buffer.
+// That would make it easier to misuse, however, so maybe not worth it.
+class MediaPacket {
+ public:
+ MediaPacket() = default;
+ MediaPacket(MediaPacket&& orig) = default;
+
+ // Takes ownership of the passed-in data
+ void Take(UniquePtr<uint8_t[]>&& data, size_t len, size_t capacity=0)
+ {
+ data_ = std::move(data);
+ len_ = len;
+ if (capacity < len) {
+ capacity = len;
+ }
+ capacity_ = capacity;
+ }
+
+ void Reset()
+ {
+ data_.reset();
+ len_ = 0;
+ capacity_ = 0;
+ }
+
+ // Copies the passed-in data
+ void Copy(const uint8_t* data, size_t len, size_t capacity=0);
+
+ uint8_t* data() const
+ {
+ return data_.get();
+ }
+
+ size_t len() const
+ {
+ return len_;
+ }
+
+ void SetLength(size_t length)
+ {
+ len_ = length;
+ }
+
+ size_t capacity() const
+ {
+ return capacity_;
+ }
+
+ Maybe<size_t>& sdp_level()
+ {
+ return sdp_level_;
+ }
+
+ void CopyDataToEncrypted()
+ {
+ encrypted_data_ = std::move(data_);
+ encrypted_len_ = len_;
+ Copy(encrypted_data_.get(), len_);
+ }
+
+ const uint8_t* encrypted_data() const
+ {
+ return encrypted_data_.get();
+ }
+
+ size_t encrypted_len() const
+ {
+ return encrypted_len_;
+ }
+
+ enum Type {
+ UNCLASSIFIED,
+ RTP,
+ RTCP,
+ SCTP
+ };
+
+ void SetType(Type type)
+ {
+ type_ = type;
+ }
+
+ Type type() const
+ {
+ return type_;
+ }
+
+ private:
+ UniquePtr<uint8_t[]> data_;
+ size_t len_ = 0;
+ size_t capacity_ = 0;
+ // Encrypted form of the data, if there is one.
+ UniquePtr<uint8_t[]> encrypted_data_;
+ size_t encrypted_len_ = 0;
+ // SDP level that this packet belongs to, if known.
+ Maybe<size_t> sdp_level_;
+ Type type_ = UNCLASSIFIED;
+};
+}
+#endif // mediapacket_h__
+
--- a/media/mtransport/nr_socket_prsock.cpp
+++ b/media/mtransport/nr_socket_prsock.cpp
@@ -1180,17 +1180,18 @@ NS_IMETHODIMP NrUdpSocketIpc::CallListen
// Use PR_IpAddrNull to avoid address being reset to 0.
if (PR_SUCCESS != PR_SetNetAddr(PR_IpAddrNull, addr.raw.family, port, &addr)) {
err_ = true;
MOZ_ASSERT(false, "Failed to set port in PRNetAddr");
return NS_OK;
}
}
- nsAutoPtr<DataBuffer> buf(new DataBuffer(data, data_length));
+ nsAutoPtr<MediaPacket> buf(new MediaPacket);
+ buf->Copy(data, data_length);
RefPtr<nr_udp_message> msg(new nr_udp_message(addr, buf));
RUN_ON_THREAD(sts_thread_,
mozilla::WrapRunnable(RefPtr<NrUdpSocketIpc>(this),
&NrUdpSocketIpc::recv_callback_s,
msg),
NS_DISPATCH_NORMAL);
return NS_OK;
@@ -1371,17 +1372,18 @@ int NrUdpSocketIpc::sendto(const void *m
if ((r=nr_transport_addr_to_netaddr(to, &addr))) {
return r;
}
if (nr_is_stun_request_message((UCHAR*)msg, len) && ShouldDrop(len)) {
return R_WOULDBLOCK;
}
- nsAutoPtr<DataBuffer> buf(new DataBuffer(static_cast<const uint8_t*>(msg), len));
+ nsAutoPtr<MediaPacket> buf(new MediaPacket);
+ buf->Copy(static_cast<const uint8_t*>(msg), len);
RUN_ON_THREAD(io_thread_,
mozilla::WrapRunnable(RefPtr<NrUdpSocketIpc>(this),
&NrUdpSocketIpc::sendto_i,
addr, buf),
NS_DISPATCH_NORMAL);
return 0;
}
@@ -1589,17 +1591,17 @@ void NrUdpSocketIpc::connect_i(const nsA
err_ = true;
MOZ_ASSERT(false, "Failed to connect UDP socket");
mon.NotifyAll();
return;
}
}
-void NrUdpSocketIpc::sendto_i(const net::NetAddr &addr, nsAutoPtr<DataBuffer> buf) {
+void NrUdpSocketIpc::sendto_i(const net::NetAddr &addr, nsAutoPtr<MediaPacket> buf) {
ASSERT_ON_THREAD(io_thread_);
ReentrantMonitorAutoEnter mon(monitor_);
if (!socket_child_) {
MOZ_ASSERT(false);
err_ = true;
return;
@@ -1746,17 +1748,18 @@ NS_IMETHODIMP NrTcpSocketIpc::UpdateBuff
return NS_OK;
}
NS_IMETHODIMP NrTcpSocketIpc::FireDataArrayEvent(const nsAString& aType,
const InfallibleTArray<uint8_t>& buffer) {
// Called when we received data.
uint8_t *buf = const_cast<uint8_t*>(buffer.Elements());
- nsAutoPtr<DataBuffer> data_buf(new DataBuffer(buf, buffer.Length()));
+ nsAutoPtr<MediaPacket> data_buf(new MediaPacket);
+ data_buf->Copy(buf, buffer.Length());
RefPtr<nr_tcp_message> msg = new nr_tcp_message(data_buf);
RUN_ON_THREAD(sts_thread_,
mozilla::WrapRunnable(RefPtr<NrTcpSocketIpc>(this),
&NrTcpSocketIpc::recv_message_s,
msg),
NS_DISPATCH_NORMAL);
return NS_OK;
--- a/media/mtransport/nr_socket_prsock.h
+++ b/media/mtransport/nr_socket_prsock.h
@@ -57,17 +57,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE
#include "nsISocketTransportService.h"
#include "nsXPCOM.h"
#include "nsIEventTarget.h"
#include "nsIUDPSocketChild.h"
#include "nsProxyRelease.h"
#include "nsThreadUtils.h"
#include "nsITCPSocketCallback.h"
-#include "databuffer.h"
+#include "mediapacket.h"
#include "m_cpp_utils.h"
#include "mozilla/ReentrantMonitor.h"
#include "mozilla/RefPtr.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/ClearOnShutdown.h"
// Stub declaration for nICEr type
typedef struct nr_socket_vtbl_ nr_socket_vtbl;
@@ -192,24 +192,24 @@ protected:
DISALLOW_COPY_ASSIGN(NrSocket);
PRFileDesc *fd_;
nsCOMPtr<nsIEventTarget> ststhread_;
};
struct nr_udp_message {
- nr_udp_message(const PRNetAddr &from, nsAutoPtr<DataBuffer> &data)
+ nr_udp_message(const PRNetAddr &from, nsAutoPtr<MediaPacket> &data)
: from(from), data(data) {
}
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nr_udp_message);
PRNetAddr from;
- nsAutoPtr<DataBuffer> data;
+ nsAutoPtr<MediaPacket> data;
private:
~nr_udp_message() {}
DISALLOW_COPY_ASSIGN(nr_udp_message);
};
class NrSocketIpc : public NrSocketBase {
public:
@@ -272,17 +272,17 @@ private:
DISALLOW_COPY_ASSIGN(NrUdpSocketIpc);
nsresult SetAddress(); // Set the local address from parent info.
// Main or private thread executors of the NrSocketBase APIs
void create_i(const nsACString &host, const uint16_t port);
void connect_i(const nsACString &host, const uint16_t port);
- void sendto_i(const net::NetAddr &addr, nsAutoPtr<DataBuffer> buf);
+ void sendto_i(const net::NetAddr &addr, nsAutoPtr<MediaPacket> buf);
void close_i();
#if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API)
static void destroy_i(nsIUDPSocketChild* aChild,
nsCOMPtr<nsIEventTarget>& aStsThread);
#endif
// STS thread executor
void recv_callback_s(RefPtr<nr_udp_message> msg);
@@ -307,17 +307,17 @@ public:
private:
virtual ~NrUdpSocketIpcProxy();
RefPtr<NrUdpSocketIpc> socket_;
nsCOMPtr<nsIEventTarget> sts_thread_;
};
struct nr_tcp_message {
- explicit nr_tcp_message(nsAutoPtr<DataBuffer> &data)
+ explicit nr_tcp_message(nsAutoPtr<MediaPacket> &data)
: read_bytes(0)
, data(data) {
}
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nr_tcp_message);
const uint8_t *reading_pointer() const {
return data->data() + read_bytes;
@@ -328,17 +328,17 @@ struct nr_tcp_message {
}
size_t read_bytes;
private:
~nr_tcp_message() {}
DISALLOW_COPY_ASSIGN(nr_tcp_message);
- nsAutoPtr<DataBuffer> data;
+ nsAutoPtr<MediaPacket> data;
};
#if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API)
class NrTcpSocketIpc : public NrSocketIpc,
public nsITCPSocketCallback {
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSITCPSOCKETCALLBACK
--- a/media/mtransport/test/buffered_stun_socket_unittest.cpp
+++ b/media/mtransport/test/buffered_stun_socket_unittest.cpp
@@ -15,17 +15,16 @@
extern "C" {
#include "nr_api.h"
#include "nr_socket.h"
#include "nr_socket_buffered_stun.h"
#include "transport_addr.h"
#include "stun.h"
}
-#include "databuffer.h"
#include "dummysocket.h"
#include "nr_socket_prsock.h"
#define GTEST_HAS_RTTI 0
#include "gtest/gtest.h"
#include "gtest_utils.h"
--- a/media/mtransport/test/dummysocket.h
+++ b/media/mtransport/test/dummysocket.h
@@ -10,33 +10,33 @@
#define MTRANSPORT_DUMMY_SOCKET_H_
#include "nr_socket_prsock.h"
extern "C" {
#include "transport_addr.h"
}
-#include "databuffer.h"
+#include "mediapacket.h"
#include "mozilla/UniquePtr.h"
#define GTEST_HAS_RTTI 0
#include "gtest/gtest.h"
#include "gtest_utils.h"
namespace mozilla {
-static UniquePtr<DataBuffer> merge(UniquePtr<DataBuffer> a, UniquePtr<DataBuffer> b) {
+static UniquePtr<MediaPacket> merge(UniquePtr<MediaPacket> a, UniquePtr<MediaPacket> b) {
if (a && a->len() && b && b->len()) {
- UniquePtr<DataBuffer> merged(new DataBuffer());
- merged->Allocate(a->len() + b->len());
+ UniquePtr<uint8_t[]> data(new uint8_t[a->len() + b->len()]);
+ memcpy(data.get(), a->data(), a->len());
+ memcpy(data.get() + a->len(), b->data(), b->len());
- memcpy(merged->data(), a->data(), a->len());
- memcpy(merged->data() + a->len(), b->data(), b->len());
-
+ UniquePtr<MediaPacket> merged(new MediaPacket);
+ merged->Take(std::move(data), a->len() + b->len());
return merged;
}
if (a && a->len()) {
return a;
}
if (b && b->len()) {
@@ -95,17 +95,18 @@ class DummySocket : public NrSocketBase
virtual int accept(nr_transport_addr *addrp, nr_socket **sockp) override {
return 0;
}
virtual int write(const void *msg, size_t len, size_t *written) override {
size_t to_write = std::min(len, writable_);
if (to_write) {
- UniquePtr<DataBuffer> msgbuf(new DataBuffer(static_cast<const uint8_t *>(msg), to_write));
+ UniquePtr<MediaPacket> msgbuf(new MediaPacket);
+ msgbuf->Copy(static_cast<const uint8_t *>(msg), to_write);
write_buffer_ = merge(std::move(write_buffer_), std::move(msgbuf));
}
*written = to_write;
return 0;
}
@@ -116,18 +117,20 @@ class DummySocket : public NrSocketBase
size_t to_read = std::min(read_buffer_->len(),
std::min(maxlen, readable_));
memcpy(buf, read_buffer_->data(), to_read);
*len = to_read;
if (to_read < read_buffer_->len()) {
- read_buffer_.reset(new DataBuffer(read_buffer_->data() + to_read,
- read_buffer_->len() - to_read));
+ MediaPacket* newPacket = new MediaPacket;
+ newPacket->Copy(read_buffer_->data() + to_read,
+ read_buffer_->len() - to_read);
+ read_buffer_.reset(newPacket);
} else {
read_buffer_.reset();
}
return 0;
}
// Implementations of the async_event APIs.
@@ -175,17 +178,18 @@ class DummySocket : public NrSocketBase
cb_ = nullptr;
cb_arg_ = nullptr;
cb(this, NR_ASYNC_WAIT_WRITE, cb_arg);
}
void SetReadBuffer(const uint8_t *data, size_t len) {
EXPECT_EQ(nullptr, write_buffer_.get());
- read_buffer_.reset(new DataBuffer(data, len));
+ read_buffer_.reset(new MediaPacket);
+ read_buffer_->Copy(data, len);
}
void ClearReadBuffer() {
read_buffer_.reset();
}
void SetReadable(size_t val) {
readable_ = val;
@@ -209,19 +213,19 @@ class DummySocket : public NrSocketBase
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DummySocket, override);
private:
~DummySocket() {}
DISALLOW_COPY_ASSIGN(DummySocket);
size_t writable_; // Amount we allow someone to write.
- UniquePtr<DataBuffer> write_buffer_;
+ UniquePtr<MediaPacket> write_buffer_;
size_t readable_; // Amount we allow someone to read.
- UniquePtr<DataBuffer> read_buffer_;
+ UniquePtr<MediaPacket> read_buffer_;
NR_async_cb cb_;
void *cb_arg_;
nr_socket *self_;
nr_transport_addr connect_addr_;
};
--- a/media/mtransport/test/proxy_tunnel_socket_unittest.cpp
+++ b/media/mtransport/test/proxy_tunnel_socket_unittest.cpp
@@ -15,17 +15,16 @@
extern "C" {
#include "nr_api.h"
#include "nr_socket.h"
#include "nr_proxy_tunnel.h"
#include "transport_addr.h"
#include "stun.h"
}
-#include "databuffer.h"
#include "dummysocket.h"
#include "nr_socket_prsock.h"
#include "nriceresolverfake.h"
#define GTEST_HAS_RTTI 0
#include "gtest/gtest.h"
#include "gtest_utils.h"
--- a/media/mtransport/test/sctp_unittest.cpp
+++ b/media/mtransport/test/sctp_unittest.cpp
@@ -194,48 +194,45 @@ class TransportTestPeer : public sigslot
++sent_;
}
int sent() const { return sent_; }
int received() const { return received_; }
bool connected() const { return connected_; }
- static TransportResult SendPacket_s(const unsigned char* data, size_t len,
+ static TransportResult SendPacket_s(nsAutoPtr<MediaPacket> packet,
const RefPtr<TransportFlow>& flow,
TransportLayer* layer) {
- TransportResult res = layer->SendPacket(data, len);
- delete data; // we always allocate
- return res;
+ return layer->SendPacket(*packet);
}
TransportResult SendPacket(const unsigned char* data, size_t len) {
- unsigned char *buffer = new unsigned char[len];
- memcpy(buffer, data, len);
+ nsAutoPtr<MediaPacket> packet(new MediaPacket);
+ packet->Copy(data, len);
// Uses DISPATCH_NORMAL to avoid possible deadlocks when we're called
// from MainThread especially during shutdown (same as DataChannels).
// RUN_ON_THREAD short-circuits if already on the STS thread, which is
// normal for most transfers outside of connect() and close(). Passes
// a refptr to flow_ to avoid any async deletion issues (since we can't
// make 'this' into a refptr as it isn't refcounted)
RUN_ON_THREAD(test_utils_->sts_target(), WrapRunnableNM(
- &TransportTestPeer::SendPacket_s, buffer, len, flow_, loopback_),
+ &TransportTestPeer::SendPacket_s, packet, flow_, loopback_),
NS_DISPATCH_NORMAL);
return 0;
}
- void PacketReceived(TransportLayer * layer, const unsigned char* data,
- size_t len) {
- std::cerr << "Received " << len << " bytes" << std::endl;
+ void PacketReceived(TransportLayer * layer, MediaPacket& packet) {
+ std::cerr << "Received " << packet.len() << " bytes" << std::endl;
// Pass the data to SCTP
- usrsctp_conninput(static_cast<void *>(this), data, len, 0);
+ usrsctp_conninput(static_cast<void *>(this), packet.data(), packet.len(), 0);
}
// Process SCTP notification
void Notification(union sctp_notification *msg, size_t len) {
ASSERT_EQ(msg->sn_header.sn_length, len);
if (msg->sn_header.sn_type == SCTP_ASSOC_CHANGE) {
struct sctp_assoc_change *change = &msg->sn_assoc_change;
--- a/media/mtransport/test/stunserver.cpp
+++ b/media/mtransport/test/stunserver.cpp
@@ -75,17 +75,17 @@ nrappkit copyright:
POSSIBILITY OF SUCH DAMAGE.
ekr@rtfm.com Thu Dec 20 20:14:49 2001
*/
#include "logging.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/Unused.h"
-#include "databuffer.h"
+#include "mediapacket.h"
// mozilla/utils.h defines this as well
#ifdef UNIMPLEMENTED
#undef UNIMPLEMENTED
#endif
extern "C" {
#include "nr_api.h"
@@ -387,23 +387,24 @@ void TestStunServer::ShutdownInstance()
struct DeferredStunOperation {
DeferredStunOperation(TestStunServer *server,
const char *data, size_t len,
nr_transport_addr *addr,
nr_socket *sock) :
server_(server),
- buffer_(reinterpret_cast<const uint8_t *>(data), len),
+ buffer_(),
sock_(sock) {
+ buffer_.Copy(reinterpret_cast<const uint8_t *>(data), len);
nr_transport_addr_copy(&addr_, addr);
}
TestStunServer *server_;
- DataBuffer buffer_;
+ MediaPacket buffer_;
nr_transport_addr addr_;
nr_socket *sock_;
};
void TestStunServer::Process(const uint8_t *msg, size_t len, nr_transport_addr *addr, nr_socket *sock) {
if (!sock) {
sock = send_sock_;
--- a/media/mtransport/test/transport_unittests.cpp
+++ b/media/mtransport/test/transport_unittests.cpp
@@ -19,17 +19,17 @@
#include "nspr.h"
#include "nss.h"
#include "ssl.h"
#include "sslproto.h"
#include "nsThreadUtils.h"
#include "nsXPCOM.h"
-#include "databuffer.h"
+#include "mediapacket.h"
#include "dtlsidentity.h"
#include "nricectxhandler.h"
#include "nricemediastream.h"
#include "transportflow.h"
#include "transportlayer.h"
#include "transportlayerdtls.h"
#include "transportlayerice.h"
#include "transportlayerlog.h"
@@ -71,17 +71,17 @@ class TransportLayerDummy : public Trans
virtual ~TransportLayerDummy() {
*destroyed_ = true;
}
nsresult InitInternal() override {
return allow_init_ ? NS_OK : NS_ERROR_FAILURE;
}
- TransportResult SendPacket(const unsigned char *data, size_t len) override {
+ TransportResult SendPacket(MediaPacket& packet) override {
MOZ_CRASH(); // Should never be called.
return 0;
}
TRANSPORT_LAYER_ID("lossy")
private:
bool allow_init_;
@@ -97,48 +97,47 @@ class Inspector {
};
// Class to simulate various kinds of network lossage
class TransportLayerLossy : public TransportLayer {
public:
TransportLayerLossy() : loss_mask_(0), packet_(0), inspector_(nullptr) {}
~TransportLayerLossy () {}
- TransportResult SendPacket(const unsigned char *data, size_t len) override {
- MOZ_MTLOG(ML_NOTICE, LAYER_INFO << "SendPacket(" << len << ")");
+ TransportResult SendPacket(MediaPacket& packet) override {
+ MOZ_MTLOG(ML_NOTICE, LAYER_INFO << "SendPacket(" << packet.len() << ")");
if (loss_mask_ & (1 << (packet_ % 32))) {
MOZ_MTLOG(ML_NOTICE, "Dropping packet");
++packet_;
- return len;
+ return packet.len();
}
if (inspector_) {
- inspector_->Inspect(this, data, len);
+ inspector_->Inspect(this, packet.data(), packet.len());
}
++packet_;
- return downward_->SendPacket(data, len);
+ return downward_->SendPacket(packet);
}
void SetLoss(uint32_t packet) {
loss_mask_ |= (1 << (packet & 32));
}
void SetInspector(UniquePtr<Inspector> inspector) {
inspector_ = std::move(inspector);
}
void StateChange(TransportLayer *layer, State state) {
TL_SET_STATE(state);
}
- void PacketReceived(TransportLayer *layer, const unsigned char *data,
- size_t len) {
- SignalPacketReceived(this, data, len);
+ void PacketReceived(TransportLayer *layer, MediaPacket& packet) {
+ SignalPacketReceived(this, packet);
}
TRANSPORT_LAYER_ID("lossy")
protected:
void WasInserted() override {
downward_->SignalPacketReceived.
connect(this,
@@ -161,17 +160,19 @@ class TransportLayerLossy : public Trans
do { \
EXPECT_GE(remaining(), expected); \
if (remaining() < expected) return false; \
} while(0)
class TlsParser {
public:
TlsParser(const unsigned char *data, size_t len)
- : buffer_(data, len), offset_(0) {}
+ : buffer_(), offset_(0) {
+ buffer_.Copy(data, len);
+ }
bool Read(unsigned char* val) {
if (remaining() < 1) {
return false;
}
*val = *ptr();
consume(1);
return true;
@@ -209,97 +210,97 @@ class TlsParser {
return true;
}
private:
size_t remaining() const { return buffer_.len() - offset_; }
const uint8_t *ptr() const { return buffer_.data() + offset_; }
void consume(size_t len) { offset_ += len; }
- DataBuffer buffer_;
+ MediaPacket buffer_;
size_t offset_;
};
class DtlsRecordParser {
public:
DtlsRecordParser(const unsigned char *data, size_t len)
- : buffer_(data, len), offset_(0) {}
+ : buffer_(), offset_(0) {
+ buffer_.Copy(data, len);
+ }
- bool NextRecord(uint8_t* ct, nsAutoPtr<DataBuffer>* buffer) {
+ bool NextRecord(uint8_t* ct, nsAutoPtr<MediaPacket>* buffer) {
if (!remaining())
return false;
CHECK_LENGTH(13U);
const uint8_t *ctp = reinterpret_cast<const uint8_t *>(ptr());
consume(11); // ct + version + length
const uint16_t *tmp = reinterpret_cast<const uint16_t*>(ptr());
size_t length = ntohs(*tmp);
consume(2);
CHECK_LENGTH(length);
- DataBuffer* db = new DataBuffer(ptr(), length);
+ MediaPacket* db = new MediaPacket;
+ db->Copy(ptr(), length);
consume(length);
*ct = *ctp;
*buffer = db;
return true;
}
private:
size_t remaining() const { return buffer_.len() - offset_; }
const uint8_t *ptr() const { return buffer_.data() + offset_; }
void consume(size_t len) { offset_ += len; }
- DataBuffer buffer_;
+ MediaPacket buffer_;
size_t offset_;
};
// Inspector that parses out DTLS records and passes
// them on.
class DtlsRecordInspector : public Inspector {
public:
virtual void Inspect(TransportLayer* layer,
const unsigned char *data, size_t len) {
DtlsRecordParser parser(data, len);
uint8_t ct;
- nsAutoPtr<DataBuffer> buf;
+ nsAutoPtr<MediaPacket> buf;
while(parser.NextRecord(&ct, &buf)) {
OnRecord(layer, ct, buf->data(), buf->len());
}
}
virtual void OnRecord(TransportLayer* layer,
uint8_t content_type,
const unsigned char *record,
size_t len) = 0;
};
// Inspector that injects arbitrary packets based on
// DTLS records of various types.
class DtlsInspectorInjector : public DtlsRecordInspector {
public:
DtlsInspectorInjector(uint8_t packet_type, uint8_t handshake_type,
- const unsigned char *data, size_t len) :
+ const unsigned char *data, size_t len) :
packet_type_(packet_type),
- handshake_type_(handshake_type),
- injected_(false) {
- data_.reset(new unsigned char[len]);
- memcpy(data_.get(), data, len);
- len_ = len;
+ handshake_type_(handshake_type) {
+ packet_.Copy(data, len);
}
virtual void OnRecord(TransportLayer* layer,
uint8_t content_type,
const unsigned char *data, size_t len) {
// Only inject once.
- if (injected_) {
+ if (!packet_.data()) {
return;
}
// Check that the first byte is as requested.
if (content_type != packet_type_) {
return;
}
@@ -310,25 +311,24 @@ class DtlsInspectorInjector : public Dtl
}
// Check that the handshake type is as requested.
if (data[0] != handshake_type_) {
return;
}
}
- layer->SendPacket(data_.get(), len_);
+ layer->SendPacket(packet_);
+ packet_.Reset();
}
private:
uint8_t packet_type_;
uint8_t handshake_type_;
- bool injected_;
- UniquePtr<unsigned char[]> data_;
- size_t len_;
+ MediaPacket packet_;
};
// Make a copy of the first instance of a message.
class DtlsInspectorRecordHandshakeMessage : public DtlsRecordInspector {
public:
explicit DtlsInspectorRecordHandshakeMessage(uint8_t handshake_type)
: handshake_type_(handshake_type),
buffer_() {}
@@ -377,27 +377,28 @@ class DtlsInspectorRecordHandshakeMessag
}
if ((fragment_offset != 0) || (fragment_length != length)) {
// This shouldn't happen because all current tests where we
// are using this code don't fragment.
return;
}
- buffer_.Allocate(length);
- if (!parser.Read(buffer_.data(), length)) {
+ UniquePtr<uint8_t[]> buffer(new uint8_t[length]);
+ if (!parser.Read(buffer.get(), length)) {
return;
}
+ buffer_.Take(std::move(buffer), length);
}
- const DataBuffer& buffer() { return buffer_; }
+ const MediaPacket& buffer() { return buffer_; }
private:
uint8_t handshake_type_;
- DataBuffer buffer_;
+ MediaPacket buffer_;
};
class TlsServerKeyExchangeECDHE {
public:
bool Parse(const unsigned char* data, size_t len) {
TlsParser parser(data, len);
uint8_t curve_type;
@@ -414,25 +415,26 @@ class TlsServerKeyExchangeECDHE {
return false;
}
uint32_t point_length;
if (!parser.Read(&point_length, 1)) {
return false;
}
- public_key_.Allocate(point_length);
- if (!parser.Read(public_key_.data(), point_length)) {
+ UniquePtr<uint8_t[]> key(new uint8_t[point_length]);
+ if (!parser.Read(key.get(), point_length)) {
return false;
}
+ public_key_.Take(std::move(key), point_length);
return true;
}
- DataBuffer public_key_;
+ MediaPacket public_key_;
};
namespace {
class TransportTestPeer : public sigslot::has_slots<> {
public:
TransportTestPeer(nsCOMPtr<nsIEventTarget> target, std::string name, MtransportTestUtils* utils)
: name_(name), offerer_(name == "P1"), target_(target),
received_packets_(0),received_bytes_(0),flow_(new TransportFlow(name)),
@@ -710,37 +712,47 @@ class TransportTestPeer : public sigslot
// Start checks on the other peer.
test_utils_->sts_target()->Dispatch(
WrapRunnableRet(&res, peer_->ice_ctx_->ctx(), &NrIceCtx::StartChecks,
offerer_),
NS_DISPATCH_SYNC);
ASSERT_TRUE(NS_SUCCEEDED(res));
}
- TransportResult SendPacket(const unsigned char* data, size_t len) {
+ // WrapRunnable/lambda and move semantics (MediaPacket is not copyable) don't
+ // get along yet, so we need a wrapper. Gross.
+ static TransportResult SendPacketWrapper(TransportLayer* layer,
+ MediaPacket* packet) {
+ return layer->SendPacket(*packet);
+ }
+
+ TransportResult SendPacket(MediaPacket& packet) {
TransportResult ret;
+
test_utils_->sts_target()->Dispatch(
- WrapRunnableRet(&ret, dtls_, &TransportLayer::SendPacket, data, len),
+ WrapRunnableNMRet(&ret,
+ &TransportTestPeer::SendPacketWrapper,
+ dtls_,
+ &packet),
NS_DISPATCH_SYNC);
return ret;
}
void StateChanged(TransportLayer *layer, TransportLayer::State state) {
if (state == TransportLayer::TS_OPEN) {
std::cerr << "Now connected" << std::endl;
}
}
- void PacketReceived(TransportLayer* layer, const unsigned char* data,
- size_t len) {
- std::cerr << "Received " << len << " bytes" << std::endl;
+ void PacketReceived(TransportLayer* layer, MediaPacket& packet) {
+ std::cerr << "Received " << packet.len() << " bytes" << std::endl;
++received_packets_;
- received_bytes_ += len;
+ received_bytes_ += packet.len();
}
void SetLoss(uint32_t loss) {
lossy_->SetLoss(loss);
}
void SetCombinePackets(bool combine) {
loopback_->CombinePackets(combine);
@@ -945,17 +957,19 @@ class TransportTest : public MtransportT
ASSERT_TRUE_WAIT(p2_->connected(), 10000);
}
void TransferTest(size_t count, size_t bytes = 1024) {
unsigned char buf[bytes];
for (size_t i= 0; i<count; ++i) {
memset(buf, count & 0xff, sizeof(buf));
- TransportResult rv = p1_->SendPacket(buf, sizeof(buf));
+ MediaPacket packet;
+ packet.Copy(buf, sizeof(buf));
+ TransportResult rv = p1_->SendPacket(packet);
ASSERT_TRUE(rv > 0);
}
std::cerr << "Received == " << p2_->receivedPackets() << " packets" << std::endl;
ASSERT_TRUE_WAIT(count == p2_->receivedPackets(), 10000);
ASSERT_TRUE((count * sizeof(buf)) == p2_->receivedBytes());
}
--- a/media/mtransport/test_nr_socket.h
+++ b/media/mtransport/test_nr_socket.h
@@ -96,16 +96,17 @@ extern "C" {
#include <set>
#include <vector>
#include <map>
#include <list>
#include <string>
#include "mozilla/UniquePtr.h"
#include "prinrval.h"
+#include "mediapacket.h"
namespace mozilla {
class TestNrSocket;
/**
* A group of TestNrSockets that behave as if they were behind the same NAT.
* @note We deliberately avoid addref/release of TestNrSocket here to avoid
@@ -236,24 +237,25 @@ class TestNrSocket : public NrSocketBase
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TestNrSocket, override)
private:
virtual ~TestNrSocket();
class UdpPacket {
public:
UdpPacket(const void *msg, size_t len, const nr_transport_addr &addr) :
- buffer_(new DataBuffer(static_cast<const uint8_t*>(msg), len)) {
+ buffer_(new MediaPacket) {
+ buffer_->Copy(static_cast<const uint8_t*>(msg), len);
// TODO(bug 1170299): Remove const_cast when no longer necessary
nr_transport_addr_copy(&remote_address_,
const_cast<nr_transport_addr*>(&addr));
}
nr_transport_addr remote_address_;
- UniquePtr<DataBuffer> buffer_;
+ UniquePtr<MediaPacket> buffer_;
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(UdpPacket);
private:
~UdpPacket(){}
};
class PortMapping {
public:
@@ -285,24 +287,25 @@ class TestNrSocket : public NrSocketBase
struct DeferredPacket {
DeferredPacket(TestNrSocket *sock,
const void *data, size_t len,
int flags,
nr_transport_addr *addr,
RefPtr<NrSocketBase> internal_socket) :
socket_(sock),
- buffer_(reinterpret_cast<const uint8_t *>(data), len),
+ buffer_(),
flags_(flags),
internal_socket_(internal_socket) {
+ buffer_.Copy(reinterpret_cast<const uint8_t *>(data), len);
nr_transport_addr_copy(&to_, addr);
}
TestNrSocket *socket_;
- DataBuffer buffer_;
+ MediaPacket buffer_;
int flags_;
nr_transport_addr to_;
RefPtr<NrSocketBase> internal_socket_;
};
bool is_port_mapping_stale(const PortMapping &port_mapping) const;
bool allow_ingress(const nr_transport_addr &from,
PortMapping **port_mapping_used) const;
--- a/media/mtransport/transportlayer.h
+++ b/media/mtransport/transportlayer.h
@@ -12,16 +12,17 @@
#include "sigslot.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/RefPtr.h"
#include "nsCOMPtr.h"
#include "nsIEventTarget.h"
#include "m_cpp_utils.h"
+#include "mediapacket.h"
namespace mozilla {
class TransportFlow;
typedef int TransportResult;
enum {
@@ -56,29 +57,28 @@ class TransportLayer : public sigslot::h
virtual void Chain(TransportLayer *downward);
// Downward interface
TransportLayer *downward() { return downward_; }
// Get the state
State state() const { return state_; }
// Must be implemented by derived classes
- virtual TransportResult SendPacket(const unsigned char *data, size_t len) = 0;
+ virtual TransportResult SendPacket(MediaPacket& packet) = 0;
// Get the thread.
const nsCOMPtr<nsIEventTarget> GetThread() const {
return target_;
}
// Event definitions that one can register for
// State has changed
sigslot::signal2<TransportLayer*, State> SignalStateChange;
// Data received on the flow
- sigslot::signal3<TransportLayer*, const unsigned char *, size_t>
- SignalPacketReceived;
+ sigslot::signal2<TransportLayer*, MediaPacket&> SignalPacketReceived;
// Return the layer id for this layer
virtual const std::string id() const = 0;
// The id of the flow
const std::string& flow_id() const {
return flow_id_;
}
--- a/media/mtransport/transportlayerdtls.cpp
+++ b/media/mtransport/transportlayerdtls.cpp
@@ -10,17 +10,16 @@
#include <algorithm>
#include <queue>
#include <sstream>
#include "dtlsidentity.h"
#include "keyhi.h"
#include "logging.h"
-#include "mozilla/Move.h"
#include "mozilla/Telemetry.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/Unused.h"
#include "nsCOMPtr.h"
#include "nsComponentManagerUtils.h"
#include "nsComponentManagerUtils.h"
#include "nsIEventTarget.h"
#include "nsNetCID.h"
@@ -58,66 +57,57 @@ static PRDescIdentity transport_layer_id
// - The TransportLayerNSPRAdapter is a PRFileDesc containing a
// FIFO.
// - When TransportLayerDtls.PacketReceived() is called, we insert
// the packets in the FIFO and then do a PR_Recv() on the NSS
// PRFileDesc, which eventually reads off the FIFO.
//
// All of this stuff is assumed to happen solely in a single thread
// (generally the SocketTransportService thread)
-struct Packet {
- Packet() : data_(nullptr), len_(0) {}
- void Assign(const void *data, int32_t len) {
- data_.reset(new uint8_t[len]);
- memcpy(data_.get(), data, len);
- len_ = len;
- }
-
- UniquePtr<uint8_t[]> data_;
- int32_t len_;
-};
-
-void TransportLayerNSPRAdapter::PacketReceived(const void *data, int32_t len) {
+void TransportLayerNSPRAdapter::PacketReceived(MediaPacket& packet) {
if (enabled_) {
- input_.push(new Packet());
- input_.back()->Assign(data, len);
+ input_.push(new MediaPacket(std::move(packet)));
}
}
int32_t TransportLayerNSPRAdapter::Recv(void *buf, int32_t buflen) {
if (input_.empty()) {
PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
return -1;
}
- Packet* front = input_.front();
- if (buflen < front->len_) {
+ MediaPacket* front = input_.front();
+ int32_t count = static_cast<int32_t>(front->len());
+
+ if (buflen < count) {
MOZ_ASSERT(false, "Not enough buffer space to receive into");
PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0);
return -1;
}
- int32_t count = front->len_;
- memcpy(buf, front->data_.get(), count);
+ memcpy(buf, front->data(), count);
input_.pop();
delete front;
return count;
}
int32_t TransportLayerNSPRAdapter::Write(const void *buf, int32_t length) {
if (!enabled_) {
MOZ_MTLOG(ML_WARNING, "Writing to disabled transport layer");
return -1;
}
- TransportResult r = output_->SendPacket(
- static_cast<const unsigned char *>(buf), length);
+ MediaPacket packet;
+ // Copies. Oh well.
+ packet.Copy(static_cast<const uint8_t*>(buf), static_cast<size_t>(length));
+
+ TransportResult r = output_->SendPacket(packet);
if (r >= 0) {
return r;
}
if (r == TE_WOULDBLOCK) {
PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
} else {
PR_SetError(PR_IO_ERROR, 0);
@@ -984,51 +974,64 @@ bool TransportLayerDtls::CheckAlpn() {
return false;
}
alpn_ = chosen;
return true;
}
void TransportLayerDtls::PacketReceived(TransportLayer* layer,
- const unsigned char *data,
- size_t len) {
+ MediaPacket& packet) {
CheckThread();
- MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "PacketReceived(" << len << ")");
+ MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "PacketReceived(" << packet.len() << ")");
if (state_ != TS_CONNECTING && state_ != TS_OPEN) {
MOZ_MTLOG(ML_DEBUG,
LAYER_INFO << "Discarding packet in inappropriate state");
return;
}
- // not DTLS per RFC 7983
- if (data[0] < 20 || data[0] > 63) {
+ if (!packet.data()) {
+ // Something ate this, probably the SRTP layer
return;
}
- nspr_io_adapter_->PacketReceived(data, len);
+ // not DTLS per RFC 7983
+ if (packet.data()[0] < 20 || packet.data()[0] > 63) {
+ return;
+ }
+ nspr_io_adapter_->PacketReceived(packet);
+ GetDecryptedPackets();
+}
+
+void
+TransportLayerDtls::GetDecryptedPackets()
+{
// If we're still connecting, try to handshake
if (state_ == TS_CONNECTING) {
Handshake();
}
// Now try a recv if we're open, since there might be data left
if (state_ == TS_OPEN) {
- // nICEr uses a 9216 bytes buffer to allow support for jumbo frames
- unsigned char buf[9216];
int32_t rv;
// One packet might contain several DTLS packets
do {
- rv = PR_Recv(ssl_fd_.get(), buf, sizeof(buf), 0, PR_INTERVAL_NO_WAIT);
+ // nICEr uses a 9216 bytes buffer to allow support for jumbo frames
+ // Can we peek to get a better idea of the actual size?
+ static const size_t kBufferSize = 9216;
+ auto buffer = MakeUnique<uint8_t[]>(kBufferSize);
+ rv = PR_Recv(ssl_fd_.get(), buffer.get(), kBufferSize, 0, PR_INTERVAL_NO_WAIT);
if (rv > 0) {
// We have data
MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Read " << rv << " bytes from NSS");
- SignalPacketReceived(this, buf, rv);
+ MediaPacket packet;
+ packet.Take(std::move(buffer), static_cast<size_t>(rv));
+ SignalPacketReceived(this, packet);
} else if (rv == 0) {
TL_SET_STATE(TS_CLOSED);
} else {
int32_t err = PR_GetError();
if (err == PR_WOULD_BLOCK_ERROR) {
// This gets ignored
MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Receive would have blocked");
@@ -1064,26 +1067,26 @@ void TransportLayerDtls::SetState(State
}
} else {
MOZ_ASSERT(false, "Invalid state transition");
}
TransportLayer::SetState(state, file, line);
}
-TransportResult TransportLayerDtls::SendPacket(const unsigned char *data,
- size_t len) {
+TransportResult TransportLayerDtls::SendPacket(MediaPacket& packet) {
CheckThread();
if (state_ != TS_OPEN) {
MOZ_MTLOG(ML_ERROR, LAYER_INFO << "Can't call SendPacket() in state "
<< state_);
return TE_ERROR;
}
- int32_t rv = PR_Send(ssl_fd_.get(), data, len, 0, PR_INTERVAL_NO_WAIT);
+ int32_t rv = PR_Send(ssl_fd_.get(), packet.data(), packet.len(), 0,
+ PR_INTERVAL_NO_WAIT);
if (rv > 0) {
// We have data
MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Wrote " << rv << " bytes to SSL Layer");
return rv;
}
if (rv == 0) {
--- a/media/mtransport/transportlayerdtls.h
+++ b/media/mtransport/transportlayerdtls.h
@@ -31,26 +31,26 @@ struct Packet;
class TransportLayerNSPRAdapter {
public:
explicit TransportLayerNSPRAdapter(TransportLayer *output) :
output_(output),
input_(),
enabled_(true) {}
- void PacketReceived(const void *data, int32_t len);
+ void PacketReceived(MediaPacket& packet);
int32_t Recv(void *buf, int32_t buflen);
int32_t Write(const void *buf, int32_t length);
void SetEnabled(bool enabled) { enabled_ = enabled; }
private:
DISALLOW_COPY_ASSIGN(TransportLayerNSPRAdapter);
TransportLayer *output_;
- std::queue<Packet *> input_;
+ std::queue<MediaPacket *> input_;
bool enabled_;
};
class TransportLayerDtls final : public TransportLayer {
public:
TransportLayerDtls() :
role_(CLIENT),
verification_mode_(VERIFY_UNSET),
@@ -89,22 +89,21 @@ class TransportLayerDtls final : public
bool use_context,
const std::string& context,
unsigned char *out,
unsigned int outlen);
// Transport layer overrides.
nsresult InitInternal() override;
void WasInserted() override;
- TransportResult SendPacket(const unsigned char *data, size_t len) override;
+ TransportResult SendPacket(MediaPacket& packet) override;
// Signals
void StateChange(TransportLayer *layer, State state);
- void PacketReceived(TransportLayer* layer, const unsigned char *data,
- size_t len);
+ void PacketReceived(TransportLayer* layer, MediaPacket& packet);
// For testing use only. Returns the fd.
PRFileDesc* internal_fd() { CheckThread(); return ssl_fd_.get(); }
TRANSPORT_LAYER_ID("dtls")
protected:
void SetState(State state, const char *file, unsigned line) override;
@@ -134,16 +133,17 @@ class TransportLayerDtls final : public
~VerificationDigest() {}
DISALLOW_COPY_ASSIGN(VerificationDigest);
};
bool Setup();
bool SetupCipherSuites(UniquePRFileDesc& ssl_fd) const;
bool SetupAlpn(UniquePRFileDesc& ssl_fd) const;
+ void GetDecryptedPackets();
void Handshake();
bool CheckAlpn();
static SECStatus GetClientAuthDataHook(void *arg, PRFileDesc *fd,
CERTDistNames *caNames,
CERTCertificate **pRetCert,
SECKEYPrivateKey **pRetKey);
--- a/media/mtransport/transportlayerice.cpp
+++ b/media/mtransport/transportlayerice.cpp
@@ -166,32 +166,31 @@ void TransportLayerIce::RestoreOldStream
} else if (stream_->state() == NrIceMediaStream::ICE_CLOSED) {
IceFailed(stream_);
}
// No events are fired when the stream is ICE_CONNECTING. If the
// restored stream is ICE_CONNECTING, IceReady/IceFailed will fire
// later.
}
-TransportResult TransportLayerIce::SendPacket(const unsigned char *data,
- size_t len) {
+TransportResult TransportLayerIce::SendPacket(MediaPacket& packet) {
CheckThread();
// use old_stream_ until stream_ is ready
nsresult res = (old_stream_?old_stream_:stream_)->SendPacket(component_,
- data,
- len);
+ packet.data(),
+ packet.len());
if (!NS_SUCCEEDED(res)) {
return (res == NS_BASE_STREAM_WOULD_BLOCK) ?
TE_WOULDBLOCK : TE_ERROR;
}
- MOZ_MTLOG(ML_DEBUG, LAYER_INFO << " SendPacket(" << len << ") succeeded");
+ MOZ_MTLOG(ML_DEBUG, LAYER_INFO << " SendPacket(" << packet.len() << ") succeeded");
- return len;
+ return packet.len();
}
void TransportLayerIce::IceCandidate(NrIceMediaStream *stream,
const std::string&) {
// NO-OP for now
}
@@ -222,12 +221,17 @@ void TransportLayerIce::IcePacketReceive
CheckThread();
// We get packets for both components, so ignore the ones that aren't
// for us.
if (component_ != component)
return;
MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "PacketReceived(" << stream->name() << ","
<< component << "," << len << ")");
- SignalPacketReceived(this, data, len);
+ // Might be useful to allow MediaPacket to borrow a buffer (ie; not take
+ // ownership, but copy it if the MediaPacket is moved). This could be a
+ // footgun though with MediaPackets that end up on the heap.
+ MediaPacket packet;
+ packet.Copy(data, len);
+ SignalPacketReceived(this, packet);
}
} // close namespace
--- a/media/mtransport/transportlayerice.h
+++ b/media/mtransport/transportlayerice.h
@@ -36,17 +36,17 @@ class TransportLayerIce : public Transpo
void SetParameters(RefPtr<NrIceMediaStream> stream,
int component);
void ResetOldStream(); // called after successful ice restart
void RestoreOldStream(); // called after unsuccessful ice restart
// Transport layer overrides.
- TransportResult SendPacket(const unsigned char *data, size_t len) override;
+ TransportResult SendPacket(MediaPacket& packet) override;
// Slots for ICE
void IceCandidate(NrIceMediaStream *stream, const std::string&);
void IceReady(NrIceMediaStream *stream);
void IceFailed(NrIceMediaStream *stream);
void IcePacketReceived(NrIceMediaStream *stream, int component,
const unsigned char *data, int len);
--- a/media/mtransport/transportlayerlog.cpp
+++ b/media/mtransport/transportlayerlog.cpp
@@ -20,34 +20,31 @@ void TransportLayerLogging::WasInserted(
this, &TransportLayerLogging::StateChange);
downward_->SignalPacketReceived.connect(
this, &TransportLayerLogging::PacketReceived);
TL_SET_STATE(downward_->state());
}
}
TransportResult
-TransportLayerLogging::SendPacket(const unsigned char *data, size_t len) {
- MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "SendPacket(" << len << ")");
+TransportLayerLogging::SendPacket(MediaPacket& packet) {
+ MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "SendPacket(" << packet.len() << ")");
if (downward_) {
- return downward_->SendPacket(data, len);
+ return downward_->SendPacket(packet);
}
- return static_cast<TransportResult>(len);
+ return static_cast<TransportResult>(packet.len());
}
void TransportLayerLogging::StateChange(TransportLayer *layer, State state) {
MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Received StateChange to " << state);
TL_SET_STATE(state);
}
void TransportLayerLogging::PacketReceived(TransportLayer* layer,
- const unsigned char *data,
- size_t len) {
- MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "PacketReceived(" << len << ")");
+ MediaPacket& packet) {
+ MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "PacketReceived(" << packet.len() << ")");
- SignalPacketReceived(this, data, len);
+ SignalPacketReceived(this, packet);
}
-
-
} // close namespace
--- a/media/mtransport/transportlayerlog.h
+++ b/media/mtransport/transportlayerlog.h
@@ -15,22 +15,21 @@
namespace mozilla {
class TransportLayerLogging : public TransportLayer {
public:
TransportLayerLogging() {}
// Overrides for TransportLayer
- TransportResult SendPacket(const unsigned char *data, size_t len) override;
+ TransportResult SendPacket(MediaPacket& packet) override;
// Signals (forwarded to upper layer)
void StateChange(TransportLayer *layer, State state);
- void PacketReceived(TransportLayer* layer, const unsigned char *data,
- size_t len);
+ void PacketReceived(TransportLayer* layer, MediaPacket& packet);
TRANSPORT_LAYER_ID("log")
protected:
void WasInserted() override;
private:
DISALLOW_COPY_ASSIGN(TransportLayerLogging);
--- a/media/mtransport/transportlayerloopback.cpp
+++ b/media/mtransport/transportlayerloopback.cpp
@@ -55,70 +55,67 @@ nsresult TransportLayerLoopback::Init()
// Connect to the other side
void TransportLayerLoopback::Connect(TransportLayerLoopback* peer) {
peer_ = peer;
TL_SET_STATE(TS_OPEN);
}
TransportResult
-TransportLayerLoopback::SendPacket(const unsigned char *data, size_t len) {
- MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "SendPacket(" << len << ")");
+TransportLayerLoopback::SendPacket(MediaPacket& packet) {
+ MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "SendPacket(" << packet.len() << ")");
if (!peer_) {
MOZ_MTLOG(ML_ERROR, "Discarding packet because peer not attached");
return TE_ERROR;
}
- nsresult res = peer_->QueuePacket(data, len);
+ size_t len = packet.len();
+ nsresult res = peer_->QueuePacket(packet);
if (!NS_SUCCEEDED(res))
return TE_ERROR;
return static_cast<TransportResult>(len);
}
-nsresult TransportLayerLoopback::QueuePacket(const unsigned char *data,
- size_t len) {
+nsresult TransportLayerLoopback::QueuePacket(MediaPacket& packet) {
MOZ_ASSERT(packets_lock_);
PR_Lock(packets_lock_);
if (combinePackets_ && !packets_.empty()) {
- QueuedPacket *packet = packets_.front();
- packets_.pop();
+ MediaPacket *prevPacket = packets_.front();
- MOZ_MTLOG(ML_DEBUG, LAYER_INFO << " Enqueuing combined packets of length " << packet->len() << " and " << len);
- packets_.push(new QueuedPacket());
- packets_.back()->Assign(packet->data(), packet->len(),
- data, len);
+ MOZ_MTLOG(ML_DEBUG, LAYER_INFO << " Enqueuing combined packets of length " << prevPacket->len() << " and " << packet.len());
+ auto combined = MakeUnique<uint8_t[]>(prevPacket->len() + packet.len());
+ memcpy(combined.get(), prevPacket->data(), prevPacket->len());
+ memcpy(combined.get() + prevPacket->len(), packet.data(), packet.len());
+ prevPacket->Take(std::move(combined), prevPacket->len() + packet.len());
} else {
- MOZ_MTLOG(ML_DEBUG, LAYER_INFO << " Enqueuing packet of length " << len);
- packets_.push(new QueuedPacket());
- packets_.back()->Assign(data, len);
+ MOZ_MTLOG(ML_DEBUG, LAYER_INFO << " Enqueuing packet of length " << packet.len());
+ packets_.push(new MediaPacket(std::move(packet)));
}
PRStatus r = PR_Unlock(packets_lock_);
MOZ_ASSERT(r == PR_SUCCESS);
if (r != PR_SUCCESS)
return NS_ERROR_FAILURE;
return NS_OK;
}
void TransportLayerLoopback::DeliverPackets() {
while (!packets_.empty()) {
- QueuedPacket *packet = packets_.front();
+ UniquePtr<MediaPacket> packet(packets_.front());
packets_.pop();
MOZ_MTLOG(ML_DEBUG, LAYER_INFO << " Delivering packet of length " <<
packet->len());
- SignalPacketReceived(this, packet->data(), packet->len());
-
- delete packet;
+ SignalPacketReceived(this, *packet);
}
}
NS_IMPL_ISUPPORTS(TransportLayerLoopback::Deliverer, nsITimerCallback, nsINamed)
NS_IMETHODIMP TransportLayerLoopback::Deliverer::Notify(nsITimer *timer) {
if (!layer_)
return NS_OK;
--- a/media/mtransport/transportlayerloopback.h
+++ b/media/mtransport/transportlayerloopback.h
@@ -37,17 +37,17 @@ class TransportLayerLoopback : public Tr
timer_(nullptr),
packets_(),
packets_lock_(nullptr),
deliverer_(nullptr),
combinePackets_(false) {}
~TransportLayerLoopback() {
while (!packets_.empty()) {
- QueuedPacket *packet = packets_.front();
+ MediaPacket *packet = packets_.front();
packets_.pop();
delete packet;
}
if (packets_lock_) {
PR_DestroyLock(packets_lock_);
}
timer_->Cancel();
deliverer_->Detach();
@@ -67,61 +67,26 @@ class TransportLayerLoopback : public Tr
if (peer) {
peer->Disconnect();
}
}
void CombinePackets(bool combine) { combinePackets_ = combine; }
// Overrides for TransportLayer
- TransportResult SendPacket(const unsigned char *data, size_t len) override;
+ TransportResult SendPacket(MediaPacket& packet) override;
// Deliver queued packets
void DeliverPackets();
TRANSPORT_LAYER_ID("loopback")
private:
DISALLOW_COPY_ASSIGN(TransportLayerLoopback);
- // A queued packet
- class QueuedPacket {
- public:
- QueuedPacket() : data_(nullptr), len_(0) {}
- ~QueuedPacket() {
- delete [] data_;
- }
-
- void Assign(const unsigned char *data, size_t len) {
- data_ = new unsigned char[len];
- memcpy(static_cast<void *>(data_),
- static_cast<const void *>(data), len);
- len_ = len;
- }
-
- void Assign(const unsigned char *data1, size_t len1,
- const unsigned char *data2, size_t len2) {
- data_ = new unsigned char[len1 + len2];
- memcpy(static_cast<void *>(data_),
- static_cast<const void *>(data1), len1);
- memcpy(static_cast<void *>(data_ + len1),
- static_cast<const void *>(data2), len2);
- len_ = len1 + len2;
- }
-
- const unsigned char *data() const { return data_; }
- size_t len() const { return len_; }
-
- private:
- DISALLOW_COPY_ASSIGN(QueuedPacket);
-
- unsigned char *data_;
- size_t len_;
- };
-
// A timer to deliver packets if some are available
// Fires every 100 ms
class Deliverer : public nsITimerCallback
, public nsINamed {
public:
explicit Deliverer(TransportLayerLoopback *layer) :
layer_(layer) {}
void Detach() {
@@ -137,20 +102,20 @@ class TransportLayerLoopback : public Tr
}
DISALLOW_COPY_ASSIGN(Deliverer);
TransportLayerLoopback *layer_;
};
// Queue a packet for delivery
- nsresult QueuePacket(const unsigned char *data, size_t len);
+ nsresult QueuePacket(MediaPacket& packet);
TransportLayerLoopback* peer_;
nsCOMPtr<nsITimer> timer_;
- std::queue<QueuedPacket *> packets_;
+ std::queue<MediaPacket *> packets_;
PRLock *packets_lock_;
RefPtr<Deliverer> deliverer_;
bool combinePackets_;
};
} // close namespace
#endif
--- a/media/mtransport/transportlayersrtp.cpp
+++ b/media/mtransport/transportlayersrtp.cpp
@@ -9,17 +9,16 @@
#include "transportlayersrtp.h"
#include "transportlayerdtls.h"
#include "logging.h"
#include "nsError.h"
#include "mozilla/Assertions.h"
#include "transportlayerdtls.h"
#include "srtp.h"
-#include "databuffer.h"
#include "nsAutoPtr.h"
namespace mozilla {
MOZ_MTLOG_MODULE("mtransport")
static char kDTLSExporterLabel[] = "EXTRACTOR-dtls_srtp";
@@ -52,95 +51,95 @@ TransportLayerSrtp::Setup()
}
// downward_ is the TransportLayerIce
downward_->SignalPacketReceived.connect(this, &TransportLayerSrtp::PacketReceived);
return true;
}
-static bool
-IsRtp(const unsigned char* aData, size_t aLen)
+static bool IsRtp(const unsigned char* data, size_t len)
{
- if (aLen < 2)
+ if (len < 2)
return false;
// Check if this is a RTCP packet. Logic based on the types listed in
// media/webrtc/trunk/src/modules/rtp_rtcp/source/rtp_utility.cc
// Anything outside this range is RTP.
- if ((aData[1] < 192) || (aData[1] > 207))
+ if ((data[1] < 192) || (data[1] > 207))
return true;
- if (aData[1] == 192) // FIR
+ if (data[1] == 192) // FIR
return false;
- if (aData[1] == 193) // NACK, but could also be RTP. This makes us sad
+ if (data[1] == 193) // NACK, but could also be RTP. This makes us sad
return true; // but it's how webrtc.org behaves.
- if (aData[1] == 194)
+ if (data[1] == 194)
return true;
- if (aData[1] == 195) // IJ.
+ if (data[1] == 195) // IJ.
return false;
- if ((aData[1] > 195) && (aData[1] < 200)) // the > 195 is redundant
+ if ((data[1] > 195) && (data[1] < 200)) // the > 195 is redundant
return true;
- if ((aData[1] >= 200) && (aData[1] <= 207)) // SR, RR, SDES, BYE,
+ if ((data[1] >= 200) && (data[1] <= 207)) // SR, RR, SDES, BYE,
return false; // APP, RTPFB, PSFB, XR
MOZ_ASSERT(false); // Not reached, belt and suspenders.
return true;
}
TransportResult
-TransportLayerSrtp::SendPacket(const unsigned char* data, size_t len)
+TransportLayerSrtp::SendPacket(MediaPacket& packet)
{
- if (len < 4) {
+ if (packet.len() < 4) {
MOZ_ASSERT(false);
return TE_ERROR;
}
- // Make copy and add some room to expand.
- nsAutoPtr<DataBuffer> buf(
- new DataBuffer(data, len, len + SRTP_MAX_EXPANSION));
+ MOZ_ASSERT(packet.capacity() - packet.len() >= SRTP_MAX_EXPANSION);
int out_len;
nsresult res;
- if (IsRtp(data, len)) {
- MOZ_MTLOG(ML_INFO, "Attempting to protect RTP...");
- res = mSendSrtp->ProtectRtp(
- buf->data(), buf->len(), buf->capacity(), &out_len);
- } else {
- MOZ_MTLOG(ML_INFO, "Attempting to protect RTCP...");
- res = mSendSrtp->ProtectRtcp(
- buf->data(), buf->len(), buf->capacity(), &out_len);
+ switch (packet.type()) {
+ case MediaPacket::RTP:
+ MOZ_MTLOG(ML_INFO, "Attempting to protect RTP...");
+ res = mSendSrtp->ProtectRtp(packet.data(), packet.len(), packet.capacity(), &out_len);
+ break;
+ case MediaPacket::RTCP:
+ MOZ_MTLOG(ML_INFO, "Attempting to protect RTCP...");
+ res = mSendSrtp->ProtectRtcp(packet.data(), packet.len(), packet.capacity(), &out_len);
+ break;
+ default:
+ MOZ_CRASH("SRTP layer asked to send packet that is neither RTP or RTCP");
}
if (NS_FAILED(res)) {
MOZ_MTLOG(ML_ERROR,
- "Error protecting RTP/RTCP len=" << len
+ "Error protecting RTP/RTCP len=" << packet.len()
<< "[" << std::hex
- << buf->data()[0] << " "
- << buf->data()[1] << " "
- << buf->data()[2] << " "
- << buf->data()[3]
+ << packet.data()[0] << " "
+ << packet.data()[1] << " "
+ << packet.data()[2] << " "
+ << packet.data()[3]
<< "]");
return TE_ERROR;
}
- // paranoia; don't have uninitialized bytes included in data->len()
- buf->SetLength(out_len);
+ size_t unencrypted_len = packet.len();
+ packet.SetLength(out_len);
- TransportResult bytes = downward_->SendPacket(buf->data(), buf->len());
- if (bytes == static_cast<int>(buf->len())) {
+ TransportResult bytes = downward_->SendPacket(packet);
+ if (bytes == out_len) {
// Whole packet was written, but the encrypted length might be different.
// Don't confuse the caller.
- return len;
+ return unencrypted_len;
}
if (bytes == TE_WOULDBLOCK) {
return TE_WOULDBLOCK;
}
return TE_ERROR;
}
@@ -212,56 +211,63 @@ TransportLayerSrtp::StateChange(Transpor
MOZ_MTLOG(ML_INFO, "Created SRTP flow!");
}
TL_SET_STATE(state);
}
void
-TransportLayerSrtp::PacketReceived(TransportLayer* layer,
- const unsigned char *data,
- size_t len)
+TransportLayerSrtp::PacketReceived(TransportLayer* layer, MediaPacket& packet)
{
if (state() != TS_OPEN) {
return;
}
- if (len < 4) {
+ if (!packet.data()) {
+ // Something ate this, probably the DTLS layer
+ return;
+ }
+
+ if (packet.len() < 4) {
return;
}
// not RTP/RTCP per RFC 7983
- if (data[0] <= 127 || data[0] >= 192) {
+ if (packet.data()[0] <= 127 || packet.data()[0] >= 192) {
return;
}
- // Make a copy rather than cast away constness
- auto innerData = MakeUnique<unsigned char[]>(len);
- memcpy(innerData.get(), data, len);
+ // We want to keep the encrypted packet around for packet dumping
+ packet.CopyDataToEncrypted();
int outLen;
nsresult res;
- if (IsRtp(innerData.get(), len)) {
+ if (IsRtp(packet.data(), packet.len())) {
+ packet.SetType(MediaPacket::RTP);
MOZ_MTLOG(ML_INFO, "Attempting to unprotect RTP...");
- res = mRecvSrtp->UnprotectRtp(innerData.get(), len, len, &outLen);
+ res = mRecvSrtp->UnprotectRtp(packet.data(), packet.len(), packet.len(), &outLen);
} else {
+ packet.SetType(MediaPacket::RTCP);
MOZ_MTLOG(ML_INFO, "Attempting to unprotect RTCP...");
- res = mRecvSrtp->UnprotectRtcp(innerData.get(), len, len, &outLen);
+ res = mRecvSrtp->UnprotectRtcp(packet.data(), packet.len(), packet.len(), &outLen);
}
if (NS_SUCCEEDED(res)) {
- SignalPacketReceived(this, innerData.get(), outLen);
+ packet.SetLength(outLen);
+ SignalPacketReceived(this, packet);
} else {
+ // TODO: What do we do wrt packet dumping here? Maybe signal an empty
+ // packet? Signal the still-encrypted packet?
MOZ_MTLOG(ML_ERROR,
- "Error unprotecting RTP/RTCP len=" << len
+ "Error unprotecting RTP/RTCP len=" << packet.len()
<< "[" << std::hex
- << innerData[0] << " "
- << innerData[1] << " "
- << innerData[2] << " "
- << innerData[3]
+ << packet.data()[0] << " "
+ << packet.data()[1] << " "
+ << packet.data()[2] << " "
+ << packet.data()[3]
<< "]");
}
}
} // namespace mozilla
--- a/media/mtransport/transportlayersrtp.h
+++ b/media/mtransport/transportlayersrtp.h
@@ -19,22 +19,21 @@ class TransportLayerDtls;
class TransportLayerSrtp final : public TransportLayer {
public:
explicit TransportLayerSrtp(TransportLayerDtls& dtls);
virtual ~TransportLayerSrtp() {};
// Transport layer overrides.
void WasInserted() override;
- TransportResult SendPacket(const unsigned char *data, size_t len) override;
+ TransportResult SendPacket(MediaPacket& packet) override;
// Signals
void StateChange(TransportLayer *layer, State state);
- void PacketReceived(TransportLayer* layer, const unsigned char *data,
- size_t len);
+ void PacketReceived(TransportLayer* layer, MediaPacket& packet);
TRANSPORT_LAYER_ID("srtp")
private:
bool Setup();
DISALLOW_COPY_ASSIGN(TransportLayerSrtp);
RefPtr<SrtpFlow> mSendSrtp;
RefPtr<SrtpFlow> mRecvSrtp;
--- a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
+++ b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
@@ -25,17 +25,16 @@
#include "MediaStreamGraphImpl.h"
#include "MediaStreamListener.h"
#include "MediaStreamTrack.h"
#include "MediaStreamVideoSink.h"
#include "RtpLogger.h"
#include "VideoSegment.h"
#include "VideoStreamTrack.h"
#include "VideoUtils.h"
-#include "databuffer.h"
#include "libyuv/convert.h"
#include "mozilla/PeerIdentity.h"
#include "mozilla/Preferences.h"
#include "mozilla/SharedThreadPool.h"
#include "mozilla/Sprintf.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/UniquePtrExtensions.h"
#include "mozilla/dom/RTCStatsReportBinding.h"
@@ -918,32 +917,18 @@ MediaPipeline::TransportReady_s(Transpor
ToString(aInfo.mType));
if (mDirection == DirectionType::RECEIVE) {
CSFLogInfo(LOGTAG,
"Listening for %s packets received on %p",
ToString(aInfo.mType),
aInfo.mSrtp);
- switch (aInfo.mType) {
- case RTP:
- aInfo.mSrtp->SignalPacketReceived.connect(
- this, &MediaPipeline::RtpPacketReceived);
- break;
- case RTCP:
- aInfo.mSrtp->SignalPacketReceived.connect(
- this, &MediaPipeline::RtcpPacketReceived);
- break;
- case MUX:
- aInfo.mSrtp->SignalPacketReceived.connect(
- this, &MediaPipeline::PacketReceived);
- break;
- default:
- MOZ_CRASH();
- }
+ aInfo.mSrtp->SignalPacketReceived.connect(
+ this, &MediaPipeline::PacketReceived);
}
aInfo.mState = StateType::MP_OPEN;
UpdateRtcpMuxState(aInfo);
return NS_OK;
}
nsresult
@@ -973,24 +958,24 @@ MediaPipeline::UpdateRtcpMuxState(Transp
if (aInfo.mType == MUX) {
if (aInfo.mTransport == mRtcp.mTransport) {
mRtcp.mState = aInfo.mState;
}
}
}
nsresult
-MediaPipeline::SendPacket(TransportLayer* aLayer, const void* aData, int aLen)
+MediaPipeline::SendPacket(TransportLayer* aLayer, MediaPacket& packet)
{
ASSERT_ON_THREAD(mStsThread);
- TransportResult res =
- aLayer->SendPacket(static_cast<const unsigned char*>(aData), aLen);
+ int len = packet.len();
+ TransportResult res = aLayer->SendPacket(packet);
- if (res != aLen) {
+ if (res != len) {
// Ignore blocking indications
if (res == TE_WOULDBLOCK)
return NS_OK;
CSFLogError(LOGTAG, "Failed write on stream %s", mDescription.c_str());
return NS_BASE_STREAM_CLOSED;
}
@@ -1057,19 +1042,17 @@ MediaPipeline::IncrementRtcpPacketsRecei
mDescription.c_str(),
this,
static_cast<void*>(mRtp.mTransport),
mRtcpPacketsReceived);
}
}
void
-MediaPipeline::RtpPacketReceived(TransportLayer* aLayer,
- const unsigned char* aData,
- size_t aLen)
+MediaPipeline::RtpPacketReceived(TransportLayer* aLayer, MediaPacket& packet)
{
if (mDirection == DirectionType::TRANSMIT) {
return;
}
if (!mTransport->Pipeline()) {
CSFLogError(LOGTAG, "Discarding incoming packet; transport disconnected");
return;
@@ -1085,27 +1068,22 @@ MediaPipeline::RtpPacketReceived(Transpo
return;
}
if (mRtp.mSrtp->state() != TransportLayer::TS_OPEN) {
CSFLogError(LOGTAG, "Discarding incoming packet; transport not open");
return;
}
- if (!aLen) {
- return;
- }
-
- // Filter out everything but RTP/RTCP
- if (aData[0] < 128 || aData[0] > 191) {
+ if (!packet.len()) {
return;
}
webrtc::RTPHeader header;
- if (!mRtpParser->Parse(aData, aLen, &header, true)) {
+ if (!mRtpParser->Parse(packet.data(), packet.len(), &header, true)) {
return;
}
if (mFilter && !mFilter->Filter(header)) {
return;
}
// Make sure to only get the time once, and only if we need it by
@@ -1141,36 +1119,36 @@ MediaPipeline::RtpPacketReceived(Transpo
mCsrcStats.insert(std::make_pair(
header.arrOfCSRCs[i], RtpCSRCStats(header.arrOfCSRCs[i], now)));
} else {
csrcInfo->second.SetTimestamp(now);
}
}
}
- mPacketDumper->Dump(mLevel, dom::mozPacketDumpType::Srtp, false, aData, aLen);
-
CSFLogDebug(LOGTAG, "%s received RTP packet.", mDescription.c_str());
- IncrementRtpPacketsReceived(aLen);
+ IncrementRtpPacketsReceived(packet.len());
OnRtpPacketReceived();
- RtpLogger::LogPacket(
- aData, aLen, true, true, header.headerLength, mDescription);
+ RtpLogger::LogPacket(packet, true, header.headerLength, mDescription);
+
+ // Might be nice to pass ownership of the buffer in this case, but it is a
+ // small optimization in a rare case.
+ mPacketDumper->Dump(
+ mLevel, dom::mozPacketDumpType::Srtp, false, packet.encrypted_data(), packet.encrypted_len());
mPacketDumper->Dump(
- mLevel, dom::mozPacketDumpType::Rtp, false, aData, aLen);
+ mLevel, dom::mozPacketDumpType::Rtp, false, packet.data(), packet.len());
(void)mConduit->ReceivedRTPPacket(
- aData, aLen, header.ssrc); // Ignore error codes
+ packet.data(), packet.len(), header.ssrc); // Ignore error codes
}
void
-MediaPipeline::RtcpPacketReceived(TransportLayer* aLayer,
- const unsigned char* aData,
- size_t aLen)
+MediaPipeline::RtcpPacketReceived(TransportLayer* aLayer, MediaPacket& packet)
{
if (!mTransport->Pipeline()) {
CSFLogDebug(LOGTAG, "Discarding incoming packet; transport disconnected");
return;
}
if (!mConduit) {
CSFLogDebug(LOGTAG, "Discarding incoming packet; media disconnected");
@@ -1182,94 +1160,60 @@ MediaPipeline::RtcpPacketReceived(Transp
return;
}
if (mRtcp.mSrtp->state() != TransportLayer::TS_OPEN) {
CSFLogError(LOGTAG, "Discarding incoming packet; transport not open");
return;
}
- if (!aLen) {
- return;
- }
-
- // Filter out everything but RTP/RTCP
- if (aData[0] < 128 || aData[0] > 191) {
+ if (!packet.len()) {
return;
}
// We do not filter receiver reports, since the webrtc.org code for
// senders already has logic to ignore RRs that do not apply.
// TODO bug 1279153: remove SR check for reduced size RTCP
- if (mFilter && !mFilter->FilterSenderReport(aData, aLen)) {
+ if (mFilter && !mFilter->FilterSenderReport(packet.data(), packet.len())) {
CSFLogWarn(LOGTAG, "Dropping incoming RTCP packet; filtered out");
return;
}
- mPacketDumper->Dump(mLevel, dom::mozPacketDumpType::Srtcp, false, aData, aLen);
-
CSFLogDebug(LOGTAG, "%s received RTCP packet.", mDescription.c_str());
IncrementRtcpPacketsReceived();
- RtpLogger::LogPacket(aData, aLen, true, false, 0, mDescription);
-
- mPacketDumper->Dump(mLevel, dom::mozPacketDumpType::Rtcp, false, aData, aLen);
-
- (void)mConduit->ReceivedRTCPPacket(aData, aLen); // Ignore error codes
-}
-
-bool
-MediaPipeline::IsRtp(const unsigned char* aData, size_t aLen) const
-{
- if (aLen < 2)
- return false;
-
- // Check if this is a RTCP packet. Logic based on the types listed in
- // media/webrtc/trunk/src/modules/rtp_rtcp/source/rtp_utility.cc
-
- // Anything outside this range is RTP.
- if ((aData[1] < 192) || (aData[1] > 207))
- return true;
+ RtpLogger::LogPacket(packet, true, 0, mDescription);
- if (aData[1] == 192) // FIR
- return false;
-
- if (aData[1] == 193) // NACK, but could also be RTP. This makes us sad
- return true; // but it's how webrtc.org behaves.
-
- if (aData[1] == 194)
- return true;
+ // Might be nice to pass ownership of the buffer in this case, but it is a
+ // small optimization in a rare case.
+ mPacketDumper->Dump(
+ mLevel, dom::mozPacketDumpType::Srtcp, false, packet.encrypted_data(), packet.encrypted_len());
- if (aData[1] == 195) // IJ.
- return false;
-
- if ((aData[1] > 195) && (aData[1] < 200)) // the > 195 is redundant
- return true;
+ mPacketDumper->Dump(mLevel, dom::mozPacketDumpType::Rtcp, false, packet.data(), packet.len());
- if ((aData[1] >= 200) && (aData[1] <= 207)) // SR, RR, SDES, BYE,
- return false; // APP, RTPFB, PSFB, XR
-
- MOZ_ASSERT(false); // Not reached, belt and suspenders.
- return true;
+ (void)mConduit->ReceivedRTCPPacket(packet.data(), packet.len()); // Ignore error codes
}
void
-MediaPipeline::PacketReceived(TransportLayer* aLayer,
- const unsigned char* aData,
- size_t aLen)
+MediaPipeline::PacketReceived(TransportLayer* aLayer, MediaPacket& packet)
{
if (!mTransport->Pipeline()) {
CSFLogDebug(LOGTAG, "Discarding incoming packet; transport disconnected");
return;
}
- if (IsRtp(aData, aLen)) {
- RtpPacketReceived(aLayer, aData, aLen);
- } else {
- RtcpPacketReceived(aLayer, aData, aLen);
+ switch (packet.type()) {
+ case MediaPacket::RTP:
+ RtpPacketReceived(aLayer, packet);
+ break;
+ case MediaPacket::RTCP:
+ RtcpPacketReceived(aLayer, packet);
+ break;
+ default:
+ MOZ_CRASH("TransportLayerSrtp let something other than RTP/RTCP through");
}
}
class MediaPipelineTransmit::PipelineListener : public MediaStreamVideoSink
{
friend class MediaPipelineTransmit;
public:
@@ -1659,101 +1603,101 @@ MediaPipeline::GetTransportInfo_s(Transp
}
return nullptr;
}
nsresult
MediaPipeline::PipelineTransport::SendRtpPacket(const uint8_t* aData, size_t aLen)
{
- // Might be nice to avoid this copy.
- nsAutoPtr<DataBuffer> buf(new DataBuffer(aData, aLen));
+ nsAutoPtr<MediaPacket> packet(new MediaPacket);
+ packet->Copy(aData, aLen, aLen + SRTP_MAX_EXPANSION);
+ packet->SetType(MediaPacket::RTP);
RUN_ON_THREAD(
mStsThread,
WrapRunnable(RefPtr<MediaPipeline::PipelineTransport>(this),
&MediaPipeline::PipelineTransport::SendRtpRtcpPacket_s,
- buf,
- true),
+ packet),
NS_DISPATCH_NORMAL);
return NS_OK;
}
nsresult
MediaPipeline::PipelineTransport::SendRtpRtcpPacket_s(
- nsAutoPtr<DataBuffer> aData,
- bool aIsRtp)
+ nsAutoPtr<MediaPacket> aPacket)
{
+ bool isRtp = aPacket->type() == MediaPacket::RTP;
+
ASSERT_ON_THREAD(mStsThread);
if (!mPipeline) {
return NS_OK; // Detached
}
- TransportInfo& transport = aIsRtp ? mPipeline->mRtp : mPipeline->mRtcp;
+
+ TransportInfo& transport = isRtp ? mPipeline->mRtp : mPipeline->mRtcp;
if (transport.mSrtp->state() != TransportLayer::TS_OPEN) {
// SRTP not ready yet.
return NS_OK;
}
MOZ_ASSERT(transport.mTransport);
NS_ENSURE_TRUE(transport.mTransport, NS_ERROR_NULL_POINTER);
+ MediaPacket packet(std::move(*aPacket));
+ packet.sdp_level() = Some(mPipeline->Level());
+
if (RtpLogger::IsPacketLoggingOn()) {
int headerLen = 12;
webrtc::RTPHeader header;
if (mPipeline->mRtpParser &&
- mPipeline->mRtpParser->Parse(aData->data(), aData->len(), &header)) {
+ mPipeline->mRtpParser->Parse(packet.data(), packet.len(), &header)) {
headerLen = header.headerLength;
}
- RtpLogger::LogPacket(aData->data(),
- aData->len(),
- false,
- aIsRtp,
- headerLen,
- mPipeline->mDescription);
+ RtpLogger::LogPacket(packet, false, headerLen, mPipeline->mDescription);
}
- if (aIsRtp) {
+ if (isRtp) {
mPipeline->mPacketDumper->Dump(mPipeline->Level(),
dom::mozPacketDumpType::Rtp,
true,
- aData->data(),
- aData->len());
- mPipeline->IncrementRtpPacketsSent(aData->len());
+ packet.data(),
+ packet.len());
+ mPipeline->IncrementRtpPacketsSent(packet.len());
} else {
mPipeline->mPacketDumper->Dump(mPipeline->Level(),
dom::mozPacketDumpType::Rtcp,
true,
- aData->data(),
- aData->len());
+ packet.data(),
+ packet.len());
mPipeline->IncrementRtcpPacketsSent();
}
CSFLogDebug(LOGTAG,
"%s sending %s packet",
mPipeline->mDescription.c_str(),
- (aIsRtp ? "RTP" : "RTCP"));
+ (isRtp ? "RTP" : "RTCP"));
- return mPipeline->SendPacket(transport.mSrtp, aData->data(), aData->len());
+ return mPipeline->SendPacket(transport.mSrtp, packet);
}
nsresult
MediaPipeline::PipelineTransport::SendRtcpPacket(const uint8_t* aData,
size_t aLen)
{
- // Might be nice to avoid this copy.
- nsAutoPtr<DataBuffer> buf(new DataBuffer(aData, aLen));
+ nsAutoPtr<MediaPacket> packet(new MediaPacket);
+ packet->Copy(aData, aLen, aLen + SRTP_MAX_EXPANSION);
+ packet->SetType(MediaPacket::RTCP);
RUN_ON_THREAD(
mStsThread,
WrapRunnable(RefPtr<MediaPipeline::PipelineTransport>(this),
&MediaPipeline::PipelineTransport::SendRtpRtcpPacket_s,
- buf,
- false),
+ packet),
NS_DISPATCH_NORMAL);
return NS_OK;
}
// Called if we're attached with AddDirectListener()
void
MediaPipelineTransmit::PipelineListener::NotifyRealtimeTrackData(
--- a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.h
+++ b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.h
@@ -11,17 +11,17 @@
#include <map>
#include "sigslot.h"
#include "signaling/src/media-conduit/MediaConduitInterface.h"
#include "mozilla/ReentrantMonitor.h"
#include "mozilla/Atomics.h"
#include "SrtpFlow.h"
-#include "databuffer.h"
+#include "mediapacket.h"
#include "mtransport/runnable_utils.h"
#include "mtransport/transportflow.h"
#include "AudioPacketizer.h"
#include "StreamTracks.h"
#include "signaling/src/peerconnection/PacketDumper.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
@@ -194,17 +194,17 @@ public:
void Attach(MediaPipeline* pipeline) { mPipeline = pipeline; }
void Detach() { mPipeline = nullptr; }
MediaPipeline* Pipeline() const { return mPipeline; }
virtual nsresult SendRtpPacket(const uint8_t* aData, size_t aLen) override;
virtual nsresult SendRtcpPacket(const uint8_t* aData, size_t aLen) override;
private:
- nsresult SendRtpRtcpPacket_s(nsAutoPtr<DataBuffer> aData, bool aIsRtp);
+ nsresult SendRtpRtcpPacket_s(nsAutoPtr<MediaPacket> aData);
// Creates a cycle, which we break with Detach
RefPtr<MediaPipeline> mPipeline;
const nsCOMPtr<nsIEventTarget> mStsThread;
};
protected:
virtual ~MediaPipeline();
@@ -245,30 +245,23 @@ protected:
void IncrementRtpPacketsSent(int aBytes);
void IncrementRtcpPacketsSent();
void IncrementRtpPacketsReceived(int aBytes);
virtual void OnRtpPacketReceived() {};
void IncrementRtcpPacketsReceived();
virtual nsresult SendPacket(TransportLayer* aLayer,
- const void* aData,
- int aLen);
+ MediaPacket& packet);
// Process slots on transports
void StateChange(TransportLayer* aLayer, TransportLayer::State);
- void RtpPacketReceived(TransportLayer* aLayer,
- const unsigned char* aData,
- size_t aLen);
- void RtcpPacketReceived(TransportLayer* aLayer,
- const unsigned char* aData,
- size_t aLen);
- void PacketReceived(TransportLayer* aLayer,
- const unsigned char* aData,
- size_t aLen);
+ void RtpPacketReceived(TransportLayer* aLayer, MediaPacket& packet);
+ void RtcpPacketReceived(TransportLayer* aLayer, MediaPacket& packet);
+ void PacketReceived(TransportLayer* aLayer, MediaPacket& packet);
void SetDescription_s(const std::string& description);
const DirectionType mDirection;
size_t mLevel;
RefPtr<MediaSessionConduit> mConduit; // Our conduit. Written on the main
// thread. Read on STS thread.
--- a/media/webrtc/signaling/src/mediapipeline/RtpLogger.cpp
+++ b/media/webrtc/signaling/src/mediapipeline/RtpLogger.cpp
@@ -28,18 +28,19 @@ static const char* rlLogTag = "RtpLogger
#define LOGTAG rlLogTag
namespace mozilla {
bool RtpLogger::IsPacketLoggingOn() {
return CSFLogTestLevel(CSF_LOG_DEBUG);
}
-void RtpLogger::LogPacket(const unsigned char *data, int len, bool input,
- bool isRtp, int headerLength, std::string desc) {
+void RtpLogger::LogPacket(const MediaPacket& packet, bool input,
+ size_t headerLength, std::string desc) {
+ bool isRtp = (packet.type() == MediaPacket::RTP);
if (CSFLogTestLevel(CSF_LOG_DEBUG)) {
std::stringstream ss;
/* This creates text2pcap compatible format, e.g.:
* O 10:36:26.864934 000000 80 c8 00 06 6d ... RTCP_PACKET
*/
ss << (input ? "I " : "O ");
std::time_t t = std::time(nullptr);
std::tm tm = *std::localtime(&t);
@@ -54,27 +55,27 @@ void RtpLogger::LogPacket(const unsigned
ss << "." << (tb.millitm) << " ";
#else
struct timeval tv;
gettimeofday(&tv, NULL);
ss << "." << (tv.tv_usec) << " ";
#endif
ss << " 000000";
ss << std::hex << std::setfill('0');
- int offset_ = headerLength;
- if (isRtp && (offset_ + 5 < len)) {
+ size_t offset_ = headerLength;
+ if (isRtp && (offset_ + 5 < packet.len())) {
// Allow the first 5 bytes of the payload in clear
offset_ += 5;
}
- for (int i=0; i < len; ++i) {
+ for (size_t i=0; i < packet.len(); ++i) {
if (isRtp && i > offset_) {
ss << " 00";
}
else {
- ss << " " << std::setw(2) << (int)data[i];
+ ss << " " << std::setw(2) << (int)packet.data()[i];
}
}
CSFLogDebug(LOGTAG, "%s%s%s", ss.str().c_str(),
(isRtp ? " RTP_PACKET " : " RTCP_PACKET "), desc.c_str());
}
}
} // end of namespace
--- a/media/webrtc/signaling/src/mediapipeline/RtpLogger.h
+++ b/media/webrtc/signaling/src/mediapipeline/RtpLogger.h
@@ -3,26 +3,27 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
// Original author: nohlmeier@mozilla.com
#ifndef rtplogger_h__
#define rtplogger_h__
#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
+#include "mtransport/mediapacket.h"
namespace mozilla {
/* This class logs RTP and RTCP packets in hex in a format compatible to
* text2pcap.
* Example to convert the MOZ log file into a PCAP file:
* egrep '(RTP_PACKET|RTCP_PACKET)' moz.log | text2pcap -D -n -l 1 -i 17 -u 1234,1235 -t '%H:%M:%S.' - rtp.pcap
*/
class RtpLogger {
public:
static bool IsPacketLoggingOn();
- static void LogPacket(const unsigned char *data, int len, bool input,
- bool isRtp, int headerLength, std::string desc);
+ static void LogPacket(const MediaPacket& packet, bool input,
+ size_t headerLength, std::string desc);
};
} // End of namespace
#endif
copy from media/mtransport/transportlayersrtp.cpp
copy to media/webrtc/signaling/src/mediapipeline/TransportLayerPacketDumper.cpp
--- a/media/mtransport/transportlayersrtp.cpp
+++ b/media/webrtc/signaling/src/mediapipeline/TransportLayerPacketDumper.cpp
@@ -1,267 +1,77 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* 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/. */
// Original author: ekr@rtfm.com
-#include "transportlayersrtp.h"
-#include "transportlayerdtls.h"
+#include "TransportLayerPacketDumper.h"
#include "logging.h"
#include "nsError.h"
#include "mozilla/Assertions.h"
-#include "transportlayerdtls.h"
-#include "srtp.h"
-#include "databuffer.h"
-#include "nsAutoPtr.h"
namespace mozilla {
MOZ_MTLOG_MODULE("mtransport")
-static char kDTLSExporterLabel[] = "EXTRACTOR-dtls_srtp";
-
-TransportLayerSrtp::TransportLayerSrtp(TransportLayerDtls& dtls)
-{
- // We need to connect to the dtls layer, not the ice layer, because even
- // though the packets that DTLS decrypts don't flow through us, we do base our
- // keying information on the keying information established by the DTLS layer.
- dtls.SignalStateChange.connect(this, &TransportLayerSrtp::StateChange);
-
- TL_SET_STATE(dtls.state());
-}
+TransportLayerPacketDumper::TransportLayerPacketDumper(
+ nsAutoPtr<PacketDumper>&& aPacketDumper, dom::mozPacketDumpType aType) :
+ mPacketDumper(std::move(aPacketDumper)),
+ mType(aType)
+{}
void
-TransportLayerSrtp::WasInserted()
-{
- // Connect to the lower layers
- if (!Setup()) {
- TL_SET_STATE(TS_ERROR);
- }
-}
-
-bool
-TransportLayerSrtp::Setup()
+TransportLayerPacketDumper::WasInserted()
{
CheckThread();
if (!downward_) {
- MOZ_MTLOG(ML_ERROR, "SRTP layer with nothing below. This is useless");
- return false;
+ MOZ_MTLOG(ML_ERROR, "Packet dumper with nothing below. This is useless");
+ TL_SET_STATE(TS_ERROR);
}
- // downward_ is the TransportLayerIce
- downward_->SignalPacketReceived.connect(this, &TransportLayerSrtp::PacketReceived);
-
- return true;
-}
-
-static bool
-IsRtp(const unsigned char* aData, size_t aLen)
-{
- if (aLen < 2)
- return false;
-
- // Check if this is a RTCP packet. Logic based on the types listed in
- // media/webrtc/trunk/src/modules/rtp_rtcp/source/rtp_utility.cc
-
- // Anything outside this range is RTP.
- if ((aData[1] < 192) || (aData[1] > 207))
- return true;
-
- if (aData[1] == 192) // FIR
- return false;
-
- if (aData[1] == 193) // NACK, but could also be RTP. This makes us sad
- return true; // but it's how webrtc.org behaves.
-
- if (aData[1] == 194)
- return true;
-
- if (aData[1] == 195) // IJ.
- return false;
-
- if ((aData[1] > 195) && (aData[1] < 200)) // the > 195 is redundant
- return true;
-
- if ((aData[1] >= 200) && (aData[1] <= 207)) // SR, RR, SDES, BYE,
- return false; // APP, RTPFB, PSFB, XR
-
- MOZ_ASSERT(false); // Not reached, belt and suspenders.
- return true;
+ downward_->SignalStateChange.connect(this,
+ &TransportLayerPacketDumper::StateChange);
+ downward_->SignalPacketReceived.connect(this,
+ &TransportLayerPacketDumper::PacketReceived);
}
TransportResult
-TransportLayerSrtp::SendPacket(const unsigned char* data, size_t len)
+TransportLayerPacketDumper::SendPacket(MediaPacket& packet)
{
- if (len < 4) {
- MOZ_ASSERT(false);
- return TE_ERROR;
- }
-
- // Make copy and add some room to expand.
- nsAutoPtr<DataBuffer> buf(
- new DataBuffer(data, len, len + SRTP_MAX_EXPANSION));
-
- int out_len;
- nsresult res;
- if (IsRtp(data, len)) {
- MOZ_MTLOG(ML_INFO, "Attempting to protect RTP...");
- res = mSendSrtp->ProtectRtp(
- buf->data(), buf->len(), buf->capacity(), &out_len);
- } else {
- MOZ_MTLOG(ML_INFO, "Attempting to protect RTCP...");
- res = mSendSrtp->ProtectRtcp(
- buf->data(), buf->len(), buf->capacity(), &out_len);
- }
+ if (packet.sdp_level().isSome()) {
+ dom::mozPacketDumpType dumpType = mType;
+ if (mType == dom::mozPacketDumpType::Srtp &&
+ packet.type() == MediaPacket::RTCP) {
+ dumpType = dom::mozPacketDumpType::Srtcp;
+ }
- if (NS_FAILED(res)) {
- MOZ_MTLOG(ML_ERROR,
- "Error protecting RTP/RTCP len=" << len
- << "[" << std::hex
- << buf->data()[0] << " "
- << buf->data()[1] << " "
- << buf->data()[2] << " "
- << buf->data()[3]
- << "]");
- return TE_ERROR;
+ mPacketDumper->Dump(*packet.sdp_level(),
+ dumpType,
+ true,
+ packet.data(),
+ packet.len());
}
-
- // paranoia; don't have uninitialized bytes included in data->len()
- buf->SetLength(out_len);
-
- TransportResult bytes = downward_->SendPacket(buf->data(), buf->len());
- if (bytes == static_cast<int>(buf->len())) {
- // Whole packet was written, but the encrypted length might be different.
- // Don't confuse the caller.
- return len;
- }
-
- if (bytes == TE_WOULDBLOCK) {
- return TE_WOULDBLOCK;
- }
-
- return TE_ERROR;
+ return downward_->SendPacket(packet);
}
void
-TransportLayerSrtp::StateChange(TransportLayer* layer, State state)
+TransportLayerPacketDumper::StateChange(TransportLayer* aLayer, State aState)
{
- if (state == TS_OPEN) {
- TransportLayerDtls* dtls = static_cast<TransportLayerDtls*>(layer);
- MOZ_ASSERT(dtls); // DTLS is mandatory
-
- uint16_t cipher_suite;
- nsresult res = dtls->GetSrtpCipher(&cipher_suite);
- if (NS_FAILED(res)) {
- MOZ_MTLOG(ML_ERROR, "Failed to negotiate DTLS-SRTP. This is an error");
- TL_SET_STATE(TS_ERROR);
- return;
- }
-
- // SRTP Key Exporter as per RFC 5764 S 4.2
- unsigned char srtp_block[SRTP_TOTAL_KEY_LENGTH * 2];
- res = dtls->ExportKeyingMaterial(
- kDTLSExporterLabel, false, "", srtp_block, sizeof(srtp_block));
- if (NS_FAILED(res)) {
- MOZ_MTLOG(ML_ERROR, "Failed to compute DTLS-SRTP keys. This is an error");
- TL_SET_STATE(TS_ERROR);
- return;
- }
-
- // Slice and dice as per RFC 5764 S 4.2
- unsigned char client_write_key[SRTP_TOTAL_KEY_LENGTH];
- unsigned char server_write_key[SRTP_TOTAL_KEY_LENGTH];
- int offset = 0;
- memcpy(client_write_key, srtp_block + offset, SRTP_MASTER_KEY_LENGTH);
- offset += SRTP_MASTER_KEY_LENGTH;
- memcpy(server_write_key, srtp_block + offset, SRTP_MASTER_KEY_LENGTH);
- offset += SRTP_MASTER_KEY_LENGTH;
- memcpy(client_write_key + SRTP_MASTER_KEY_LENGTH,
- srtp_block + offset,
- SRTP_MASTER_SALT_LENGTH);
- offset += SRTP_MASTER_SALT_LENGTH;
- memcpy(server_write_key + SRTP_MASTER_KEY_LENGTH,
- srtp_block + offset,
- SRTP_MASTER_SALT_LENGTH);
- offset += SRTP_MASTER_SALT_LENGTH;
- MOZ_ASSERT(offset == sizeof(srtp_block));
-
- unsigned char* write_key;
- unsigned char* read_key;
-
- if (dtls->role() == TransportLayerDtls::CLIENT) {
- write_key = client_write_key;
- read_key = server_write_key;
- } else {
- write_key = server_write_key;
- read_key = client_write_key;
- }
-
- MOZ_ASSERT(!mSendSrtp && !mRecvSrtp);
- mSendSrtp =
- SrtpFlow::Create(cipher_suite, false, write_key, SRTP_TOTAL_KEY_LENGTH);
- mRecvSrtp =
- SrtpFlow::Create(cipher_suite, true, read_key, SRTP_TOTAL_KEY_LENGTH);
- if (!mSendSrtp || !mRecvSrtp) {
- MOZ_MTLOG(ML_ERROR, "Couldn't create SRTP flow.");
- TL_SET_STATE(TS_ERROR);
- return;
- }
-
- MOZ_MTLOG(ML_INFO, "Created SRTP flow!");
- }
-
- TL_SET_STATE(state);
+ TL_SET_STATE(aState);
}
void
-TransportLayerSrtp::PacketReceived(TransportLayer* layer,
- const unsigned char *data,
- size_t len)
+TransportLayerPacketDumper::PacketReceived(TransportLayer* aLayer,
+ MediaPacket& packet)
{
- if (state() != TS_OPEN) {
- return;
- }
-
- if (len < 4) {
- return;
- }
-
- // not RTP/RTCP per RFC 7983
- if (data[0] <= 127 || data[0] >= 192) {
- return;
- }
-
- // Make a copy rather than cast away constness
- auto innerData = MakeUnique<unsigned char[]>(len);
- memcpy(innerData.get(), data, len);
- int outLen;
- nsresult res;
-
- if (IsRtp(innerData.get(), len)) {
- MOZ_MTLOG(ML_INFO, "Attempting to unprotect RTP...");
- res = mRecvSrtp->UnprotectRtp(innerData.get(), len, len, &outLen);
- } else {
- MOZ_MTLOG(ML_INFO, "Attempting to unprotect RTCP...");
- res = mRecvSrtp->UnprotectRtcp(innerData.get(), len, len, &outLen);
- }
-
- if (NS_SUCCEEDED(res)) {
- SignalPacketReceived(this, innerData.get(), outLen);
- } else {
- MOZ_MTLOG(ML_ERROR,
- "Error unprotecting RTP/RTCP len=" << len
- << "[" << std::hex
- << innerData[0] << " "
- << innerData[1] << " "
- << innerData[2] << " "
- << innerData[3]
- << "]");
- }
+ // There's no way to know the level yet, so we can't use the packet dumper
+ // yet. We rely on the SRTP layer saving the encrypted packet in
+ // MediaPacket::encrypted_, to allow MediaPipeline to dump it later.
+ SignalPacketReceived(this, packet);
}
} // namespace mozilla
copy from media/mtransport/transportlayersrtp.h
copy to media/webrtc/signaling/src/mediapipeline/TransportLayerPacketDumper.h
--- a/media/mtransport/transportlayersrtp.h
+++ b/media/webrtc/signaling/src/mediapipeline/TransportLayerPacketDumper.h
@@ -1,45 +1,40 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* 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/. */
-#ifndef transportlayersrtp_h__
-#define transportlayersrtp_h__
-
-#include <string>
+#ifndef transportlayerpacketdumper_h__
+#define transportlayerpacketdumper_h__
#include "transportlayer.h"
-#include "mozilla/RefPtr.h"
-#include "SrtpFlow.h"
+#include "signaling/src/peerconnection/PacketDumper.h"
+#include "mozilla/dom/RTCPeerConnectionBinding.h"
namespace mozilla {
-class TransportLayerDtls;
-
-class TransportLayerSrtp final : public TransportLayer {
+class TransportLayerPacketDumper final : public TransportLayer {
public:
- explicit TransportLayerSrtp(TransportLayerDtls& dtls);
- virtual ~TransportLayerSrtp() {};
+ explicit TransportLayerPacketDumper(nsAutoPtr<PacketDumper>&& aPacketDumper,
+ dom::mozPacketDumpType aType);
+ virtual ~TransportLayerPacketDumper() {};
// Transport layer overrides.
void WasInserted() override;
- TransportResult SendPacket(const unsigned char *data, size_t len) override;
+ TransportResult SendPacket(MediaPacket& packet) override;
// Signals
- void StateChange(TransportLayer *layer, State state);
- void PacketReceived(TransportLayer* layer, const unsigned char *data,
- size_t len);
+ void StateChange(TransportLayer *aLayer, State state);
+ void PacketReceived(TransportLayer* aLayer, MediaPacket& packet);
- TRANSPORT_LAYER_ID("srtp")
+ TRANSPORT_LAYER_ID("packet-dumper")
private:
- bool Setup();
- DISALLOW_COPY_ASSIGN(TransportLayerSrtp);
- RefPtr<SrtpFlow> mSendSrtp;
- RefPtr<SrtpFlow> mRecvSrtp;
+ DISALLOW_COPY_ASSIGN(TransportLayerPacketDumper);
+ nsAutoPtr<PacketDumper> mPacketDumper;
+ dom::mozPacketDumpType mType;
};
} // close namespace
#endif
--- a/media/webrtc/signaling/src/mediapipeline/moz.build
+++ b/media/webrtc/signaling/src/mediapipeline/moz.build
@@ -18,11 +18,12 @@ LOCAL_INCLUDES += [
'/netwerk/srtp/src/crypto/include',
'/netwerk/srtp/src/include',
]
UNIFIED_SOURCES += [
'MediaPipeline.cpp',
'MediaPipelineFilter.cpp',
'RtpLogger.cpp',
+ 'TransportLayerPacketDumper.cpp',
]
FINAL_LIBRARY = 'xul'
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
@@ -17,16 +17,18 @@
#include "PeerConnectionImpl.h"
#include "PeerConnectionMedia.h"
#include "runnable_utils.h"
#include "transportlayerice.h"
#include "transportlayerdtls.h"
#include "transportlayersrtp.h"
#include "signaling/src/jsep/JsepSession.h"
#include "signaling/src/jsep/JsepTransport.h"
+#include "signaling/src/mediapipeline/TransportLayerPacketDumper.h"
+#include "signaling/src/peerconnection/PacketDumper.h"
#include "nsContentUtils.h"
#include "nsNetCID.h"
#include "nsNetUtil.h"
#include "nsIURI.h"
#include "nsIScriptSecurityManager.h"
#include "nsICancelable.h"
#include "nsILoadInfo.h"
@@ -523,32 +525,39 @@ PeerConnectionMedia::UpdateTransportFlow
return UpdateTransportFlow(transportLevel, true, *aTransceiver.mTransport);
}
// Accessing the PCMedia should be safe here because we shouldn't
// have enqueued this function unless it was still active and
// the ICE data is destroyed on the STS.
static void
FinalizeTransportFlow_s(RefPtr<PeerConnectionMedia> aPCMedia,
+ nsAutoPtr<PacketDumper> aPacketDumper,
RefPtr<TransportFlow> aFlow, size_t aLevel,
bool aIsRtcp,
TransportLayerIce* aIceLayer,
TransportLayerDtls* aDtlsLayer,
TransportLayerSrtp* aSrtpLayer)
{
+ TransportLayerPacketDumper* srtpDumper(new TransportLayerPacketDumper(
+ std::move(aPacketDumper), dom::mozPacketDumpType::Srtp));
+
aIceLayer->SetParameters(aPCMedia->ice_media_stream(aLevel),
aIsRtcp ? 2 : 1);
// TODO(bug 854518): Process errors.
(void)aIceLayer->Init();
(void)aDtlsLayer->Init();
+ (void)srtpDumper->Init();
(void)aSrtpLayer->Init();
aDtlsLayer->Chain(aIceLayer);
- aSrtpLayer->Chain(aIceLayer);
+ srtpDumper->Chain(aIceLayer);
+ aSrtpLayer->Chain(srtpDumper);
aFlow->PushLayer(aIceLayer);
aFlow->PushLayer(aDtlsLayer);
+ aFlow->PushLayer(srtpDumper);
aFlow->PushLayer(aSrtpLayer);
}
static void
AddNewIceStreamForRestart_s(RefPtr<PeerConnectionMedia> aPCMedia,
RefPtr<TransportFlow> aFlow,
size_t aLevel,
bool aIsRtcp)
@@ -651,19 +660,22 @@ PeerConnectionMedia::UpdateTransportFlow
alpn.insert(alpnDefault);
}
rv = dtls->SetAlpn(alpn, alpnDefault);
if (NS_FAILED(rv)) {
CSFLogError(LOGTAG, "Couldn't set ALPN");
return rv;
}
+ nsAutoPtr<PacketDumper> packetDumper(new PacketDumper(mParent));
+
RefPtr<PeerConnectionMedia> pcMedia(this);
rv = GetSTSThread()->Dispatch(
- WrapRunnableNM(FinalizeTransportFlow_s, pcMedia, flow, aLevel, aIsRtcp,
+ WrapRunnableNM(FinalizeTransportFlow_s, pcMedia, packetDumper, flow,
+ aLevel, aIsRtcp,
ice.release(), dtls.release(), srtp.release()),
NS_DISPATCH_NORMAL);
if (NS_FAILED(rv)) {
CSFLogError(LOGTAG, "Failed to dispatch FinalizeTransportFlow_s");
return rv;
}
AddTransportFlow(aLevel, aIsRtcp, flow);
--- a/netwerk/sctp/datachannel/DataChannel.cpp
+++ b/netwerk/sctp/datachannel/DataChannel.cpp
@@ -812,87 +812,79 @@ DataChannelConnection::ProcessQueuedOpen
// OpenFinish returns a reference itself, so we need to take it can Release it
channel = OpenFinish(channel.forget()); // may reset the flag and re-push
} else {
NS_ASSERTION(false, "How did a DataChannel get queued without the FINISH_OPEN flag?");
}
}
}
+
void
-DataChannelConnection::SctpDtlsInput(TransportLayer *layer,
- const unsigned char *data, size_t len)
+DataChannelConnection::SctpDtlsInput(TransportLayer *layer, MediaPacket& packet)
{
if (MOZ_LOG_TEST(gSCTPLog, LogLevel::Debug)) {
char *buf;
- if ((buf = usrsctp_dumppacket((void *)data, len, SCTP_DUMP_INBOUND)) != nullptr) {
+ if ((buf = usrsctp_dumppacket((void *)packet.data(),
+ packet.len(),
+ SCTP_DUMP_INBOUND)) != nullptr) {
SCTP_LOG(("%s", buf));
usrsctp_freedumpbuffer(buf);
}
}
// Pass the data to SCTP
MutexAutoLock lock(mLock);
- usrsctp_conninput(static_cast<void *>(this), data, len, 0);
+ usrsctp_conninput(static_cast<void *>(this), packet.data(), packet.len(), 0);
}
int
-DataChannelConnection::SendPacket(unsigned char data[], size_t len, bool release)
+DataChannelConnection::SendPacket(nsAutoPtr<MediaPacket> packet)
{
//LOG(("%p: SCTP/DTLS sent %ld bytes", this, len));
- int res = 0;
if (mDtls) {
- res = mDtls->SendPacket(data, len) < 0 ? 1 : 0;
+ return mDtls->SendPacket(*packet) < 0 ? 1 : 0;
}
- if (release)
- delete [] data;
- return res;
+ return 0;
}
/* static */
int
DataChannelConnection::SctpDtlsOutput(void *addr, void *buffer, size_t length,
uint8_t tos, uint8_t set_df)
{
DataChannelConnection *peer = static_cast<DataChannelConnection *>(addr);
- int res;
MOZ_DIAGNOSTIC_ASSERT(!peer->mShutdown);
if (MOZ_LOG_TEST(gSCTPLog, LogLevel::Debug)) {
char *buf;
if ((buf = usrsctp_dumppacket(buffer, length, SCTP_DUMP_OUTBOUND)) != nullptr) {
SCTP_LOG(("%s", buf));
usrsctp_freedumpbuffer(buf);
}
}
+
// We're async proxying even if on the STSThread because this is called
// with internal SCTP locks held in some cases (such as in usrsctp_connect()).
// SCTP has an option for Apple, on IP connections only, to release at least
// one of the locks before calling a packet output routine; with changes to
// the underlying SCTP stack this might remove the need to use an async proxy.
- if ((false /*peer->IsSTSThread()*/)) {
- res = peer->SendPacket(static_cast<unsigned char *>(buffer), length, false);
- } else {
- auto *data = new unsigned char[length];
- memcpy(data, buffer, length);
- // Commented out since we have to Dispatch SendPacket to avoid deadlock"
- // res = -1;
-
- // XXX It might be worthwhile to add an assertion against the thread
- // somehow getting into the DataChannel/SCTP code again, as
- // DISPATCH_SYNC is not fully blocking. This may be tricky, as it
- // needs to be a per-thread check, not a global.
- peer->mSTS->Dispatch(WrapRunnable(
- RefPtr<DataChannelConnection>(peer),
- &DataChannelConnection::SendPacket, data, length, true),
- NS_DISPATCH_NORMAL);
- res = 0; // cheat! Packets can always be dropped later anyways
- }
- return res;
+ nsAutoPtr<MediaPacket> packet(new MediaPacket);
+ packet->Copy(static_cast<const uint8_t*>(buffer), length);
+
+ // XXX It might be worthwhile to add an assertion against the thread
+ // somehow getting into the DataChannel/SCTP code again, as
+ // DISPATCH_SYNC is not fully blocking. This may be tricky, as it
+ // needs to be a per-thread check, not a global.
+ peer->mSTS->Dispatch(WrapRunnable(
+ RefPtr<DataChannelConnection>(peer),
+ &DataChannelConnection::SendPacket, packet),
+ NS_DISPATCH_NORMAL);
+ return 0; // cheat! Packets can always be dropped later anyways
}
#endif
#ifdef ALLOW_DIRECT_SCTP_LISTEN_CONNECT
// listen for incoming associations
// Blocks! - Don't call this from main thread!
#error This code will not work as-is since SetEvenOdd() runs on Mainthread
--- a/netwerk/sctp/datachannel/DataChannel.h
+++ b/netwerk/sctp/datachannel/DataChannel.h
@@ -236,18 +236,18 @@ protected:
// Use from main thread only as WeakPtr is not threadsafe
WeakPtr<DataConnectionListener> mListener;
private:
friend class DataChannelConnectRunnable;
#ifdef SCTP_DTLS_SUPPORTED
static void DTLSConnectThread(void *data);
- int SendPacket(unsigned char data[], size_t len, bool release);
- void SctpDtlsInput(TransportLayer *layer, const unsigned char *data, size_t len);
+ int SendPacket(nsAutoPtr<MediaPacket> packet);
+ void SctpDtlsInput(TransportLayer *layer, MediaPacket& packet);
static int SctpDtlsOutput(void *addr, void *buffer, size_t length, uint8_t tos, uint8_t set_df);
#endif
DataChannel* FindChannelByStream(uint16_t stream);
uint16_t FindFreeStream();
bool RequestMoreStreams(int32_t aNeeded = 16);
uint32_t UpdateCurrentStreamIndex();
uint32_t GetCurrentStreamIndex();
int SendControlMessage(const uint8_t *data, uint32_t len, uint16_t stream);