blob: fa9b6c73a2d6207158e0f910d58bdb20ca05a24b [file] [log] [blame]
Adrien Béraud612b55b2023-05-29 10:42:04 -04001/*
2 * Copyright (C) 2004-2023 Savoir-faire Linux Inc.
3 *
Adrien Béraudcb753622023-07-17 22:32:49 -04004 * This program is free software: you can redistribute it and/or modify
Adrien Béraud612b55b2023-05-29 10:42:04 -04005 * it under the terms of the GNU General Public License as published by
Adrien Béraudcb753622023-07-17 22:32:49 -04006 * the Free Software Foundation, either version 3 of the License, or
Adrien Béraud612b55b2023-05-29 10:42:04 -04007 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Adrien Béraudcb753622023-07-17 22:32:49 -040011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Adrien Béraud612b55b2023-05-29 10:42:04 -040012 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
Adrien Béraudcb753622023-07-17 22:32:49 -040015 * along with this program. If not, see <https://www.gnu.org/licenses/>.
Adrien Béraud612b55b2023-05-29 10:42:04 -040016 */
Morteza Namvar5f639522023-07-04 17:08:58 -040017#include "upnp/mapping.h"
18// #include "logger.h"
Adrien Béraud33a03ba2023-06-21 11:35:54 -040019#include "igd.h"
Adrien Béraud612b55b2023-05-29 10:42:04 -040020
Adrien Béraud1ae60aa2023-07-07 09:55:09 -040021namespace dhtnet {
Adrien Béraud612b55b2023-05-29 10:42:04 -040022namespace upnp {
23
Adrien Berauda8731ac2023-08-17 12:19:39 -040024using namespace std::literals;
25
Adrien Béraud612b55b2023-05-29 10:42:04 -040026Mapping::Mapping(PortType type, uint16_t portExternal, uint16_t portInternal, bool available)
27 : type_(type)
28 , externalPort_(portExternal)
29 , internalPort_(portInternal)
30 , internalAddr_()
31 , igd_()
32 , available_(available)
33 , state_(MappingState::PENDING)
34 , notifyCb_(nullptr)
35 , autoUpdate_(false)
François-Simon Fauteux-Chapleaufd29c1d2024-05-30 16:48:26 -040036 , renewalTime_(sys_clock::time_point::max())
Adrien Béraud612b55b2023-05-29 10:42:04 -040037{}
38
39Mapping::Mapping(const Mapping& other)
40{
Adrien Béraud024c46f2024-03-02 23:53:18 -050041 std::lock_guard lock(other.mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -040042
43 internalAddr_ = other.internalAddr_;
44 internalPort_ = other.internalPort_;
45 externalPort_ = other.externalPort_;
46 type_ = other.type_;
47 igd_ = other.igd_;
48 available_ = other.available_;
49 state_ = other.state_;
50 notifyCb_ = other.notifyCb_;
51 autoUpdate_ = other.autoUpdate_;
Adrien Béraud612b55b2023-05-29 10:42:04 -040052 renewalTime_ = other.renewalTime_;
François-Simon Fauteux-Chapleaufd29c1d2024-05-30 16:48:26 -040053 expiryTime_ = other.expiryTime_;
Adrien Béraud612b55b2023-05-29 10:42:04 -040054}
55
56void
57Mapping::updateFrom(const Mapping::sharedPtr_t& other)
58{
59 updateFrom(*other);
60}
61
62void
63Mapping::updateFrom(const Mapping& other)
64{
65 if (type_ != other.type_) {
Morteza Namvar5f639522023-07-04 17:08:58 -040066 // JAMI_ERR("The source and destination types must match");
Adrien Béraud612b55b2023-05-29 10:42:04 -040067 return;
68 }
69
70 internalAddr_ = std::move(other.internalAddr_);
71 internalPort_ = other.internalPort_;
72 externalPort_ = other.externalPort_;
73 igd_ = other.igd_;
74 state_ = other.state_;
75}
76
77void
78Mapping::setAvailable(bool val)
79{
Morteza Namvar5f639522023-07-04 17:08:58 -040080 // JAMI_DBG("Changing mapping %s state from %s to %s",
81 // toString().c_str(),
82 // available_ ? "AVAILABLE" : "UNAVAILABLE",
83 // val ? "AVAILABLE" : "UNAVAILABLE");
Adrien Béraud612b55b2023-05-29 10:42:04 -040084
Adrien Béraud024c46f2024-03-02 23:53:18 -050085 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -040086 available_ = val;
87}
88
89void
90Mapping::setState(const MappingState& state)
91{
Adrien Béraud024c46f2024-03-02 23:53:18 -050092 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -040093 state_ = state;
94}
95
96const char*
97Mapping::getStateStr() const
98{
Adrien Béraud024c46f2024-03-02 23:53:18 -050099 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400100 return getStateStr(state_);
101}
102
103std::string
104Mapping::toString(bool extraInfo) const
105{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500106 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400107 std::ostringstream descr;
108 descr << UPNP_MAPPING_DESCRIPTION_PREFIX << "-" << getTypeStr(type_);
109 descr << ":" << std::to_string(internalPort_);
110
111 if (extraInfo) {
112 descr << " (state=" << getStateStr(state_)
113 << ", auto-update=" << (autoUpdate_ ? "YES" : "NO") << ")";
114 }
115
116 return descr.str();
117}
118
119bool
120Mapping::isValid() const
121{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500122 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400123 if (state_ == MappingState::FAILED)
124 return false;
125 if (internalPort_ == 0)
126 return false;
127 if (externalPort_ == 0)
128 return false;
129 if (not igd_ or not igd_->isValid())
130 return false;
131 IpAddr intAddr(internalAddr_);
132 return intAddr and not intAddr.isLoopback();
133}
134
135bool
136Mapping::hasValidHostAddress() const
137{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500138 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400139
140 IpAddr intAddr(internalAddr_);
141 return intAddr and not intAddr.isLoopback();
142}
143
144bool
145Mapping::hasPublicAddress() const
146{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500147 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400148
149 return igd_ and igd_->getPublicIp() and not igd_->getPublicIp().isPrivate();
150}
151
152Mapping::key_t
153Mapping::getMapKey() const
154{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500155 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400156
157 key_t mapKey = internalPort_;
158 if (type_ == PortType::UDP)
159 mapKey |= 1 << (sizeof(uint16_t) * 8);
160 return mapKey;
161}
162
163PortType
164Mapping::getTypeFromMapKey(key_t key)
165{
166 return (key >> (sizeof(uint16_t) * 8)) ? PortType::UDP : PortType::TCP;
167}
168
169std::string
170Mapping::getExternalAddress() const
171{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500172 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400173 if (igd_)
174 return igd_->getPublicIp().toString();
175 return {};
176}
177
178void
179Mapping::setExternalPort(uint16_t port)
180{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500181 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400182 externalPort_ = port;
183}
184
185uint16_t
186Mapping::getExternalPort() const
187{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500188 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400189 return externalPort_;
190}
191
192std::string
193Mapping::getExternalPortStr() const
194{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500195 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400196 return std::to_string(externalPort_);
197}
198
199void
200Mapping::setInternalAddress(const std::string& addr)
201{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500202 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400203 internalAddr_ = addr;
204}
205
206std::string
207Mapping::getInternalAddress() const
208{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500209 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400210 return internalAddr_;
211}
212
213void
214Mapping::setInternalPort(uint16_t port)
215{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500216 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400217 internalPort_ = port;
218}
219
220uint16_t
221Mapping::getInternalPort() const
222{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500223 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400224 return internalPort_;
225}
226
227std::string
228Mapping::getInternalPortStr() const
229{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500230 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400231 return std::to_string(internalPort_);
232}
233
234PortType
235Mapping::getType() const
236{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500237 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400238 return type_;
239}
240
241const char*
242Mapping::getTypeStr() const
243{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500244 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400245 return getTypeStr(type_);
246}
247
248bool
249Mapping::isAvailable() const
250{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500251 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400252 return available_;
253}
254
255std::shared_ptr<IGD>
256Mapping::getIgd() const
257{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500258 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400259 return igd_;
260}
261
262NatProtocolType
263Mapping::getProtocol() const
264{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500265 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400266 if (igd_)
267 return igd_->getProtocol();
268 return NatProtocolType::UNKNOWN;
269}
Adrien Berauda8731ac2023-08-17 12:19:39 -0400270
271std::string_view
Adrien Béraud612b55b2023-05-29 10:42:04 -0400272Mapping::getProtocolName() const
273{
Adrien Berauda8731ac2023-08-17 12:19:39 -0400274 switch(getProtocol()) {
275 case NatProtocolType::NAT_PMP:
276 return "NAT-PMP"sv;
277 case NatProtocolType::PUPNP:
278 return "PUPNP"sv;
279 default:
280 return "UNKNOWN"sv;
Adrien Béraud612b55b2023-05-29 10:42:04 -0400281 }
Adrien Béraud612b55b2023-05-29 10:42:04 -0400282}
283
284void
285Mapping::setIgd(const std::shared_ptr<IGD>& igd)
286{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500287 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400288 igd_ = igd;
289}
290
291MappingState
292Mapping::getState() const
293{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500294 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400295 return state_;
296}
297
298Mapping::NotifyCallback
299Mapping::getNotifyCallback() const
300{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500301 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400302 return notifyCb_;
303}
304
305void
306Mapping::setNotifyCallback(NotifyCallback cb)
307{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500308 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400309 notifyCb_ = std::move(cb);
310}
311
312void
313Mapping::enableAutoUpdate(bool enable)
314{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500315 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400316 autoUpdate_ = enable;
317}
318
319bool
320Mapping::getAutoUpdate() const
321{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500322 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400323 return autoUpdate_;
324}
325
Adrien Béraud612b55b2023-05-29 10:42:04 -0400326sys_clock::time_point
327Mapping::getRenewalTime() const
328{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500329 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400330 return renewalTime_;
331}
332
333void
334Mapping::setRenewalTime(sys_clock::time_point time)
335{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500336 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400337 renewalTime_ = time;
338}
François-Simon Fauteux-Chapleaufd29c1d2024-05-30 16:48:26 -0400339
340sys_clock::time_point
341Mapping::getExpiryTime() const
342{
343 std::lock_guard lock(mutex_);
344 return expiryTime_;
345}
346
347void
348Mapping::setExpiryTime(sys_clock::time_point time)
349{
350 std::lock_guard lock(mutex_);
351 expiryTime_ = time;
352}
Adrien Béraud612b55b2023-05-29 10:42:04 -0400353
354} // namespace upnp
Sébastien Blin464bdff2023-07-19 08:02:53 -0400355} // namespace dhtnet