blob: 6c58c21c01bee48597e4232d0bfe43b2af29d1bb [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 Béraud612b55b2023-05-29 10:42:04 -040026 upnpContext_->registerController(this);
Morteza Namvar5f639522023-07-04 17:08:58 -040027 // JAMI_DBG("Controller@%p: Created UPnP Controller session", this);
Adrien Béraud612b55b2023-05-29 10:42:04 -040028}
29
30Controller::~Controller()
31{
Morteza Namvar5f639522023-07-04 17:08:58 -040032 // JAMI_DBG("Controller@%p: Destroying UPnP Controller session", this);
Adrien Béraud612b55b2023-05-29 10:42:04 -040033
34 releaseAllMappings();
35 upnpContext_->unregisterController(this);
36}
37
38void
39Controller::setPublicAddress(const IpAddr& addr)
40{
41 assert(upnpContext_);
42
43 if (addr and addr.getFamily() == AF_INET) {
44 upnpContext_->setPublicAddress(addr);
45 }
46}
47
48bool
49Controller::isReady() const
50{
51 assert(upnpContext_);
52 return upnpContext_->isReady();
53}
54
55IpAddr
56Controller::getExternalIP() const
57{
58 assert(upnpContext_);
59 if (upnpContext_->isReady()) {
60 return upnpContext_->getExternalIP();
61 }
62 return {};
63}
64
65Mapping::sharedPtr_t
66Controller::reserveMapping(uint16_t port, PortType type)
67{
68 Mapping map(type, port, port);
69 return reserveMapping(map);
70}
71
72Mapping::sharedPtr_t
73Controller::reserveMapping(Mapping& requestedMap)
74{
75 assert(upnpContext_);
76
77 // Try to get a provisioned port
78 auto mapRes = upnpContext_->reserveMapping(requestedMap);
79 if (mapRes)
80 addLocalMap(*mapRes);
81 return mapRes;
82}
83
84void
85Controller::releaseMapping(const Mapping& map)
86{
87 assert(upnpContext_);
88
89 removeLocalMap(map);
90 return upnpContext_->releaseMapping(map);
91}
92
93void
94Controller::releaseAllMappings()
95{
96 assert(upnpContext_);
97
98 std::lock_guard<std::mutex> lk(mapListMutex_);
99 for (auto const& [_, map] : mappingList_) {
100 upnpContext_->releaseMapping(map);
101 }
102 mappingList_.clear();
103}
104
105void
106Controller::addLocalMap(const Mapping& map)
107{
108 if (map.getMapKey()) {
109 std::lock_guard<std::mutex> lock(mapListMutex_);
110 auto ret = mappingList_.emplace(map.getMapKey(), map);
111 if (not ret.second) {
Morteza Namvar5f639522023-07-04 17:08:58 -0400112 // JAMI_WARN("Mapping request for %s already in the list!", map.toString().c_str());
Adrien Béraud612b55b2023-05-29 10:42:04 -0400113 }
114 }
115}
116
117bool
118Controller::removeLocalMap(const Mapping& map)
119{
120 assert(upnpContext_);
121
122 std::lock_guard<std::mutex> lk(mapListMutex_);
123 if (mappingList_.erase(map.getMapKey()) != 1) {
Morteza Namvar5f639522023-07-04 17:08:58 -0400124 // JAMI_ERR("Failed to remove mapping %s from local list", map.getTypeStr());
Adrien Béraud612b55b2023-05-29 10:42:04 -0400125 return false;
126 }
127
128 return true;
129}
130
131uint16_t
132Controller::generateRandomPort(PortType type)
133{
134 return UPnPContext::generateRandomPort(type);
135}
136
137} // namespace upnp
Sébastien Blin464bdff2023-07-19 08:02:53 -0400138} // namespace dhtnet