blob: 0f02255502d7e54d4d290f436e74c2fb023707b6 [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 */
Adrien Béraud612b55b2023-05-29 10:42:04 -040017#pragma once
18
19#include "ip_utils.h"
20
21#include <utility>
22#include <string>
23#include <vector>
24#include <cstring> // strcmp
Adrien Béraude48fd6d2023-07-18 16:29:35 -040025#include <memory>
Adrien Béraud612b55b2023-05-29 10:42:04 -040026
27#include <pjsip/sip_msg.h>
28#include <pjlib.h>
29#include <pj/pool.h>
30#include <pjsip/sip_endpoint.h>
31#include <pjsip/sip_dialog.h>
32
Adrien Béraud1ae60aa2023-07-07 09:55:09 -040033namespace dhtnet {
Adrien Béraud612b55b2023-05-29 10:42:04 -040034namespace sip_utils {
35
36using namespace std::literals;
37
38// SIP methods. Only list methods that need to be explicitly
39// handled
40
41namespace SIP_METHODS {
42constexpr std::string_view MESSAGE = "MESSAGE"sv;
43constexpr std::string_view INFO = "INFO"sv;
44constexpr std::string_view OPTIONS = "OPTIONS"sv;
45constexpr std::string_view PUBLISH = "PUBLISH"sv;
46constexpr std::string_view REFER = "REFER"sv;
47constexpr std::string_view NOTIFY = "NOTIFY"sv;
48} // namespace SIP_METHODS
49
50static constexpr int DEFAULT_SIP_PORT {5060};
51static constexpr int DEFAULT_SIP_TLS_PORT {5061};
52static constexpr int DEFAULT_AUTO_SELECT_PORT {0};
53
54/// PjsipErrorCategory - a PJSIP error category for std::error_code
55class PjsipErrorCategory final : public std::error_category
56{
57public:
58 const char* name() const noexcept override { return "pjsip"; }
59 std::string message(int condition) const override;
60};
61
62/// PJSIP related exception
63/// Based on std::system_error with code() returning std::error_code with PjsipErrorCategory category
64class PjsipFailure : public std::system_error
65{
66private:
67 static constexpr const char* what_ = "PJSIP call failed";
68
69public:
70 PjsipFailure()
71 : std::system_error(std::error_code(PJ_EUNKNOWN, PjsipErrorCategory()), what_)
72 {}
73
74 explicit PjsipFailure(pj_status_t status)
75 : std::system_error(std::error_code(status, PjsipErrorCategory()), what_)
76 {}
77};
78
79
80/**
81 * Helper function to parser header from incoming sip messages
82 * @return Header from SIP message
83 */
84/*std::string fetchHeaderValue(pjsip_msg* msg, const std::string& field);
85
86pjsip_route_hdr* createRouteSet(const std::string& route, pj_pool_t* hdr_pool);
87
88std::string_view stripSipUriPrefix(std::string_view sipUri);
89
90std::string parseDisplayName(const pjsip_name_addr* sip_name_addr);
91std::string parseDisplayName(const pjsip_from_hdr* header);
92std::string parseDisplayName(const pjsip_contact_hdr* header);
93
94std::string_view getHostFromUri(std::string_view sipUri);
95
96void addContactHeader(const std::string& contact, pjsip_tx_data* tdata);
97void addUserAgentHeader(const std::string& userAgent, pjsip_tx_data* tdata);
98std::string_view getPeerUserAgent(const pjsip_rx_data* rdata);
99std::vector<std::string> getPeerAllowMethods(const pjsip_rx_data* rdata);
100void logMessageHeaders(const pjsip_hdr* hdr_list);*/
101
102std::string_view sip_strerror(pj_status_t code);
103
104// Helper function that return a constant pj_str_t from an array of any types
105// that may be statically casted into char pointer.
106// Per convention, the input array is supposed to be null terminated.
107template<typename T, std::size_t N>
108constexpr const pj_str_t
109CONST_PJ_STR(T (&a)[N]) noexcept
110{
111 return {const_cast<char*>(a), N - 1};
112}
113
114inline const pj_str_t
115CONST_PJ_STR(const std::string& str) noexcept
116{
117 return {const_cast<char*>(str.c_str()), (pj_ssize_t) str.size()};
118}
119
120inline constexpr pj_str_t
121CONST_PJ_STR(const std::string_view& str) noexcept
122{
123 return {const_cast<char*>(str.data()), (pj_ssize_t) str.size()};
124}
125
126inline constexpr std::string_view
127as_view(const pj_str_t& str) noexcept
128{
129 return {str.ptr, (size_t) str.slen};
130}
131
132// PJSIP dialog locking in RAII way
133// Usage: declare local variable like this: sip_utils::PJDialogLock lock {dialog};
134// The lock is kept until the local variable is deleted
135class PJDialogLock
136{
137public:
138 explicit PJDialogLock(pjsip_dialog* dialog)
139 : dialog_(dialog)
140 {
141 pjsip_dlg_inc_lock(dialog_);
142 }
143
144 ~PJDialogLock() { pjsip_dlg_dec_lock(dialog_); }
145
146private:
147 PJDialogLock(const PJDialogLock&) = delete;
148 PJDialogLock& operator=(const PJDialogLock&) = delete;
149 pjsip_dialog* dialog_ {nullptr};
150};
151
152// Helper on PJSIP memory pool allocation from endpoint
153// This encapsulate the allocated memory pool inside a unique_ptr
154static inline std::unique_ptr<pj_pool_t, decltype(pj_pool_release)&>
155smart_alloc_pool(pjsip_endpoint* endpt, const char* const name, pj_size_t initial, pj_size_t inc)
156{
157 auto pool = pjsip_endpt_create_pool(endpt, name, initial, inc);
158 if (not pool)
159 throw std::bad_alloc();
160 return std::unique_ptr<pj_pool_t, decltype(pj_pool_release)&>(pool, pj_pool_release);
161}
162
163void sockaddr_to_host_port(pj_pool_t* pool, pjsip_host_port* host_port, const pj_sockaddr* addr);
164
165static constexpr int POOL_TP_INIT {512};
166static constexpr int POOL_TP_INC {512};
167static constexpr int TRANSPORT_INFO_LENGTH {64};
168
169} // namespace sip_utils
Sébastien Blin464bdff2023-07-19 08:02:53 -0400170} // namespace dhtnet