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 : // Some of this code is cut-and-pasted from nICEr. Copyright is:
10 :
11 : /*
12 : Copyright (c) 2007, Adobe Systems, Incorporated
13 : All rights reserved.
14 :
15 : Redistribution and use in source and binary forms, with or without
16 : modification, are permitted provided that the following conditions are
17 : met:
18 :
19 : * Redistributions of source code must retain the above copyright
20 : notice, this list of conditions and the following disclaimer.
21 :
22 : * Redistributions in binary form must reproduce the above copyright
23 : notice, this list of conditions and the following disclaimer in the
24 : documentation and/or other materials provided with the distribution.
25 :
26 : * Neither the name of Adobe Systems, Network Resonance nor the names of its
27 : contributors may be used to endorse or promote products derived from
28 : this software without specific prior written permission.
29 :
30 : THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 : "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 : LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
33 : A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
34 : OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35 : SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
36 : LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37 : DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38 : THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 : (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
40 : OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 : */
42 :
43 :
44 : #include <string>
45 : #include <vector>
46 :
47 : #include "nsCOMPtr.h"
48 : #include "nsComponentManagerUtils.h"
49 : #include "nsError.h"
50 : #include "nsIEventTarget.h"
51 : #include "nsNetCID.h"
52 : #include "nsComponentManagerUtils.h"
53 : #include "nsServiceManagerUtils.h"
54 :
55 : // nICEr includes
56 : extern "C" {
57 : #include "nr_api.h"
58 : #include "registry.h"
59 : #include "async_timer.h"
60 : #include "ice_util.h"
61 : #include "transport_addr.h"
62 : #include "nr_crypto.h"
63 : #include "nr_socket.h"
64 : #include "nr_socket_local.h"
65 : #include "stun_client_ctx.h"
66 : #include "stun_server_ctx.h"
67 : #include "ice_ctx.h"
68 : #include "ice_candidate.h"
69 : #include "ice_handler.h"
70 : }
71 :
72 : // Local includes
73 : #include "logging.h"
74 : #include "nricectx.h"
75 : #include "nricemediastream.h"
76 : #include "transportflow.h"
77 : #include "transportlayerice.h"
78 :
79 : namespace mozilla {
80 :
81 : #ifdef ERROR
82 : #undef ERROR
83 : #endif
84 :
85 0 : MOZ_MTLOG_MODULE("mtransport")
86 :
87 0 : TransportLayerIce::TransportLayerIce(const std::string& name)
88 : : name_(name),
89 : ctx_(nullptr), stream_(nullptr), component_(0),
90 0 : old_stream_(nullptr)
91 : {
92 : // setup happens later
93 0 : }
94 :
95 0 : TransportLayerIce::~TransportLayerIce() {
96 : // No need to do anything here, since we use smart pointers
97 0 : }
98 :
99 0 : void TransportLayerIce::SetParameters(RefPtr<NrIceCtx> ctx,
100 : RefPtr<NrIceMediaStream> stream,
101 : int component) {
102 : // If SetParameters is called and we already have a stream_, this means
103 : // we're handling an ICE restart. We need to hold the old stream until
104 : // we know the new stream is working.
105 0 : if (stream_ && !old_stream_ && (stream_ != stream)) {
106 : // Here we leave the old stream's signals connected until we don't need
107 : // it anymore. They will be disconnected if ice restart is successful.
108 0 : old_stream_ = stream_;
109 0 : MOZ_MTLOG(ML_INFO, LAYER_INFO << "SetParameters save old stream("
110 : << old_stream_->name() << ")");
111 : }
112 :
113 0 : ctx_ = ctx;
114 0 : stream_ = stream;
115 0 : component_ = component;
116 :
117 0 : PostSetup();
118 0 : }
119 :
120 0 : void TransportLayerIce::PostSetup() {
121 0 : target_ = ctx_->thread();
122 :
123 0 : stream_->SignalReady.connect(this, &TransportLayerIce::IceReady);
124 0 : stream_->SignalFailed.connect(this, &TransportLayerIce::IceFailed);
125 0 : stream_->SignalPacketReceived.connect(this,
126 0 : &TransportLayerIce::IcePacketReceived);
127 0 : if (stream_->state() == NrIceMediaStream::ICE_OPEN) {
128 0 : TL_SET_STATE(TS_OPEN);
129 : }
130 0 : }
131 :
132 0 : void TransportLayerIce::ResetOldStream() {
133 0 : if (old_stream_ == nullptr) {
134 0 : return; // no work to do
135 : }
136 : // ICE restart successful on the new stream, we can forget the old stream now
137 0 : MOZ_MTLOG(ML_INFO, LAYER_INFO << "ResetOldStream(" << old_stream_->name()
138 : << ")");
139 0 : old_stream_->SignalReady.disconnect(this);
140 0 : old_stream_->SignalFailed.disconnect(this);
141 0 : old_stream_->SignalPacketReceived.disconnect(this);
142 0 : old_stream_ = nullptr;
143 : }
144 :
145 0 : void TransportLayerIce::RestoreOldStream() {
146 0 : if (old_stream_ == nullptr) {
147 0 : return; // no work to do
148 : }
149 : // ICE restart rollback, we need to restore the old stream
150 0 : MOZ_MTLOG(ML_INFO, LAYER_INFO << "RestoreOldStream(" << old_stream_->name()
151 : << ")");
152 0 : stream_->SignalReady.disconnect(this);
153 0 : stream_->SignalFailed.disconnect(this);
154 0 : stream_->SignalPacketReceived.disconnect(this);
155 0 : stream_ = old_stream_;
156 0 : old_stream_ = nullptr;
157 :
158 0 : if (stream_->state() == NrIceMediaStream::ICE_OPEN) {
159 0 : IceReady(stream_);
160 0 : } else if (stream_->state() == NrIceMediaStream::ICE_CLOSED) {
161 0 : IceFailed(stream_);
162 : }
163 : // No events are fired when the stream is ICE_CONNECTING. If the
164 : // restored stream is ICE_CONNECTING, IceReady/IceFailed will fire
165 : // later.
166 : }
167 :
168 0 : TransportResult TransportLayerIce::SendPacket(const unsigned char *data,
169 : size_t len) {
170 0 : CheckThread();
171 : // use old_stream_ until stream_ is ready
172 0 : nsresult res = (old_stream_?old_stream_:stream_)->SendPacket(component_,
173 : data,
174 0 : len);
175 :
176 0 : if (!NS_SUCCEEDED(res)) {
177 0 : return (res == NS_BASE_STREAM_WOULD_BLOCK) ?
178 0 : TE_WOULDBLOCK : TE_ERROR;
179 : }
180 :
181 0 : MOZ_MTLOG(ML_DEBUG, LAYER_INFO << " SendPacket(" << len << ") succeeded");
182 :
183 0 : return len;
184 : }
185 :
186 :
187 0 : void TransportLayerIce::IceCandidate(NrIceMediaStream *stream,
188 : const std::string&) {
189 : // NO-OP for now
190 0 : }
191 :
192 0 : void TransportLayerIce::IceReady(NrIceMediaStream *stream) {
193 0 : CheckThread();
194 : // only handle the current stream (not the old stream during restart)
195 0 : if (stream != stream_) {
196 0 : return;
197 : }
198 0 : MOZ_MTLOG(ML_INFO, LAYER_INFO << "ICE Ready(" << stream->name() << ","
199 : << component_ << ")");
200 0 : TL_SET_STATE(TS_OPEN);
201 : }
202 :
203 0 : void TransportLayerIce::IceFailed(NrIceMediaStream *stream) {
204 0 : CheckThread();
205 : // only handle the current stream (not the old stream during restart)
206 0 : if (stream != stream_) {
207 0 : return;
208 : }
209 0 : MOZ_MTLOG(ML_INFO, LAYER_INFO << "ICE Failed(" << stream->name() << ","
210 : << component_ << ")");
211 0 : TL_SET_STATE(TS_ERROR);
212 : }
213 :
214 0 : void TransportLayerIce::IcePacketReceived(NrIceMediaStream *stream, int component,
215 : const unsigned char *data, int len) {
216 0 : CheckThread();
217 : // We get packets for both components, so ignore the ones that aren't
218 : // for us.
219 0 : if (component_ != component)
220 0 : return;
221 :
222 0 : MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "PacketReceived(" << stream->name() << ","
223 : << component << "," << len << ")");
224 0 : SignalPacketReceived(this, data, len);
225 : }
226 :
227 : } // close namespace
|