summaryrefslogtreecommitdiffstats
path: root/media/mtransport/nricectxhandler.cpp
blob: 4cea6c2c155126757c1bb0b0ef5d399e215673f7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#include <sstream>

#include "logging.h"

// nICEr includes
extern "C" {
#include "nr_api.h"
#include "ice_ctx.h"
}

// Local includes
#include "nricectxhandler.h"
#include "nricemediastream.h"
#include "nriceresolver.h"

namespace mozilla {

MOZ_MTLOG_MODULE("mtransport")

NrIceCtxHandler::NrIceCtxHandler(const std::string& name,
                                 bool offerer,
                                 NrIceCtx::Policy policy)
  : current_ctx(new NrIceCtx(name, offerer, policy)),
    old_ctx(nullptr),
    restart_count(0)
{
}

RefPtr<NrIceCtxHandler>
NrIceCtxHandler::Create(const std::string& name,
                        bool offerer,
                        bool allow_loopback,
                        bool tcp_enabled,
                        bool allow_link_local,
                        NrIceCtx::Policy policy)
{
  // InitializeGlobals only executes once
  NrIceCtx::InitializeGlobals(allow_loopback, tcp_enabled, allow_link_local);

  RefPtr<NrIceCtxHandler> ctx = new NrIceCtxHandler(name, offerer, policy);

  if (ctx == nullptr ||
      ctx->current_ctx == nullptr ||
      !ctx->current_ctx->Initialize()) {
    return nullptr;
  }

  return ctx;
}


RefPtr<NrIceMediaStream>
NrIceCtxHandler::CreateStream(const std::string& name, int components)
{
  // To make tracking NrIceMediaStreams easier during ICE restart
  // prepend an int to the name that increments with each ICE restart
  std::ostringstream os;
  os << restart_count << "-" << name;
  return NrIceMediaStream::Create(this->current_ctx, os.str(), components);
}


RefPtr<NrIceCtx>
NrIceCtxHandler::CreateCtx() const
{
  return CreateCtx(NrIceCtx::GetNewUfrag(), NrIceCtx::GetNewPwd());
}


RefPtr<NrIceCtx>
NrIceCtxHandler::CreateCtx(const std::string& ufrag,
                           const std::string& pwd) const
{
  RefPtr<NrIceCtx> new_ctx = new NrIceCtx(this->current_ctx->name(),
                                          true, // offerer (hardcoded per bwc)
                                          this->current_ctx->policy());
  if (new_ctx == nullptr) {
    return nullptr;
  }

  if (!new_ctx->Initialize(ufrag, pwd)) {
    return nullptr;
  }

  // copy the stun, and turn servers from the current context
  int r = nr_ice_ctx_set_stun_servers(new_ctx->ctx_,
                                      this->current_ctx->ctx_->stun_servers,
                                      this->current_ctx->ctx_->stun_server_ct);
  if (r) {
    MOZ_MTLOG(ML_ERROR, "Error while setting STUN servers in CreateCtx"
                        << " (likely ice restart related)");
    return nullptr;
  }

  r = nr_ice_ctx_copy_turn_servers(new_ctx->ctx_,
                                   this->current_ctx->ctx_->turn_servers,
                                   this->current_ctx->ctx_->turn_server_ct);
  if (r) {
    MOZ_MTLOG(ML_ERROR, "Error while copying TURN servers in CreateCtx"
                        << " (likely ice restart related)");
    return nullptr;
  }

  // grab the NrIceResolver stashed in the nr_resolver and allocate another
  // for the new ctx.  Note: there may not be an nr_resolver.
  if (this->current_ctx->ctx_->resolver) {
    NrIceResolver* resolver =
      static_cast<NrIceResolver*>(this->current_ctx->ctx_->resolver->obj);
    if (!resolver ||
        NS_FAILED(new_ctx->SetResolver(resolver->AllocateResolver()))) {
      MOZ_MTLOG(ML_ERROR, "Error while setting dns resolver in CreateCtx"
                          << " (likely ice restart related)");
      return nullptr;
    }
  }

  return new_ctx;
}


bool
NrIceCtxHandler::BeginIceRestart(RefPtr<NrIceCtx> new_ctx)
{
  MOZ_ASSERT(!old_ctx, "existing ice restart in progress");
  if (old_ctx) {
    MOZ_MTLOG(ML_ERROR, "Existing ice restart in progress");
    return false; // ice restart already in progress
  }

  if (new_ctx == nullptr) {
    return false;
  }

  ++restart_count;
  old_ctx = current_ctx;
  current_ctx = new_ctx;
  return true;
}


void
NrIceCtxHandler::FinalizeIceRestart()
{
  // no harm calling this even if we're not in the middle of restarting
  old_ctx = nullptr;
}


void
NrIceCtxHandler::RollbackIceRestart()
{
  if (old_ctx == nullptr) {
    return;
  }
  current_ctx = old_ctx;
  old_ctx = nullptr;
}


} // close namespace