blob: 7e3c03669b9ccb74238f8319706ca17f896fb865 [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 */
Andreas Traczyk9e064bf2024-09-05 16:10:11 -040017
Morteza Namvar5f639522023-07-04 17:08:58 -040018#include "upnp/mapping.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_) {
Adrien Béraud612b55b2023-05-29 10:42:04 -040066 return;
67 }
68
69 internalAddr_ = std::move(other.internalAddr_);
70 internalPort_ = other.internalPort_;
71 externalPort_ = other.externalPort_;
72 igd_ = other.igd_;
73 state_ = other.state_;
74}
75
76void
77Mapping::setAvailable(bool val)
78{
Adrien Béraud024c46f2024-03-02 23:53:18 -050079 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -040080 available_ = val;
81}
82
83void
84Mapping::setState(const MappingState& state)
85{
Adrien Béraud024c46f2024-03-02 23:53:18 -050086 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -040087 state_ = state;
88}
89
90const char*
91Mapping::getStateStr() const
92{
Adrien Béraud024c46f2024-03-02 23:53:18 -050093 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -040094 return getStateStr(state_);
95}
96
97std::string
98Mapping::toString(bool extraInfo) const
99{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500100 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400101 std::ostringstream descr;
102 descr << UPNP_MAPPING_DESCRIPTION_PREFIX << "-" << getTypeStr(type_);
103 descr << ":" << std::to_string(internalPort_);
104
105 if (extraInfo) {
106 descr << " (state=" << getStateStr(state_)
107 << ", auto-update=" << (autoUpdate_ ? "YES" : "NO") << ")";
108 }
109
110 return descr.str();
111}
112
113bool
114Mapping::isValid() const
115{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500116 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400117 if (state_ == MappingState::FAILED)
118 return false;
119 if (internalPort_ == 0)
120 return false;
121 if (externalPort_ == 0)
122 return false;
123 if (not igd_ or not igd_->isValid())
124 return false;
125 IpAddr intAddr(internalAddr_);
126 return intAddr and not intAddr.isLoopback();
127}
128
129bool
130Mapping::hasValidHostAddress() const
131{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500132 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400133
134 IpAddr intAddr(internalAddr_);
135 return intAddr and not intAddr.isLoopback();
136}
137
138bool
139Mapping::hasPublicAddress() const
140{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500141 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400142
143 return igd_ and igd_->getPublicIp() and not igd_->getPublicIp().isPrivate();
144}
145
146Mapping::key_t
147Mapping::getMapKey() const
148{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500149 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400150
151 key_t mapKey = internalPort_;
152 if (type_ == PortType::UDP)
153 mapKey |= 1 << (sizeof(uint16_t) * 8);
154 return mapKey;
155}
156
157PortType
158Mapping::getTypeFromMapKey(key_t key)
159{
160 return (key >> (sizeof(uint16_t) * 8)) ? PortType::UDP : PortType::TCP;
161}
162
163std::string
164Mapping::getExternalAddress() const
165{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500166 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400167 if (igd_)
168 return igd_->getPublicIp().toString();
169 return {};
170}
171
172void
173Mapping::setExternalPort(uint16_t port)
174{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500175 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400176 externalPort_ = port;
177}
178
179uint16_t
180Mapping::getExternalPort() const
181{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500182 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400183 return externalPort_;
184}
185
186std::string
187Mapping::getExternalPortStr() const
188{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500189 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400190 return std::to_string(externalPort_);
191}
192
193void
194Mapping::setInternalAddress(const std::string& addr)
195{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500196 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400197 internalAddr_ = addr;
198}
199
200std::string
201Mapping::getInternalAddress() const
202{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500203 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400204 return internalAddr_;
205}
206
207void
208Mapping::setInternalPort(uint16_t port)
209{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500210 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400211 internalPort_ = port;
212}
213
214uint16_t
215Mapping::getInternalPort() const
216{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500217 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400218 return internalPort_;
219}
220
221std::string
222Mapping::getInternalPortStr() const
223{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500224 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400225 return std::to_string(internalPort_);
226}
227
228PortType
229Mapping::getType() const
230{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500231 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400232 return type_;
233}
234
235const char*
236Mapping::getTypeStr() const
237{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500238 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400239 return getTypeStr(type_);
240}
241
242bool
243Mapping::isAvailable() const
244{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500245 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400246 return available_;
247}
248
249std::shared_ptr<IGD>
250Mapping::getIgd() const
251{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500252 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400253 return igd_;
254}
255
256NatProtocolType
257Mapping::getProtocol() const
258{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500259 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400260 if (igd_)
261 return igd_->getProtocol();
262 return NatProtocolType::UNKNOWN;
263}
Adrien Berauda8731ac2023-08-17 12:19:39 -0400264
265std::string_view
Adrien Béraud612b55b2023-05-29 10:42:04 -0400266Mapping::getProtocolName() const
267{
Adrien Berauda8731ac2023-08-17 12:19:39 -0400268 switch(getProtocol()) {
269 case NatProtocolType::NAT_PMP:
270 return "NAT-PMP"sv;
271 case NatProtocolType::PUPNP:
272 return "PUPNP"sv;
273 default:
274 return "UNKNOWN"sv;
Adrien Béraud612b55b2023-05-29 10:42:04 -0400275 }
Adrien Béraud612b55b2023-05-29 10:42:04 -0400276}
277
278void
279Mapping::setIgd(const std::shared_ptr<IGD>& igd)
280{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500281 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400282 igd_ = igd;
283}
284
285MappingState
286Mapping::getState() const
287{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500288 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400289 return state_;
290}
291
292Mapping::NotifyCallback
293Mapping::getNotifyCallback() const
294{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500295 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400296 return notifyCb_;
297}
298
299void
300Mapping::setNotifyCallback(NotifyCallback cb)
301{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500302 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400303 notifyCb_ = std::move(cb);
304}
305
306void
307Mapping::enableAutoUpdate(bool enable)
308{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500309 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400310 autoUpdate_ = enable;
311}
312
313bool
314Mapping::getAutoUpdate() const
315{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500316 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400317 return autoUpdate_;
318}
319
Adrien Béraud612b55b2023-05-29 10:42:04 -0400320sys_clock::time_point
321Mapping::getRenewalTime() const
322{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500323 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400324 return renewalTime_;
325}
326
327void
328Mapping::setRenewalTime(sys_clock::time_point time)
329{
Adrien Béraud024c46f2024-03-02 23:53:18 -0500330 std::lock_guard lock(mutex_);
Adrien Béraud612b55b2023-05-29 10:42:04 -0400331 renewalTime_ = time;
332}
François-Simon Fauteux-Chapleaufd29c1d2024-05-30 16:48:26 -0400333
334sys_clock::time_point
335Mapping::getExpiryTime() const
336{
337 std::lock_guard lock(mutex_);
338 return expiryTime_;
339}
340
341void
342Mapping::setExpiryTime(sys_clock::time_point time)
343{
344 std::lock_guard lock(mutex_);
345 expiryTime_ = time;
346}
Adrien Béraud612b55b2023-05-29 10:42:04 -0400347
348} // namespace upnp
Sébastien Blin464bdff2023-07-19 08:02:53 -0400349} // namespace dhtnet