Line data Source code
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 "logging.h"
10 : #include "nspr.h"
11 : #include "prlock.h"
12 :
13 : #include "nsNetCID.h"
14 : #include "nsIComponentManager.h"
15 : #include "nsComponentManagerUtils.h"
16 : #include "nsIComponentRegistrar.h"
17 : #include "nsIEventTarget.h"
18 : #include "nsIIOService.h"
19 : #include "nsIServiceManager.h"
20 : #include "nsISocketTransportService.h"
21 : #include "nsServiceManagerUtils.h"
22 :
23 : #include "transportflow.h"
24 : #include "transportlayerloopback.h"
25 :
26 : namespace mozilla {
27 :
28 0 : MOZ_MTLOG_MODULE("mtransport")
29 :
30 0 : nsresult TransportLayerLoopback::Init() {
31 0 : timer_ = do_CreateInstance(NS_TIMER_CONTRACTID);
32 0 : MOZ_ASSERT(timer_);
33 0 : if (!timer_)
34 0 : return NS_ERROR_FAILURE;
35 :
36 : nsresult rv;
37 0 : target_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
38 0 : MOZ_ASSERT(NS_SUCCEEDED(rv));
39 0 : if (!NS_SUCCEEDED(rv))
40 0 : return rv;
41 :
42 0 : timer_->SetTarget(target_);
43 :
44 0 : packets_lock_ = PR_NewLock();
45 0 : MOZ_ASSERT(packets_lock_);
46 0 : if (!packets_lock_)
47 0 : return NS_ERROR_FAILURE;
48 :
49 0 : deliverer_ = new Deliverer(this);
50 :
51 0 : timer_->InitWithCallback(deliverer_, 100, nsITimer::TYPE_REPEATING_SLACK);
52 :
53 0 : return NS_OK;
54 : }
55 :
56 : // Connect to the other side
57 0 : void TransportLayerLoopback::Connect(TransportLayerLoopback* peer) {
58 0 : peer_ = peer;
59 :
60 0 : TL_SET_STATE(TS_OPEN);
61 0 : }
62 :
63 : TransportResult
64 0 : TransportLayerLoopback::SendPacket(const unsigned char *data, size_t len) {
65 0 : MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "SendPacket(" << len << ")");
66 :
67 0 : if (!peer_) {
68 0 : MOZ_MTLOG(ML_ERROR, "Discarding packet because peer not attached");
69 0 : return TE_ERROR;
70 : }
71 :
72 0 : nsresult res = peer_->QueuePacket(data, len);
73 0 : if (!NS_SUCCEEDED(res))
74 0 : return TE_ERROR;
75 :
76 0 : return static_cast<TransportResult>(len);
77 : }
78 :
79 0 : nsresult TransportLayerLoopback::QueuePacket(const unsigned char *data,
80 : size_t len) {
81 0 : MOZ_ASSERT(packets_lock_);
82 :
83 0 : PR_Lock(packets_lock_);
84 :
85 0 : if (combinePackets_ && !packets_.empty()) {
86 0 : QueuedPacket *packet = packets_.front();
87 0 : packets_.pop();
88 :
89 0 : MOZ_MTLOG(ML_DEBUG, LAYER_INFO << " Enqueuing combined packets of length " << packet->len() << " and " << len);
90 0 : packets_.push(new QueuedPacket());
91 0 : packets_.back()->Assign(packet->data(), packet->len(),
92 0 : data, len);
93 : } else {
94 0 : MOZ_MTLOG(ML_DEBUG, LAYER_INFO << " Enqueuing packet of length " << len);
95 0 : packets_.push(new QueuedPacket());
96 0 : packets_.back()->Assign(data, len);
97 : }
98 :
99 0 : PRStatus r = PR_Unlock(packets_lock_);
100 0 : MOZ_ASSERT(r == PR_SUCCESS);
101 0 : if (r != PR_SUCCESS)
102 0 : return NS_ERROR_FAILURE;
103 :
104 0 : return NS_OK;
105 : }
106 :
107 :
108 0 : void TransportLayerLoopback::DeliverPackets() {
109 0 : while (!packets_.empty()) {
110 0 : QueuedPacket *packet = packets_.front();
111 0 : packets_.pop();
112 :
113 0 : MOZ_MTLOG(ML_DEBUG, LAYER_INFO << " Delivering packet of length " <<
114 : packet->len());
115 0 : SignalPacketReceived(this, packet->data(), packet->len());
116 :
117 0 : delete packet;
118 : }
119 0 : }
120 :
121 0 : NS_IMPL_ISUPPORTS(TransportLayerLoopback::Deliverer, nsITimerCallback)
122 :
123 0 : NS_IMETHODIMP TransportLayerLoopback::Deliverer::Notify(nsITimer *timer) {
124 0 : if (!layer_)
125 0 : return NS_OK;
126 :
127 0 : layer_->DeliverPackets();
128 :
129 0 : return NS_OK;
130 : }
131 : } // close namespace
|