Line data Source code
1 : /* 2 : * Copyright (C) 2004-2024 Savoir-faire Linux Inc. 3 : * 4 : * Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com> 5 : * 6 : * This program is free software; you can redistribute it and/or modify 7 : * it under the terms of the GNU General Public License as published by 8 : * the Free Software Foundation; either version 3 of the License, or 9 : * (at your option) any later version. 10 : * 11 : * This program is distributed in the hope that it will be useful, 12 : * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 : * GNU General Public License for more details. 15 : * 16 : * You should have received a copy of the GNU General Public License 17 : * along with this program; if not, write to the Free Software 18 : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 : */ 20 : 21 : #pragma once 22 : 23 : #include "connectivity/ip_utils.h" 24 : #include "media/media_codec.h" 25 : #include "noncopyable.h" 26 : 27 : #include <utility> 28 : #include <string> 29 : #include <vector> 30 : #include <cstring> // strcmp 31 : 32 : #include <dhtnet/ip_utils.h> 33 : 34 : #include <pjsip/sip_msg.h> 35 : #include <pjlib.h> 36 : #include <pj/pool.h> 37 : #include <pjsip/sip_endpoint.h> 38 : #include <pjsip/sip_dialog.h> 39 : 40 : namespace jami { 41 : namespace sip_utils { 42 : 43 : using namespace std::literals; 44 : 45 : // SIP methods. Only list methods that need to be explicitly 46 : // handled 47 : 48 : namespace SIP_METHODS { 49 : constexpr std::string_view MESSAGE = "MESSAGE"sv; 50 : constexpr std::string_view INFO = "INFO"sv; 51 : constexpr std::string_view OPTIONS = "OPTIONS"sv; 52 : constexpr std::string_view PUBLISH = "PUBLISH"sv; 53 : constexpr std::string_view REFER = "REFER"sv; 54 : constexpr std::string_view NOTIFY = "NOTIFY"sv; 55 : } // namespace SIP_METHODS 56 : 57 : static constexpr int DEFAULT_SIP_PORT {5060}; 58 : static constexpr int DEFAULT_SIP_TLS_PORT {5061}; 59 : static constexpr int DEFAULT_AUTO_SELECT_PORT {0}; 60 : 61 : /// PjsipErrorCategory - a PJSIP error category for std::error_code 62 : class PjsipErrorCategory final : public std::error_category 63 : { 64 : public: 65 0 : const char* name() const noexcept override { return "pjsip"; } 66 : std::string message(int condition) const override; 67 : }; 68 : 69 : /// PJSIP related exception 70 : /// Based on std::system_error with code() returning std::error_code with PjsipErrorCategory category 71 : class PjsipFailure : public std::system_error 72 : { 73 : private: 74 : static constexpr const char* what_ = "PJSIP call failed"; 75 : 76 : public: 77 : PjsipFailure() 78 : : std::system_error(std::error_code(PJ_EUNKNOWN, PjsipErrorCategory()), what_) 79 : {} 80 : 81 : explicit PjsipFailure(pj_status_t status) 82 : : std::system_error(std::error_code(status, PjsipErrorCategory()), what_) 83 : {} 84 : }; 85 : 86 : std::string sip_strerror(pj_status_t code); 87 : 88 : // Helper function that return a constant pj_str_t from an array of any types 89 : // that may be statically casted into char pointer. 90 : // Per convention, the input array is supposed to be null terminated. 91 : template<typename T, std::size_t N> 92 : constexpr const pj_str_t 93 2333 : CONST_PJ_STR(T (&a)[N]) noexcept 94 : { 95 2333 : return {const_cast<char*>(a), N - 1}; 96 : } 97 : 98 : inline const pj_str_t 99 140917 : CONST_PJ_STR(const std::string& str) noexcept 100 : { 101 140917 : return {const_cast<char*>(str.c_str()), (pj_ssize_t) str.size()}; 102 : } 103 : 104 : inline constexpr pj_str_t 105 89795 : CONST_PJ_STR(const std::string_view& str) noexcept 106 : { 107 89795 : return {const_cast<char*>(str.data()), (pj_ssize_t) str.size()}; 108 : } 109 : 110 : inline constexpr std::string_view 111 81984 : as_view(const pj_str_t& str) noexcept 112 : { 113 81984 : return {str.ptr, (size_t) str.slen}; 114 : } 115 : 116 : static constexpr const char* 117 315 : getKeyExchangeName(KeyExchangeProtocol kx) 118 : { 119 315 : return kx == KeyExchangeProtocol::SDES ? "sdes" : ""; 120 : } 121 : 122 : static inline KeyExchangeProtocol 123 24 : getKeyExchangeProtocol(std::string_view name) 124 : { 125 24 : return name == "sdes"sv ? KeyExchangeProtocol::SDES : KeyExchangeProtocol::NONE; 126 : } 127 : 128 : /** 129 : * Helper function to parser header from incoming sip messages 130 : * @return Header from SIP message 131 : */ 132 : std::string fetchHeaderValue(pjsip_msg* msg, const std::string& field); 133 : 134 : pjsip_route_hdr* createRouteSet(const std::string& route, pj_pool_t* hdr_pool); 135 : 136 : std::string_view stripSipUriPrefix(std::string_view sipUri); 137 : 138 : std::string parseDisplayName(const pjsip_name_addr* sip_name_addr); 139 : std::string parseDisplayName(const pjsip_from_hdr* header); 140 : std::string parseDisplayName(const pjsip_contact_hdr* header); 141 : 142 : std::string_view getHostFromUri(std::string_view sipUri); 143 : 144 : void addContactHeader(const std::string& contact, pjsip_tx_data* tdata); 145 : void addUserAgentHeader(const std::string& userAgent, pjsip_tx_data* tdata); 146 : std::string_view getPeerUserAgent(const pjsip_rx_data* rdata); 147 : std::vector<std::string> getPeerAllowMethods(const pjsip_rx_data* rdata); 148 : void logMessageHeaders(const pjsip_hdr* hdr_list); 149 : 150 : constexpr std::string_view DEFAULT_VIDEO_STREAMID = "video_0"; 151 : constexpr std::string_view DEFAULT_AUDIO_STREAMID = "audio_0"; 152 : 153 : std::string streamId(const std::string& callId, std::string_view label); 154 : 155 : // PJSIP dialog locking in RAII way 156 : // Usage: declare local variable like this: sip_utils::PJDialogLock lock {dialog}; 157 : // The lock is kept until the local variable is deleted 158 : class PJDialogLock 159 : { 160 : public: 161 287 : explicit PJDialogLock(pjsip_dialog* dialog) 162 287 : : dialog_(dialog) 163 : { 164 287 : pjsip_dlg_inc_lock(dialog_); 165 287 : } 166 : 167 287 : ~PJDialogLock() { pjsip_dlg_dec_lock(dialog_); } 168 : 169 : private: 170 : NON_COPYABLE(PJDialogLock); 171 : pjsip_dialog* dialog_ {nullptr}; 172 : }; 173 : 174 : // Helper on PJSIP memory pool allocation from endpoint 175 : // This encapsulate the allocated memory pool inside a unique_ptr 176 : static inline std::unique_ptr<pj_pool_t, decltype(pj_pool_release)&> 177 2040 : smart_alloc_pool(pjsip_endpoint* endpt, const char* const name, pj_size_t initial, pj_size_t inc) 178 : { 179 2040 : auto pool = pjsip_endpt_create_pool(endpt, name, initial, inc); 180 2040 : if (not pool) 181 0 : throw std::bad_alloc(); 182 2040 : return std::unique_ptr<pj_pool_t, decltype(pj_pool_release)&>(pool, pj_pool_release); 183 : } 184 : 185 : void sockaddr_to_host_port(pj_pool_t* pool, pjsip_host_port* host_port, const pj_sockaddr* addr); 186 : 187 : static constexpr int POOL_TP_INIT {512}; 188 : static constexpr int POOL_TP_INC {512}; 189 : static constexpr int TRANSPORT_INFO_LENGTH {64}; 190 : 191 : } // namespace sip_utils 192 : } // namespace jami