diff --git a/src/upnp/protocol/pupnp/pupnp.cpp b/src/upnp/protocol/pupnp/pupnp.cpp
index c43d0311c22058b99d53b942d60c3ac596cb1b47..9d5942758c369a0191b58b020f0bee5488687605 100644
--- a/src/upnp/protocol/pupnp/pupnp.cpp
+++ b/src/upnp/protocol/pupnp/pupnp.cpp
@@ -48,45 +48,39 @@ constexpr static unsigned int SEARCH_TIMEOUT {60};
 constexpr static auto PUPNP_SEARCH_RETRY_UNIT {std::chrono::seconds(10)};
 
 // Helper functions for xml parsing.
-static std::string
+static std::string_view
 getElementText(IXML_Node* node)
 {
-    std::string ret;
     if (node) {
-        IXML_Node* textNode = ixmlNode_getFirstChild(node);
-        if (textNode) {
-            const char* value = ixmlNode_getNodeValue(textNode);
-            if (value)
-                ret = std::string(value);
-        }
+        if (IXML_Node* textNode = ixmlNode_getFirstChild(node))
+            if (const char* value = ixmlNode_getNodeValue(textNode))
+                return std::string_view(value);
     }
-    return ret;
+    return {};
 }
 
-static std::string
+static std::string_view
 getFirstDocItem(IXML_Document* doc, const char* item)
 {
-    std::string ret;
     std::unique_ptr<IXML_NodeList, decltype(ixmlNodeList_free)&>
         nodeList(ixmlDocument_getElementsByTagName(doc, item), ixmlNodeList_free);
     if (nodeList) {
         // If there are several nodes which match the tag, we only want the first one.
-        ret = getElementText(ixmlNodeList_item(nodeList.get(), 0));
+        return getElementText(ixmlNodeList_item(nodeList.get(), 0));
     }
-    return ret;
+    return {};
 }
 
-static std::string
+static std::string_view
 getFirstElementItem(IXML_Element* element, const char* item)
 {
-    std::string ret;
     std::unique_ptr<IXML_NodeList, decltype(ixmlNodeList_free)&>
         nodeList(ixmlElement_getElementsByTagName(element, item), ixmlNodeList_free);
     if (nodeList) {
         // If there are several nodes which match the tag, we only want the first one.
-        ret = getElementText(ixmlNodeList_item(nodeList.get(), 0));
+        return getElementText(ixmlNodeList_item(nodeList.get(), 0));
     }
-    return ret;
+    return {};
 }
 
 static bool
@@ -95,12 +89,12 @@ errorOnResponse(IXML_Document* doc)
     if (not doc)
         return true;
 
-    std::string errorCode = getFirstDocItem(doc, "errorCode");
+    auto errorCode = getFirstDocItem(doc, "errorCode");
     if (not errorCode.empty()) {
-        std::string errorDescription = getFirstDocItem(doc, "errorDescription");
-        JAMI_WARN("PUPnP: Response contains error: %s : %s",
-                  errorCode.c_str(),
-                  errorDescription.c_str());
+        auto errorDescription = getFirstDocItem(doc, "errorDescription");
+        JAMI_WARNING("PUPnP: Response contains error: {:s}: {:s}",
+                  errorCode,
+                  errorDescription);
         return true;
     }
     return false;
