transportlayerloopback.cpp (3421B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 // Original author: ekr@rtfm.com 8 9 #include "transportlayerloopback.h" 10 11 #include "logging.h" 12 #include "nsNetCID.h" 13 #include "nsServiceManagerUtils.h" 14 #include "nsString.h" 15 #include "prlock.h" 16 17 namespace mozilla { 18 19 MOZ_MTLOG_MODULE("mtransport") 20 21 nsresult TransportLayerLoopback::Init() { 22 nsresult rv; 23 target_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv); 24 MOZ_ASSERT(NS_SUCCEEDED(rv)); 25 if (!NS_SUCCEEDED(rv)) return rv; 26 27 timer_ = NS_NewTimer(target_); 28 MOZ_ASSERT(timer_); 29 if (!timer_) return NS_ERROR_FAILURE; 30 31 packets_lock_ = PR_NewLock(); 32 MOZ_ASSERT(packets_lock_); 33 if (!packets_lock_) return NS_ERROR_FAILURE; 34 35 deliverer_ = new Deliverer(this); 36 37 timer_->InitWithCallback(deliverer_, 100, nsITimer::TYPE_REPEATING_SLACK); 38 39 return NS_OK; 40 } 41 42 // Connect to the other side 43 void TransportLayerLoopback::Connect(TransportLayerLoopback* peer) { 44 peer_ = peer; 45 46 TL_SET_STATE(TS_OPEN); 47 } 48 49 TransportResult TransportLayerLoopback::SendPacket(MediaPacket& packet) { 50 MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "SendPacket(" << packet.len() << ")"); 51 52 if (!peer_) { 53 MOZ_MTLOG(ML_ERROR, "Discarding packet because peer not attached"); 54 return TE_ERROR; 55 } 56 57 size_t len = packet.len(); 58 nsresult res = peer_->QueuePacket(packet); 59 if (!NS_SUCCEEDED(res)) return TE_ERROR; 60 61 return static_cast<TransportResult>(len); 62 } 63 64 nsresult TransportLayerLoopback::QueuePacket(MediaPacket& packet) { 65 MOZ_ASSERT(packets_lock_); 66 67 PR_Lock(packets_lock_); 68 69 if (combinePackets_ && !packets_.empty()) { 70 MediaPacket* prevPacket = packets_.front(); 71 72 MOZ_MTLOG(ML_DEBUG, LAYER_INFO << " Enqueuing combined packets of length " 73 << prevPacket->len() << " and " 74 << packet.len()); 75 auto combined = MakeUnique<uint8_t[]>(prevPacket->len() + packet.len()); 76 memcpy(combined.get(), prevPacket->data(), prevPacket->len()); 77 memcpy(combined.get() + prevPacket->len(), packet.data(), packet.len()); 78 prevPacket->Take(std::move(combined), prevPacket->len() + packet.len()); 79 } else { 80 MOZ_MTLOG(ML_DEBUG, 81 LAYER_INFO << " Enqueuing packet of length " << packet.len()); 82 packets_.push(new MediaPacket(std::move(packet))); 83 } 84 85 PRStatus r = PR_Unlock(packets_lock_); 86 MOZ_ASSERT(r == PR_SUCCESS); 87 if (r != PR_SUCCESS) return NS_ERROR_FAILURE; 88 89 return NS_OK; 90 } 91 92 void TransportLayerLoopback::DeliverPackets() { 93 while (!packets_.empty()) { 94 UniquePtr<MediaPacket> packet(packets_.front()); 95 packets_.pop(); 96 97 MOZ_MTLOG(ML_DEBUG, 98 LAYER_INFO << " Delivering packet of length " << packet->len()); 99 SignalPacketReceived(this, *packet); 100 } 101 } 102 103 NS_IMPL_ISUPPORTS(TransportLayerLoopback::Deliverer, nsITimerCallback, nsINamed) 104 105 NS_IMETHODIMP TransportLayerLoopback::Deliverer::Notify(nsITimer* timer) { 106 if (!layer_) return NS_OK; 107 108 layer_->DeliverPackets(); 109 110 return NS_OK; 111 } 112 113 NS_IMETHODIMP TransportLayerLoopback::Deliverer::GetName(nsACString& aName) { 114 aName.AssignLiteral("TransportLayerLoopback::Deliverer"); 115 return NS_OK; 116 } 117 118 } // namespace mozilla