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/. */
7 // Original author: ekr@rtfm.com
9 // Some of this code is cut-and-pasted from nICEr. Copyright is:
12 Copyright (c) 2007, Adobe Systems, Incorporated
15 Redistribution and use in source and binary forms, with or without
16 modification, are permitted provided that the following conditions are
19 * Redistributions of source code must retain the above copyright
20 notice, this list of conditions and the following disclaimer.
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.
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.
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.
43 /* This Source Code Form is subject to the terms of the Mozilla Public
44 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
45 * You can obtain one at http://mozilla.org/MPL/2.0/. */
47 // Original author: ekr@rtfm.com
49 // This is a wrapper around the nICEr ICE stack
60 #include "mozilla/RefPtr.h"
61 #include "mozilla/Scoped.h"
62 #include "mozilla/TimeStamp.h"
63 #include "nsAutoPtr.h"
64 #include "nsIEventTarget.h"
67 #include "m_cpp_utils.h"
69 typedef struct nr_ice_ctx_ nr_ice_ctx
;
70 typedef struct nr_ice_peer_ctx_ nr_ice_peer_ctx
;
71 typedef struct nr_ice_media_stream_ nr_ice_media_stream
;
72 typedef struct nr_ice_handler_ nr_ice_handler
;
73 typedef struct nr_ice_handler_vtbl_ nr_ice_handler_vtbl
;
74 typedef struct nr_ice_candidate_ nr_ice_candidate
;
75 typedef struct nr_ice_cand_pair_ nr_ice_cand_pair
;
76 typedef struct nr_ice_stun_server_ nr_ice_stun_server
;
77 typedef struct nr_ice_turn_server_ nr_ice_turn_server
;
78 typedef struct nr_resolver_ nr_resolver
;
80 typedef void* NR_SOCKET
;
84 // Timestamps set whenever a packet is dropped due to global rate limiting
85 // (see nr_socket_prsock.cpp)
86 TimeStamp
nr_socket_short_term_violation_time();
87 TimeStamp
nr_socket_long_term_violation_time();
89 class NrIceMediaStream
;
91 extern const char kNrIceTransportUdp
[];
92 extern const char kNrIceTransportTcp
[];
94 class NrIceStunServer
{
96 explicit NrIceStunServer(const PRNetAddr
& addr
) : has_addr_(true) {
97 memcpy(&addr_
, &addr
, sizeof(addr
));
100 // The main function to use. Will take either an address or a hostname.
101 static NrIceStunServer
* Create(const std::string
& addr
, uint16_t port
) {
102 ScopedDeletePtr
<NrIceStunServer
> server(
103 new NrIceStunServer());
105 nsresult rv
= server
->Init(addr
, port
);
109 return server
.forget();
112 nsresult
ToNicerStunStruct(nr_ice_stun_server
* server
,
113 const std::string
& transport
=
114 kNrIceTransportUdp
) const;
117 NrIceStunServer() : addr_() {}
119 nsresult
Init(const std::string
& addr
, uint16_t port
) {
120 PRStatus status
= PR_StringToNetAddr(addr
.c_str(), &addr_
);
121 if (status
== PR_SUCCESS
) {
122 // Parseable as an address
123 addr_
.inet
.port
= PR_htons(port
);
128 else if (addr
.size() < 256) {
129 // Apparently this is a hostname.
136 return NS_ERROR_FAILURE
;
145 class NrIceTurnServer
: public NrIceStunServer
{
147 static NrIceTurnServer
*Create(const std::string
& addr
, uint16_t port
,
148 const std::string
& username
,
149 const std::vector
<unsigned char>& password
,
150 const char *transport
= kNrIceTransportUdp
) {
151 ScopedDeletePtr
<NrIceTurnServer
> server(
152 new NrIceTurnServer(username
, password
, transport
));
154 nsresult rv
= server
->Init(addr
, port
);
158 return server
.forget();
161 nsresult
ToNicerTurnStruct(nr_ice_turn_server
*server
) const;
164 NrIceTurnServer(const std::string
& username
,
165 const std::vector
<unsigned char>& password
,
166 const char *transport
) :
167 username_(username
), password_(password
), transport_(transport
) {}
169 std::string username_
;
170 std::vector
<unsigned char> password_
;
171 std::string transport_
;
176 enum ConnectionState
{ ICE_CTX_INIT
,
182 enum GatheringState
{ ICE_CTX_GATHER_INIT
,
183 ICE_CTX_GATHER_STARTED
,
184 ICE_CTX_GATHER_COMPLETE
187 enum Controlling
{ ICE_CONTROLLING
,
191 static RefPtr
<NrIceCtx
> Create(const std::string
& name
,
193 bool set_interface_priorities
= true,
194 bool allow_loopback
= false);
196 // Deinitialize all ICE global state. Used only for testing.
197 static void internal_DeinitializeGlobal();
200 nr_ice_ctx
*ctx() { return ctx_
; }
201 nr_ice_peer_ctx
*peer() { return peer_
; }
204 void destroy_peer_ctx();
206 // Create a media stream
207 RefPtr
<NrIceMediaStream
> CreateStream(const std::string
& name
,
210 RefPtr
<NrIceMediaStream
> GetStream(size_t index
) {
211 if (index
< streams_
.size()) {
212 return streams_
[index
];
217 // Some might be null
218 size_t GetStreamCount() const
220 return streams_
.size();
223 // The name of the ctx
224 const std::string
& name() const { return name_
; }
226 // Get ufrag and password.
227 std::string
ufrag() const;
228 std::string
pwd() const;
231 ConnectionState
connection_state() const {
232 return connection_state_
;
236 GatheringState
gathering_state() const {
237 return gathering_state_
;
240 // Get the global attributes
241 std::vector
<std::string
> GetGlobalAttributes();
243 // Set the other side's global attributes
244 nsresult
ParseGlobalAttributes(std::vector
<std::string
> attrs
);
246 // Set whether we are controlling or not.
247 nsresult
SetControlling(Controlling controlling
);
249 Controlling
GetControlling();
251 // Set the STUN servers. Must be called before StartGathering
253 nsresult
SetStunServers(const std::vector
<NrIceStunServer
>& stun_servers
);
255 // Set the TURN servers. Must be called before StartGathering
257 nsresult
SetTurnServers(const std::vector
<NrIceTurnServer
>& turn_servers
);
259 // Provide the resolution provider. Must be called before
261 nsresult
SetResolver(nr_resolver
*resolver
);
263 // Start ICE gathering
264 nsresult
StartGathering();
267 nsresult
StartChecks();
269 // Finalize the ICE negotiation. I.e., there will be no
274 bool generating_trickle() const { return trickle_
; }
276 // Signals to indicate events. API users can (and should)
277 // register for these.
278 sigslot::signal2
<NrIceCtx
*, NrIceCtx::GatheringState
>
279 SignalGatheringStateChange
;
280 sigslot::signal2
<NrIceCtx
*, NrIceCtx::ConnectionState
>
281 SignalConnectionStateChange
;
283 // The thread to direct method calls to
284 nsCOMPtr
<nsIEventTarget
> thread() { return sts_target_
; }
286 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NrIceCtx
)
289 NrIceCtx(const std::string
& name
,
291 : connection_state_(ICE_CTX_INIT
),
292 gathering_state_(ICE_CTX_GATHER_INIT
),
298 ice_handler_vtbl_(nullptr),
299 ice_handler_(nullptr),
301 // XXX: offerer_ will be used eventually; placate clang in the meantime.
307 DISALLOW_COPY_ASSIGN(NrIceCtx
);
309 // Callbacks for nICEr
310 static void initialized_cb(NR_SOCKET s
, int h
, void *arg
); // ICE initialized
312 // Handler implementation
313 static int select_pair(void *obj
,nr_ice_media_stream
*stream
,
314 int component_id
, nr_ice_cand_pair
**potentials
,
316 static int stream_ready(void *obj
, nr_ice_media_stream
*stream
);
317 static int stream_failed(void *obj
, nr_ice_media_stream
*stream
);
318 static int ice_checking(void *obj
, nr_ice_peer_ctx
*pctx
);
319 static int ice_completed(void *obj
, nr_ice_peer_ctx
*pctx
);
320 static int msg_recvd(void *obj
, nr_ice_peer_ctx
*pctx
,
321 nr_ice_media_stream
*stream
, int component_id
,
322 unsigned char *msg
, int len
);
323 static void trickle_cb(void *arg
, nr_ice_ctx
*ctx
, nr_ice_media_stream
*stream
,
324 int component_id
, nr_ice_candidate
*candidate
);
326 // Find a media stream by stream ptr. Gross
327 RefPtr
<NrIceMediaStream
> FindStream(nr_ice_media_stream
*stream
);
330 void SetConnectionState(ConnectionState state
);
333 void SetGatheringState(GatheringState state
);
335 ConnectionState connection_state_
;
336 GatheringState gathering_state_
;
337 const std::string name_
;
339 std::vector
<RefPtr
<NrIceMediaStream
> > streams_
;
341 nr_ice_peer_ctx
*peer_
;
342 nr_ice_handler_vtbl
* ice_handler_vtbl_
; // Must be pointer
343 nr_ice_handler
* ice_handler_
; // Must be pointer
345 nsCOMPtr
<nsIEventTarget
> sts_target_
; // The thread to run on