Line data Source code
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 0 : MOZ_MTLOG_MODULE("mtransport")
19 :
20 0 : NrIceCtxHandler::NrIceCtxHandler(const std::string& name,
21 0 : NrIceCtx::Policy policy)
22 0 : : current_ctx(new NrIceCtx(name, policy)),
23 : old_ctx(nullptr),
24 0 : restart_count(0)
25 : {
26 0 : }
27 :
28 : RefPtr<NrIceCtxHandler>
29 0 : NrIceCtxHandler::Create(const std::string& name,
30 : bool allow_loopback,
31 : bool tcp_enabled,
32 : bool allow_link_local,
33 : NrIceCtx::Policy policy)
34 : {
35 : // InitializeGlobals only executes once
36 0 : NrIceCtx::InitializeGlobals(allow_loopback, tcp_enabled, allow_link_local);
37 :
38 0 : RefPtr<NrIceCtxHandler> ctx = new NrIceCtxHandler(name, policy);
39 :
40 0 : if (ctx == nullptr ||
41 0 : ctx->current_ctx == nullptr ||
42 0 : !ctx->current_ctx->Initialize()) {
43 0 : return nullptr;
44 : }
45 :
46 0 : return ctx;
47 : }
48 :
49 :
50 : RefPtr<NrIceMediaStream>
51 0 : NrIceCtxHandler::CreateStream(const std::string& name, int components)
52 : {
53 : // To make tracking NrIceMediaStreams easier during ICE restart
54 : // prepend an int to the name that increments with each ICE restart
55 0 : std::ostringstream os;
56 0 : os << restart_count << "-" << name;
57 0 : return NrIceMediaStream::Create(this->current_ctx, os.str(), components);
58 : }
59 :
60 :
61 : RefPtr<NrIceCtx>
62 0 : NrIceCtxHandler::CreateCtx() const
63 : {
64 0 : return CreateCtx(NrIceCtx::GetNewUfrag(), NrIceCtx::GetNewPwd());
65 : }
66 :
67 :
68 : RefPtr<NrIceCtx>
69 0 : NrIceCtxHandler::CreateCtx(const std::string& ufrag,
70 : const std::string& pwd) const
71 : {
72 0 : RefPtr<NrIceCtx> new_ctx = new NrIceCtx(this->current_ctx->name(),
73 0 : this->current_ctx->policy());
74 0 : if (new_ctx == nullptr) {
75 0 : return nullptr;
76 : }
77 :
78 0 : if (!new_ctx->Initialize(ufrag, pwd)) {
79 0 : return nullptr;
80 : }
81 :
82 : // copy the stun, and turn servers from the current context
83 0 : int r = nr_ice_ctx_set_stun_servers(new_ctx->ctx_,
84 0 : this->current_ctx->ctx_->stun_servers,
85 0 : this->current_ctx->ctx_->stun_server_ct);
86 0 : if (r) {
87 0 : MOZ_MTLOG(ML_ERROR, "Error while setting STUN servers in CreateCtx"
88 : << " (likely ice restart related)");
89 0 : return nullptr;
90 : }
91 :
92 0 : r = nr_ice_ctx_copy_turn_servers(new_ctx->ctx_,
93 0 : this->current_ctx->ctx_->turn_servers,
94 0 : this->current_ctx->ctx_->turn_server_ct);
95 0 : if (r) {
96 0 : MOZ_MTLOG(ML_ERROR, "Error while copying TURN servers in CreateCtx"
97 : << " (likely ice restart related)");
98 0 : return nullptr;
99 : }
100 :
101 : // grab the NrIceResolver stashed in the nr_resolver and allocate another
102 : // for the new ctx. Note: there may not be an nr_resolver.
103 0 : if (this->current_ctx->ctx_->resolver) {
104 : NrIceResolver* resolver =
105 0 : static_cast<NrIceResolver*>(this->current_ctx->ctx_->resolver->obj);
106 0 : if (!resolver ||
107 0 : NS_FAILED(new_ctx->SetResolver(resolver->AllocateResolver()))) {
108 0 : MOZ_MTLOG(ML_ERROR, "Error while setting dns resolver in CreateCtx"
109 : << " (likely ice restart related)");
110 0 : return nullptr;
111 : }
112 : }
113 :
114 0 : return new_ctx;
115 : }
116 :
117 :
118 : bool
119 0 : NrIceCtxHandler::BeginIceRestart(RefPtr<NrIceCtx> new_ctx)
120 : {
121 0 : MOZ_ASSERT(!old_ctx, "existing ice restart in progress");
122 0 : if (old_ctx) {
123 0 : MOZ_MTLOG(ML_ERROR, "Existing ice restart in progress");
124 0 : return false; // ice restart already in progress
125 : }
126 :
127 0 : if (new_ctx == nullptr) {
128 0 : return false;
129 : }
130 :
131 0 : ++restart_count;
132 0 : old_ctx = current_ctx;
133 0 : current_ctx = new_ctx;
134 0 : return true;
135 : }
136 :
137 :
138 : void
139 0 : NrIceCtxHandler::FinalizeIceRestart()
140 : {
141 0 : if (old_ctx) {
142 : // Fixup the telemetry by transferring old stats to current ctx.
143 0 : NrIceStats stats = old_ctx->Destroy();
144 0 : current_ctx->AccumulateStats(stats);
145 : }
146 :
147 : // no harm calling this even if we're not in the middle of restarting
148 0 : old_ctx = nullptr;
149 0 : }
150 :
151 :
152 : void
153 0 : NrIceCtxHandler::RollbackIceRestart()
154 : {
155 0 : if (old_ctx == nullptr) {
156 0 : return;
157 : }
158 0 : current_ctx = old_ctx;
159 0 : old_ctx = nullptr;
160 : }
161 :
162 0 : NrIceStats NrIceCtxHandler::Destroy()
163 : {
164 0 : NrIceStats stats;
165 :
166 : // designed to be called more than once so if stats are desired, this can be
167 : // called just prior to the destructor
168 0 : if (old_ctx && current_ctx) {
169 0 : stats = old_ctx->Destroy();
170 0 : current_ctx->AccumulateStats(stats);
171 : }
172 :
173 0 : if (current_ctx) {
174 0 : stats = current_ctx->Destroy();
175 : }
176 :
177 0 : old_ctx = nullptr;
178 0 : current_ctx = nullptr;
179 :
180 0 : return stats;
181 : }
182 :
183 0 : NrIceCtxHandler::~NrIceCtxHandler()
184 : {
185 0 : Destroy();
186 0 : }
187 :
188 : } // close namespace
|