@@ -473,13 +467,8 @@ PUPnP::validateIgd(const std::string& location, IXML_Document* doc_container_ptr
     XMLDocument document(doc_container_ptr, ixmlDocument_free);
     auto descDoc = document.get();
     // Check device type.
-    std::string deviceType = getFirstDocItem(descDoc, "deviceType");
-    if (deviceType.empty()) {
-        // No device type.
-        return false;
-    }
-
-    if (deviceType.compare(UPNP_IGD_DEVICE) != 0) {
+    auto deviceType = getFirstDocItem(descDoc, "deviceType");
+    if (deviceType != UPNP_IGD_DEVICE) {
         // Device type not IGD.
         return false;
     }
@@ -1080,7 +1069,7 @@ PUPnP::parseIgd(IXML_Document* doc, std::string locationUrl)
         return nullptr;
 
     // Check the UDN to see if its already in our device list.
-    std::string UDN = getFirstDocItem(doc, "UDN");
+    std::string UDN(getFirstDocItem(doc, "UDN"));
     if (UDN.empty()) {
         JAMI_WARN("PUPnP: could not find UDN in description document of device");
         return nullptr;
@@ -1100,10 +1089,10 @@ PUPnP::parseIgd(IXML_Document* doc, std::string locationUrl)
     int upnp_err;
 
     // Get friendly name.
-    std::string friendlyName = getFirstDocItem(doc, "friendlyName");
+    std::string friendlyName(getFirstDocItem(doc, "friendlyName"));
 
     // Get base URL.
-    std::string baseURL = getFirstDocItem(doc, "URLBase");
+    std::string baseURL(getFirstDocItem(doc, "URLBase"));
     if (baseURL.empty())
         baseURL = locationUrl;
 
@@ -1116,11 +1105,11 @@ PUPnP::parseIgd(IXML_Document* doc, std::string locationUrl)
     // Go through the "serviceType" nodes until we find the the correct service type.
     for (unsigned long node_idx = 0; node_idx < list_length; node_idx++) {
         IXML_Node* serviceType_node = ixmlNodeList_item(serviceList.get(), node_idx);
-        std::string serviceType = getElementText(serviceType_node);
+        std::string serviceType(getElementText(serviceType_node));
 
         // Only check serviceType of WANIPConnection or WANPPPConnection.
-        if (serviceType != std::string(UPNP_WANIP_SERVICE)
-            && serviceType != std::string(UPNP_WANPPP_SERVICE)) {
+        if (serviceType != UPNP_WANIP_SERVICE
+            && serviceType != UPNP_WANPPP_SERVICE) {
             // IGD is not WANIP or WANPPP service. Going to next node.
             continue;
         }
@@ -1140,14 +1129,14 @@ PUPnP::parseIgd(IXML_Document* doc, std::string locationUrl)
 
         // Get serviceId.
         IXML_Element* service_element = (IXML_Element*) service_node;
-        std::string serviceId = getFirstElementItem(service_element, "serviceId");
+        std::string serviceId(getFirstElementItem(service_element, "serviceId"));
         if (serviceId.empty()) {
             // IGD "serviceId" is empty. Going to next node.
             continue;
         }
 
         // Get the relative controlURL and turn it into absolute address using the URLBase.
-        std::string controlURL = getFirstElementItem(service_element, "controlURL");
+        std::string controlURL(getFirstElementItem(service_element, "controlURL"));
         if (controlURL.empty()) {
             // IGD control URL is empty. Going to next node.
             continue;
@@ -1164,7 +1153,7 @@ PUPnP::parseIgd(IXML_Document* doc, std::string locationUrl)
         std::free(absolute_control_url);
 
         // Get the relative eventSubURL and turn it into absolute address using the URLBase.
-        std::string eventSubURL = getFirstElementItem(service_element, "eventSubURL");
+        std::string eventSubURL(getFirstElementItem(service_element, "eventSubURL"));
         if (eventSubURL.empty()) {
             JAMI_WARN("PUPnP: IGD event sub URL is empty. Going to next node");
             continue;
@@ -1201,38 +1190,29 @@ PUPnP::actionIsIgdConnected(const UPnPIGD& igd)
     if (not clientRegistered_)
         return false;
 
-    // Action and response pointers.
-    XMLDocument action(nullptr, ixmlDocument_free); // Action pointer.
-    IXML_Document* action_container_ptr = nullptr;
-    XMLDocument response(nullptr, ixmlDocument_free); // Response pointer.
-    IXML_Document* response_container_ptr = nullptr;
-
     // Set action name.
-    std::string action_name {"GetStatusInfo"};
-
-    action_container_ptr = UpnpMakeAction(action_name.c_str(),
+    IXML_Document* action_container_ptr = UpnpMakeAction("GetStatusInfo",
                                           igd.getServiceType().c_str(),
                                           0,
                                           nullptr);
-    action.reset(action_container_ptr);
-
-    if (not action) {
+    if (not action_container_ptr) {
         JAMI_WARN("PUPnP: Failed to make GetStatusInfo action");
         return false;
     }
+    XMLDocument action(action_container_ptr, ixmlDocument_free); // Action pointer.
 
+    IXML_Document* response_container_ptr = nullptr;
     int upnp_err = UpnpSendAction(ctrlptHandle_,
                                   igd.getControlURL().c_str(),
                                   igd.getServiceType().c_str(),
                                   nullptr,
                                   action.get(),
                                   &response_container_ptr);
-    response.reset(response_container_ptr);
-
-    if (not response or upnp_err != UPNP_E_SUCCESS) {
+    if (not response_container_ptr or upnp_err != UPNP_E_SUCCESS) {
         JAMI_WARN("PUPnP: Failed to send GetStatusInfo action -> %s", UpnpGetErrorMessage(upnp_err));
         return false;
     }
+    XMLDocument response(response_container_ptr, ixmlDocument_free);
 
     if (errorOnResponse(response.get())) {
         JAMI_WARN("PUPnP: Failed to get GetStatusInfo from %s -> %d: %s",
@@ -1243,11 +1223,8 @@ PUPnP::actionIsIgdConnected(const UPnPIGD& igd)
     }
 
     // Parse response.
-    std::string status = getFirstDocItem(response.get(), "NewConnectionStatus");
-    if (status.compare("Connected") != 0)
-        return false;
-
-    return true;
+    auto status = getFirstDocItem(response.get(), "NewConnectionStatus");
+    return status == "Connected";
 }
 
 IpAddr
@@ -1354,25 +1331,25 @@ PUPnP::getMappingsListByDescr(const std::shared_ptr<IGD>& igd, const std::string
         }
 
         // Check error code.
-        std::string errorCode = getFirstDocItem(response.get(), "errorCode");
+        auto errorCode = getFirstDocItem(response.get(), "errorCode");
         if (not errorCode.empty()) {
-            if (std::stoi(errorCode) == ARRAY_IDX_INVALID
-                or std::stoi(errorCode) == CONFLICT_IN_MAPPING) {
+            auto error = to_int<int>(errorCode);
+            if (error == ARRAY_IDX_INVALID or error == CONFLICT_IN_MAPPING) {
                 // No more port mapping entries in the response.
                 JAMI_DBG("PUPnP: No more mappings (found a total of %i mappings", entry_idx);
                 break;
             } else {
-                std::string errorDescription = getFirstDocItem(response.get(), "errorDescription");
-                JAMI_ERR("PUPnP: GetGenericPortMappingEntry returned with error: %s: %s",
-                         errorCode.c_str(),
-                         errorDescription.c_str());
+                auto errorDescription = getFirstDocItem(response.get(), "errorDescription");
+                JAMI_ERROR("PUPnP: GetGenericPortMappingEntry returned with error: {:s}: {:s}",
+                         errorCode,
+                         errorDescription);
                 break;
             }
         }
 
         // Parse the response.
-        std::string desc_actual = getFirstDocItem(response.get(), "NewPortMappingDescription");
-        std::string client_ip = getFirstDocItem(response.get(), "NewInternalClient");
+        auto desc_actual = getFirstDocItem(response.get(), "NewPortMappingDescription");
+        auto client_ip = getFirstDocItem(response.get(), "NewInternalClient");
 
         if (client_ip != getHostAddress().toString()) {
             // Silently ignore un-matching addresses.
@@ -1382,9 +1359,9 @@ PUPnP::getMappingsListByDescr(const std::shared_ptr<IGD>& igd, const std::string
         if (desc_actual.find(description) == std::string::npos)
             continue;
 
-        const std::string& port_internal = getFirstDocItem(response.get(), "NewInternalPort");
-        const std::string& port_external = getFirstDocItem(response.get(), "NewExternalPort");
-        std::string transport = getFirstDocItem(response.get(), "NewProtocol");
+        auto port_internal = getFirstDocItem(response.get(), "NewInternalPort");
+        auto port_external = getFirstDocItem(response.get(), "NewExternalPort");
+        std::string transport(getFirstDocItem(response.get(), "NewProtocol"));
 
         if (port_internal.empty() || port_external.empty() || transport.empty()) {
             JAMI_ERR("PUPnP: GetGenericPortMappingEntry returned an invalid entry at index %i",
@@ -1394,8 +1371,8 @@ PUPnP::getMappingsListByDescr(const std::shared_ptr<IGD>& igd, const std::string
 
         std::transform(transport.begin(), transport.end(), transport.begin(), ::toupper);
         PortType type = transport.find("TCP") != std::string::npos ? PortType::TCP : PortType::UDP;
-        uint16_t ePort = static_cast<uint16_t>(std::stoi(port_external));
-        uint16_t iPort = static_cast<uint16_t>(std::stoi(port_internal));
+        auto ePort = to_int<uint16_t>(port_external);
+        auto iPort = to_int<uint16_t>(port_internal);
 
         Mapping map(type, ePort, iPort);
         map.setIgd(igd);
@@ -1518,7 +1495,7 @@ PUPnP::actionAddPortMapping(const Mapping& mapping)
     }
 
     // Check if an error has occurred.
-    std::string errorCode = getFirstDocItem(response.get(), "errorCode");
+    auto errorCode = getFirstDocItem(response.get(), "errorCode");
     if (not errorCode.empty()) {
         success = false;
         // Try to get the error description.
@@ -1527,10 +1504,10 @@ PUPnP::actionAddPortMapping(const Mapping& mapping)
             errorDescription = getFirstDocItem(response.get(), "errorDescription");
         }
 
-        JAMI_WARN("PUPnP: %s returned with error: %s %s",
+        JAMI_WARNING("PUPnP: {:s} returned with error: {:s} {:s}",
                   ACTION_ADD_PORT_MAPPING,
-                  errorCode.c_str(),
-                  errorDescription.c_str());
+                  errorCode,
+                  errorDescription);
     }
     return success;
 }
@@ -1606,13 +1583,13 @@ PUPnP::actionDeletePortMapping(const Mapping& mapping)
     }
 
     // Check if there is an error code.
-    std::string errorCode = getFirstDocItem(response.get(), "errorCode");
+    auto errorCode = getFirstDocItem(response.get(), "errorCode");
     if (not errorCode.empty()) {
-        std::string errorDescription = getFirstDocItem(response.get(), "errorDescription");
-        JAMI_WARN("PUPnP: %s returned with error: %s: %s",
+        auto errorDescription = getFirstDocItem(response.get(), "errorDescription");
+        JAMI_WARNING("PUPnP: {:s} returned with error: {:s}: {:s}",
                   ACTION_DELETE_PORT_MAPPING,
-                  errorCode.c_str(),
-                  errorDescription.c_str());
+                  errorCode,
+                  errorDescription);
         success = false;
     }