1 #include <sstream>
2
3 #include "logging.h"
4
5 // nICEr includes
6 extern "C" {
7 #include "nr_api.h"
8 #include "ice_ctx.h"
9 }
10
11 // Local includes
12 #include "nricectxhandler.h"
13 #include "nricemediastream.h"
14 #include "nriceresolver.h"
15
16 namespace mozilla {
17
18 MOZ_MTLOG_MODULE("mtransport")
19
NrIceCtxHandler(const std::string & name,bool offerer,NrIceCtx::Policy policy)20 NrIceCtxHandler::NrIceCtxHandler(const std::string& name,
21 bool offerer,
22 NrIceCtx::Policy policy)
23 : current_ctx(new NrIceCtx(name, offerer, policy)),
24 old_ctx(nullptr),
25 restart_count(0)
26 {
27 }
28
29 RefPtr<NrIceCtxHandler>
Create(const std::string & name,bool offerer,bool allow_loopback,bool tcp_enabled,bool allow_link_local,NrIceCtx::Policy policy)30 NrIceCtxHandler::Create(const std::string& name,
31 bool offerer,
32 bool allow_loopback,
33 bool tcp_enabled,
34 bool allow_link_local,
35 NrIceCtx::Policy policy)
36 {
37 // InitializeGlobals only executes once
38 NrIceCtx::InitializeGlobals(allow_loopback, tcp_enabled, allow_link_local);
39
40 RefPtr<NrIceCtxHandler> ctx = new NrIceCtxHandler(name, offerer, policy);
41
42 if (ctx == nullptr ||
43 ctx->current_ctx == nullptr ||
44 !ctx->current_ctx->Initialize()) {
45 return nullptr;
46 }
47
48 return ctx;
49 }
50
51
52 RefPtr<NrIceMediaStream>
CreateStream(const std::string & name,int components)53 NrIceCtxHandler::CreateStream(const std::string& name, int components)
54 {
55 // To make tracking NrIceMediaStreams easier during ICE restart
56 // prepend an int to the name that increments with each ICE restart
57 std::ostringstream os;
58 os << restart_count << "-" << name;
59 return NrIceMediaStream::Create(this->current_ctx, os.str(), components);
60 }
61
62
63 RefPtr<NrIceCtx>
CreateCtx() const64 NrIceCtxHandler::CreateCtx() const
65 {
66 return CreateCtx(NrIceCtx::GetNewUfrag(), NrIceCtx::GetNewPwd());
67 }
68
69
70 RefPtr<NrIceCtx>
CreateCtx(const std::string & ufrag,const std::string & pwd) const71 NrIceCtxHandler::CreateCtx(const std::string& ufrag,
72 const std::string& pwd) const
73 {
74 RefPtr<NrIceCtx> new_ctx = new NrIceCtx(this->current_ctx->name(),
75 true, // offerer (hardcoded per bwc)
76 this->current_ctx->policy());
77 if (new_ctx == nullptr) {
78 return nullptr;
79 }
80
81 if (!new_ctx->Initialize(ufrag, pwd)) {
82 return nullptr;
83 }
84
85 // copy the stun, and turn servers from the current context
86 int r = nr_ice_ctx_set_stun_servers(new_ctx->ctx_,
87 this->current_ctx->ctx_->stun_servers,
88 this->current_ctx->ctx_->stun_server_ct);
89 if (r) {
90 MOZ_MTLOG(ML_ERROR, "Error while setting STUN servers in CreateCtx"
91 << " (likely ice restart related)");
92 return nullptr;
93 }
94
95 r = nr_ice_ctx_copy_turn_servers(new_ctx->ctx_,
96 this->current_ctx->ctx_->turn_servers,
97 this->current_ctx->ctx_->turn_server_ct);
98 if (r) {
99 MOZ_MTLOG(ML_ERROR, "Error while copying TURN servers in CreateCtx"
100 << " (likely ice restart related)");
101 return nullptr;
102 }
103
104 // grab the NrIceResolver stashed in the nr_resolver and allocate another
105 // for the new ctx. Note: there may not be an nr_resolver.
106 if (this->current_ctx->ctx_->resolver) {
107 NrIceResolver* resolver =
108 static_cast<NrIceResolver*>(this->current_ctx->ctx_->resolver->obj);
109 if (!resolver ||
110 NS_FAILED(new_ctx->SetResolver(resolver->AllocateResolver()))) {
111 MOZ_MTLOG(ML_ERROR, "Error while setting dns resolver in CreateCtx"
112 << " (likely ice restart related)");
113 return nullptr;
114 }
115 }
116
117 return new_ctx;
118 }
119
120
121 bool
BeginIceRestart(RefPtr<NrIceCtx> new_ctx)122 NrIceCtxHandler::BeginIceRestart(RefPtr<NrIceCtx> new_ctx)
123 {
124 MOZ_ASSERT(!old_ctx, "existing ice restart in progress");
125 if (old_ctx) {
126 MOZ_MTLOG(ML_ERROR, "Existing ice restart in progress");
127 return false; // ice restart already in progress
128 }
129
130 if (new_ctx == nullptr) {
131 return false;
132 }
133
134 ++restart_count;
135 old_ctx = current_ctx;
136 current_ctx = new_ctx;
137 return true;
138 }
139
140
141 void
FinalizeIceRestart()142 NrIceCtxHandler::FinalizeIceRestart()
143 {
144 // no harm calling this even if we're not in the middle of restarting
145 old_ctx = nullptr;
146 }
147
148
149 void
RollbackIceRestart()150 NrIceCtxHandler::RollbackIceRestart()
151 {
152 if (old_ctx == nullptr) {
153 return;
154 }
155 current_ctx = old_ctx;
156 old_ctx = nullptr;
157 }
158
159
160 } // close namespace
161