blob: 4ee6a436560fdac66d01345b2d793a18982cb457 [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/upnp_control.h"
18#include "upnp/upnp_context.h"
Adrien Béraud612b55b2023-05-29 10:42:04 -040019
Adrien Béraud1ae60aa2023-07-07 09:55:09 -040020namespace dhtnet {
Adrien Béraud612b55b2023-05-29 10:42:04 -040021namespace upnp {
22
Adrien Béraud25c30c42023-07-05 13:46:54 -040023Controller::Controller(const std::shared_ptr<UPnPContext>& ctx)
24 : upnpContext_(ctx)
Adrien Béraud612b55b2023-05-29 10:42:04 -040025{
Adrien Berauda8731ac2023-08-17 12:19:39 -040026 upnpContext_->dispatch([c=upnpContext_, this]{
27 c->registerController(this);
28 });
29 //if (upnpContext_->logger_) upnpContext_->logger_->debug("Controller@{}: Created UPnP Controller session", fmt::ptr(this));
Adrien Béraud612b55b2023-05-29 10:42:04 -040030}
31
32Controller::~Controller()
33{
Adrien Berauda8731ac2023-08-17 12:19:39 -040034 //if (logger_) logger_->debug("Controller@{}: Destroying UPnP Controller session", fmt::ptr(this));
Adrien Béraud612b55b2023-05-29 10:42:04 -040035
36 releaseAllMappings();
Adrien Berauda8731ac2023-08-17 12:19:39 -040037 upnpContext_->dispatch([c=upnpContext_, this]{
38 c->unregisterController(this);
39 });
Adrien Béraud612b55b2023-05-29 10:42:04 -040040}
41
42void
43Controller::setPublicAddress(const IpAddr& addr)
44{
45 assert(upnpContext_);
46
47 if (addr and addr.getFamily() == AF_INET) {
48 upnpContext_->setPublicAddress(addr);
49 }
50}
51
52bool
53Controller::isReady() const
54{
55 assert(upnpContext_);
56 return upnpContext_->isReady();
57}
58
59IpAddr
60Controller::getExternalIP() const
61{
62 assert(upnpContext_);
63 if (upnpContext_->isReady()) {
64 return upnpContext_->getExternalIP();
65 }
66 return {};
67}
68
69Mapping::sharedPtr_t
70Controller::reserveMapping(uint16_t port, PortType type)
71{
72 Mapping map(type, port, port);
73 return reserveMapping(map);
74}
75
76Mapping::sharedPtr_t
77Controller::reserveMapping(Mapping& requestedMap)
78{
79 assert(upnpContext_);
80
81 // Try to get a provisioned port
82 auto mapRes = upnpContext_->reserveMapping(requestedMap);
83 if (mapRes)
84 addLocalMap(*mapRes);
85 return mapRes;
86}
87
88void
89Controller::releaseMapping(const Mapping& map)
90{
91 assert(upnpContext_);
92
93 removeLocalMap(map);
94 return upnpContext_->releaseMapping(map);
95}
96
97void
98Controller::releaseAllMappings()
99{
100 assert(upnpContext_);
101
102 std::lock_guard<std::mutex> lk(mapListMutex_);
103 for (auto const& [_, map] : mappingList_) {
104 upnpContext_->releaseMapping(map);
105 }
106 mappingList_.clear();
107}
108
109void
110Controller::addLocalMap(const Mapping& map)
111{
112 if (map.getMapKey()) {
113 std::lock_guard<std::mutex> lock(mapListMutex_);
114 auto ret = mappingList_.emplace(map.getMapKey(), map);
115 if (not ret.second) {
Morteza Namvar5f639522023-07-04 17:08:58 -0400116 // JAMI_WARN("Mapping request for %s already in the list!", map.toString().c_str());
Adrien Béraud612b55b2023-05-29 10:42:04 -0400117 }
118 }
119}
120
121bool
122Controller::removeLocalMap(const Mapping& map)
123{
124 assert(upnpContext_);
125
126 std::lock_guard<std::mutex> lk(mapListMutex_);
127 if (mappingList_.erase(map.getMapKey()) != 1) {
Morteza Namvar5f639522023-07-04 17:08:58 -0400128 // JAMI_ERR("Failed to remove mapping %s from local list", map.getTypeStr());
Adrien Béraud612b55b2023-05-29 10:42:04 -0400129 return false;
130 }
131
132 return true;
133}
134
135uint16_t
136Controller::generateRandomPort(PortType type)
137{
138 return UPnPContext::generateRandomPort(type);
139}
140
141} // namespace upnp
Sébastien Blin464bdff2023-07-19 08:02:53 -0400142} // namespace dhtnet