add initial project structure
Change-Id: I6a3fb080ff623b312e42d71754480a7ce00b81a0
diff --git a/src/upnp/protocol/mapping.cpp b/src/upnp/protocol/mapping.cpp
new file mode 100644
index 0000000..9b38831
--- /dev/null
+++ b/src/upnp/protocol/mapping.cpp
@@ -0,0 +1,347 @@
+/*
+ * Copyright (C) 2004-2023 Savoir-faire Linux Inc.
+ *
+ * Author: Stepan Salenikovich <stepan.salenikovich@savoirfairelinux.com>
+ * Author: Eden Abitbol <eden.abitbol@savoirfairelinux.com>
+ * Author: Mohamed Chibani <mohamed.chibani@savoirfairelinux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "mapping.h"
+#include "logger.h"
+
+namespace jami {
+namespace upnp {
+
+Mapping::Mapping(PortType type, uint16_t portExternal, uint16_t portInternal, bool available)
+ : type_(type)
+ , externalPort_(portExternal)
+ , internalPort_(portInternal)
+ , internalAddr_()
+ , igd_()
+ , available_(available)
+ , state_(MappingState::PENDING)
+ , notifyCb_(nullptr)
+ , autoUpdate_(false)
+#if HAVE_LIBNATPMP
+ , renewalTime_(sys_clock::now())
+#endif
+{}
+
+Mapping::Mapping(const Mapping& other)
+{
+ std::lock_guard<std::mutex> lock(other.mutex_);
+
+ internalAddr_ = other.internalAddr_;
+ internalPort_ = other.internalPort_;
+ externalPort_ = other.externalPort_;
+ type_ = other.type_;
+ igd_ = other.igd_;
+ available_ = other.available_;
+ state_ = other.state_;
+ notifyCb_ = other.notifyCb_;
+ autoUpdate_ = other.autoUpdate_;
+#if HAVE_LIBNATPMP
+ renewalTime_ = other.renewalTime_;
+#endif
+}
+
+void
+Mapping::updateFrom(const Mapping::sharedPtr_t& other)
+{
+ updateFrom(*other);
+}
+
+void
+Mapping::updateFrom(const Mapping& other)
+{
+ if (type_ != other.type_) {
+ JAMI_ERR("The source and destination types must match");
+ return;
+ }
+
+ internalAddr_ = std::move(other.internalAddr_);
+ internalPort_ = other.internalPort_;
+ externalPort_ = other.externalPort_;
+ igd_ = other.igd_;
+ state_ = other.state_;
+}
+
+void
+Mapping::setAvailable(bool val)
+{
+ JAMI_DBG("Changing mapping %s state from %s to %s",
+ toString().c_str(),
+ available_ ? "AVAILABLE" : "UNAVAILABLE",
+ val ? "AVAILABLE" : "UNAVAILABLE");
+
+ std::lock_guard<std::mutex> lock(mutex_);
+ available_ = val;
+}
+
+void
+Mapping::setState(const MappingState& state)
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+ state_ = state;
+}
+
+const char*
+Mapping::getStateStr() const
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+ return getStateStr(state_);
+}
+
+std::string
+Mapping::toString(bool extraInfo) const
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+ std::ostringstream descr;
+ descr << UPNP_MAPPING_DESCRIPTION_PREFIX << "-" << getTypeStr(type_);
+ descr << ":" << std::to_string(internalPort_);
+
+ if (extraInfo) {
+ descr << " (state=" << getStateStr(state_)
+ << ", auto-update=" << (autoUpdate_ ? "YES" : "NO") << ")";
+ }
+
+ return descr.str();
+}
+
+bool
+Mapping::isValid() const
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+ if (state_ == MappingState::FAILED)
+ return false;
+ if (internalPort_ == 0)
+ return false;
+ if (externalPort_ == 0)
+ return false;
+ if (not igd_ or not igd_->isValid())
+ return false;
+ IpAddr intAddr(internalAddr_);
+ return intAddr and not intAddr.isLoopback();
+}
+
+bool
+Mapping::hasValidHostAddress() const
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+
+ IpAddr intAddr(internalAddr_);
+ return intAddr and not intAddr.isLoopback();
+}
+
+bool
+Mapping::hasPublicAddress() const
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+
+ return igd_ and igd_->getPublicIp() and not igd_->getPublicIp().isPrivate();
+}
+
+Mapping::key_t
+Mapping::getMapKey() const
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+
+ key_t mapKey = internalPort_;
+ if (type_ == PortType::UDP)
+ mapKey |= 1 << (sizeof(uint16_t) * 8);
+ return mapKey;
+}
+
+PortType
+Mapping::getTypeFromMapKey(key_t key)
+{
+ return (key >> (sizeof(uint16_t) * 8)) ? PortType::UDP : PortType::TCP;
+}
+
+std::string
+Mapping::getExternalAddress() const
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+ if (igd_)
+ return igd_->getPublicIp().toString();
+ return {};
+}
+
+void
+Mapping::setExternalPort(uint16_t port)
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+ externalPort_ = port;
+}
+
+uint16_t
+Mapping::getExternalPort() const
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+ return externalPort_;
+}
+
+std::string
+Mapping::getExternalPortStr() const
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+ return std::to_string(externalPort_);
+}
+
+void
+Mapping::setInternalAddress(const std::string& addr)
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+ internalAddr_ = addr;
+}
+
+std::string
+Mapping::getInternalAddress() const
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+ return internalAddr_;
+}
+
+void
+Mapping::setInternalPort(uint16_t port)
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+ internalPort_ = port;
+}
+
+uint16_t
+Mapping::getInternalPort() const
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+ return internalPort_;
+}
+
+std::string
+Mapping::getInternalPortStr() const
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+ return std::to_string(internalPort_);
+}
+
+PortType
+Mapping::getType() const
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+ return type_;
+}
+
+const char*
+Mapping::getTypeStr() const
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+ return getTypeStr(type_);
+}
+
+bool
+Mapping::isAvailable() const
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+ return available_;
+}
+
+std::shared_ptr<IGD>
+Mapping::getIgd() const
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+ return igd_;
+}
+
+NatProtocolType
+Mapping::getProtocol() const
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+ if (igd_)
+ return igd_->getProtocol();
+ return NatProtocolType::UNKNOWN;
+}
+const char*
+Mapping::getProtocolName() const
+{
+ if (igd_) {
+ if (igd_->getProtocol() == NatProtocolType::NAT_PMP)
+ return "NAT-PMP";
+ if (igd_->getProtocol() == NatProtocolType::PUPNP)
+ return "PUPNP";
+ }
+ return "UNKNOWN";
+}
+
+void
+Mapping::setIgd(const std::shared_ptr<IGD>& igd)
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+ igd_ = igd;
+}
+
+MappingState
+Mapping::getState() const
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+ return state_;
+}
+
+Mapping::NotifyCallback
+Mapping::getNotifyCallback() const
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+ return notifyCb_;
+}
+
+void
+Mapping::setNotifyCallback(NotifyCallback cb)
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+ notifyCb_ = std::move(cb);
+}
+
+void
+Mapping::enableAutoUpdate(bool enable)
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+ autoUpdate_ = enable;
+}
+
+bool
+Mapping::getAutoUpdate() const
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+ return autoUpdate_;
+}
+
+#if HAVE_LIBNATPMP
+sys_clock::time_point
+Mapping::getRenewalTime() const
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+ return renewalTime_;
+}
+
+void
+Mapping::setRenewalTime(sys_clock::time_point time)
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+ renewalTime_ = time;
+}
+#endif
+
+} // namespace upnp
+} // namespace jami