blob: e92a654b33b373011c75be5a2bf852106760bde5 [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 */
Adrien Béraud612b55b2023-05-29 10:42:04 -040017#pragma once
18
Adrien Bérauddbb06862023-07-08 09:18:39 -040019#include "../ip_utils.h"
Adrien Béraud612b55b2023-05-29 10:42:04 -040020
21#include <map>
22#include <string>
23#include <chrono>
24#include <functional>
25#include <mutex>
Morteza Namvar5f639522023-07-04 17:08:58 -040026#include <memory>
Adrien Béraud612b55b2023-05-29 10:42:04 -040027
Adrien Béraud1ae60aa2023-07-07 09:55:09 -040028namespace dhtnet {
Adrien Béraud612b55b2023-05-29 10:42:04 -040029namespace upnp {
30
31using sys_clock = std::chrono::system_clock;
32
33enum class PortType { TCP, UDP };
34enum class MappingState { PENDING, IN_PROGRESS, FAILED, OPEN };
35
36enum class NatProtocolType;
37class IGD;
38
Adrien Béraud56740312023-08-23 08:38:28 -040039class Mapping
Adrien Béraud612b55b2023-05-29 10:42:04 -040040{
41 friend class UPnPContext;
42 friend class NatPmp;
43 friend class PUPnP;
44
45public:
46 using key_t = uint64_t;
47 using sharedPtr_t = std::shared_ptr<Mapping>;
48 using NotifyCallback = std::function<void(sharedPtr_t)>;
49
50 static constexpr char const* MAPPING_STATE_STR[4] {"PENDING", "IN_PROGRESS", "FAILED", "OPEN"};
51 static constexpr char const* UPNP_MAPPING_DESCRIPTION_PREFIX {"JAMI"};
52
53 Mapping(PortType type,
54 uint16_t portExternal = 0,
55 uint16_t portInternal = 0,
56 bool available = true);
57 Mapping(const Mapping& other);
58 Mapping(Mapping&& other) = delete;
59 ~Mapping() = default;
60
61 // Delete operators with confusing semantic.
62 Mapping& operator=(Mapping&& other) = delete;
63 bool operator==(const Mapping& other) = delete;
64 bool operator!=(const Mapping& other) = delete;
65 bool operator<(const Mapping& other) = delete;
66 bool operator>(const Mapping& other) = delete;
67 bool operator<=(const Mapping& other) = delete;
68 bool operator>=(const Mapping& other) = delete;
69
70 inline explicit operator bool() const { return isValid(); }
71
72 void updateFrom(const Mapping& other);
73 void updateFrom(const Mapping::sharedPtr_t& other);
74 std::string getExternalAddress() const;
75 uint16_t getExternalPort() const;
76 std::string getExternalPortStr() const;
77 std::string getInternalAddress() const;
78 uint16_t getInternalPort() const;
79 std::string getInternalPortStr() const;
80 PortType getType() const;
81 const char* getTypeStr() const;
82 static const char* getTypeStr(PortType type) { return type == PortType::UDP ? "UDP" : "TCP"; }
83 std::shared_ptr<IGD> getIgd() const;
84 NatProtocolType getProtocol() const;
Adrien Berauda8731ac2023-08-17 12:19:39 -040085 std::string_view getProtocolName() const;
Adrien Béraud612b55b2023-05-29 10:42:04 -040086 bool isAvailable() const;
87 MappingState getState() const;
88 const char* getStateStr() const;
89 static const char* getStateStr(MappingState state)
90 {
91 return MAPPING_STATE_STR[static_cast<int>(state)];
92 }
93 std::string toString(bool extraInfo = false) const;
94 bool isValid() const;
95 bool hasValidHostAddress() const;
96 bool hasPublicAddress() const;
97 void setNotifyCallback(NotifyCallback cb);
98 void enableAutoUpdate(bool enable);
99 bool getAutoUpdate() const;
100 key_t getMapKey() const;
101 static PortType getTypeFromMapKey(key_t key);
102#if HAVE_LIBNATPMP
103 sys_clock::time_point getRenewalTime() const;
104#endif
105
106private:
107 NotifyCallback getNotifyCallback() const;
108 void setInternalAddress(const std::string& addr);
109 void setExternalPort(uint16_t port);
110 void setInternalPort(uint16_t port);
111
112 void setIgd(const std::shared_ptr<IGD>& igd);
113 void setAvailable(bool val);
114 void setState(const MappingState& state);
115 void updateDescription();
116#if HAVE_LIBNATPMP
117 void setRenewalTime(sys_clock::time_point time);
118#endif
119
120 mutable std::mutex mutex_;
121 PortType type_ {PortType::UDP};
122 uint16_t externalPort_ {0};
123 uint16_t internalPort_ {0};
124 std::string internalAddr_;
125 // Protocol and
126 std::shared_ptr<IGD> igd_;
127 // Track if the mapping is available to use.
128 bool available_;
129 // Track the state of the mapping
130 MappingState state_;
131 NotifyCallback notifyCb_;
132 // If true, a new mapping will be requested on behave of the mapping
133 // owner when the mapping state changes from "OPEN" to "FAILED".
134 bool autoUpdate_;
135#if HAVE_LIBNATPMP
136 sys_clock::time_point renewalTime_;
137#endif
138};
139
140} // namespace upnp
Sébastien Blin464bdff2023-07-19 08:02:53 -0400141} // namespace dhtnet