blob: bb09441df1f09d6f1e6f7d9717bc679c1075691d [file] [log] [blame]
Adrien Béraud612b55b2023-05-29 10:42:04 -04001/*
2 * Copyright (C) 2004-2023 Savoir-faire Linux Inc.
3 *
4 * Author: Stepan Salenikovich <stepan.salenikovich@savoirfairelinux.com>
5 * Author: Eden Abitbol <eden.abitbol@savoirfairelinux.com>
6 * Author: Mohamed Chibani <mohamed.chibani@savoirfairelinux.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
Morteza Namvar5f639522023-07-04 17:08:58 -040023#include "upnp/mapping.h"
24// #include "logger.h"
Adrien Béraud33a03ba2023-06-21 11:35:54 -040025#include "igd.h"
Adrien Béraud612b55b2023-05-29 10:42:04 -040026
27namespace jami {
28namespace upnp {
29
30Mapping::Mapping(PortType type, uint16_t portExternal, uint16_t portInternal, bool available)
31 : type_(type)
32 , externalPort_(portExternal)
33 , internalPort_(portInternal)
34 , internalAddr_()
35 , igd_()
36 , available_(available)
37 , state_(MappingState::PENDING)
38 , notifyCb_(nullptr)
39 , autoUpdate_(false)
40#if HAVE_LIBNATPMP
41 , renewalTime_(sys_clock::now())
42#endif
43{}
44
45Mapping::Mapping(const Mapping& other)
46{
47 std::lock_guard<std::mutex> lock(other.mutex_);
48
49 internalAddr_ = other.internalAddr_;
50 internalPort_ = other.internalPort_;
51 externalPort_ = other.externalPort_;
52 type_ = other.type_;
53 igd_ = other.igd_;
54 available_ = other.available_;
55 state_ = other.state_;
56 notifyCb_ = other.notifyCb_;
57 autoUpdate_ = other.autoUpdate_;
58#if HAVE_LIBNATPMP
59 renewalTime_ = other.renewalTime_;
60#endif
61}
62
63void
64Mapping::updateFrom(const Mapping::sharedPtr_t& other)
65{
66 updateFrom(*other);
67}
68
69void
70Mapping::updateFrom(const Mapping& other)
71{
72 if (type_ != other.type_) {
Morteza Namvar5f639522023-07-04 17:08:58 -040073 // JAMI_ERR("The source and destination types must match");
Adrien Béraud612b55b2023-05-29 10:42:04 -040074 return;
75 }
76
77 internalAddr_ = std::move(other.internalAddr_);
78 internalPort_ = other.internalPort_;
79 externalPort_ = other.externalPort_;
80 igd_ = other.igd_;
81 state_ = other.state_;
82}
83
84void
85Mapping::setAvailable(bool val)
86{
Morteza Namvar5f639522023-07-04 17:08:58 -040087 // JAMI_DBG("Changing mapping %s state from %s to %s",
88 // toString().c_str(),
89 // available_ ? "AVAILABLE" : "UNAVAILABLE",
90 // val ? "AVAILABLE" : "UNAVAILABLE");
Adrien Béraud612b55b2023-05-29 10:42:04 -040091
92 std::lock_guard<std::mutex> lock(mutex_);
93 available_ = val;
94}
95
96void
97Mapping::setState(const MappingState& state)
98{
99 std::lock_guard<std::mutex> lock(mutex_);
100 state_ = state;
101}
102
103const char*
104Mapping::getStateStr() const
105{
106 std::lock_guard<std::mutex> lock(mutex_);
107 return getStateStr(state_);
108}
109
110std::string
111Mapping::toString(bool extraInfo) const
112{
113 std::lock_guard<std::mutex> lock(mutex_);
114 std::ostringstream descr;
115 descr << UPNP_MAPPING_DESCRIPTION_PREFIX << "-" << getTypeStr(type_);
116 descr << ":" << std::to_string(internalPort_);
117
118 if (extraInfo) {
119 descr << " (state=" << getStateStr(state_)
120 << ", auto-update=" << (autoUpdate_ ? "YES" : "NO") << ")";
121 }
122
123 return descr.str();
124}
125
126bool
127Mapping::isValid() const
128{
129 std::lock_guard<std::mutex> lock(mutex_);
130 if (state_ == MappingState::FAILED)
131 return false;
132 if (internalPort_ == 0)
133 return false;
134 if (externalPort_ == 0)
135 return false;
136 if (not igd_ or not igd_->isValid())
137 return false;
138 IpAddr intAddr(internalAddr_);
139 return intAddr and not intAddr.isLoopback();
140}
141
142bool
143Mapping::hasValidHostAddress() const
144{
145 std::lock_guard<std::mutex> lock(mutex_);
146
147 IpAddr intAddr(internalAddr_);
148 return intAddr and not intAddr.isLoopback();
149}
150
151bool
152Mapping::hasPublicAddress() const
153{
154 std::lock_guard<std::mutex> lock(mutex_);
155
156 return igd_ and igd_->getPublicIp() and not igd_->getPublicIp().isPrivate();
157}
158
159Mapping::key_t
160Mapping::getMapKey() const
161{
162 std::lock_guard<std::mutex> lock(mutex_);
163
164 key_t mapKey = internalPort_;
165 if (type_ == PortType::UDP)
166 mapKey |= 1 << (sizeof(uint16_t) * 8);
167 return mapKey;
168}
169
170PortType
171Mapping::getTypeFromMapKey(key_t key)
172{
173 return (key >> (sizeof(uint16_t) * 8)) ? PortType::UDP : PortType::TCP;
174}
175
176std::string
177Mapping::getExternalAddress() const
178{
179 std::lock_guard<std::mutex> lock(mutex_);
180 if (igd_)
181 return igd_->getPublicIp().toString();
182 return {};
183}
184
185void
186Mapping::setExternalPort(uint16_t port)
187{
188 std::lock_guard<std::mutex> lock(mutex_);
189 externalPort_ = port;
190}
191
192uint16_t
193Mapping::getExternalPort() const
194{
195 std::lock_guard<std::mutex> lock(mutex_);
196 return externalPort_;
197}
198
199std::string
200Mapping::getExternalPortStr() const
201{
202 std::lock_guard<std::mutex> lock(mutex_);
203 return std::to_string(externalPort_);
204}
205
206void
207Mapping::setInternalAddress(const std::string& addr)
208{
209 std::lock_guard<std::mutex> lock(mutex_);
210 internalAddr_ = addr;
211}
212
213std::string
214Mapping::getInternalAddress() const
215{
216 std::lock_guard<std::mutex> lock(mutex_);
217 return internalAddr_;
218}
219
220void
221Mapping::setInternalPort(uint16_t port)
222{
223 std::lock_guard<std::mutex> lock(mutex_);
224 internalPort_ = port;
225}
226
227uint16_t
228Mapping::getInternalPort() const
229{
230 std::lock_guard<std::mutex> lock(mutex_);
231 return internalPort_;
232}
233
234std::string
235Mapping::getInternalPortStr() const
236{
237 std::lock_guard<std::mutex> lock(mutex_);
238 return std::to_string(internalPort_);
239}
240
241PortType
242Mapping::getType() const
243{
244 std::lock_guard<std::mutex> lock(mutex_);
245 return type_;
246}
247
248const char*
249Mapping::getTypeStr() const
250{
251 std::lock_guard<std::mutex> lock(mutex_);
252 return getTypeStr(type_);
253}
254
255bool
256Mapping::isAvailable() const
257{
258 std::lock_guard<std::mutex> lock(mutex_);
259 return available_;
260}
261
262std::shared_ptr<IGD>
263Mapping::getIgd() const
264{
265 std::lock_guard<std::mutex> lock(mutex_);
266 return igd_;
267}
268
269NatProtocolType
270Mapping::getProtocol() const
271{
272 std::lock_guard<std::mutex> lock(mutex_);
273 if (igd_)
274 return igd_->getProtocol();
275 return NatProtocolType::UNKNOWN;
276}
277const char*
278Mapping::getProtocolName() const
279{
280 if (igd_) {
281 if (igd_->getProtocol() == NatProtocolType::NAT_PMP)
282 return "NAT-PMP";
283 if (igd_->getProtocol() == NatProtocolType::PUPNP)
284 return "PUPNP";
285 }
286 return "UNKNOWN";
287}
288
289void
290Mapping::setIgd(const std::shared_ptr<IGD>& igd)
291{
292 std::lock_guard<std::mutex> lock(mutex_);
293 igd_ = igd;
294}
295
296MappingState
297Mapping::getState() const
298{
299 std::lock_guard<std::mutex> lock(mutex_);
300 return state_;
301}
302
303Mapping::NotifyCallback
304Mapping::getNotifyCallback() const
305{
306 std::lock_guard<std::mutex> lock(mutex_);
307 return notifyCb_;
308}
309
310void
311Mapping::setNotifyCallback(NotifyCallback cb)
312{
313 std::lock_guard<std::mutex> lock(mutex_);
314 notifyCb_ = std::move(cb);
315}
316
317void
318Mapping::enableAutoUpdate(bool enable)
319{
320 std::lock_guard<std::mutex> lock(mutex_);
321 autoUpdate_ = enable;
322}
323
324bool
325Mapping::getAutoUpdate() const
326{
327 std::lock_guard<std::mutex> lock(mutex_);
328 return autoUpdate_;
329}
330
331#if HAVE_LIBNATPMP
332sys_clock::time_point
333Mapping::getRenewalTime() const
334{
335 std::lock_guard<std::mutex> lock(mutex_);
336 return renewalTime_;
337}
338
339void
340Mapping::setRenewalTime(sys_clock::time_point time)
341{
342 std::lock_guard<std::mutex> lock(mutex_);
343 renewalTime_ = time;
344}
345#endif
346
347} // namespace upnp
348} // namespace jami