Line data Source code
1 : /*
2 : * Copyright (C) 2004-2024 Savoir-faire Linux Inc.
3 : *
4 : * Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
5 : * Author: Alexandre Bourget <alexandre.bourget@savoirfairelinux.com>
6 : * Author: Yan Morin <yan.morin@savoirfairelinux.com>
7 : * Author: Pierre-Luc Bacon <pierre-luc.bacon@savoirfairelinux.com>
8 : *
9 : * This program is free software; you can redistribute it and/or modify
10 : * it under the terms of the GNU General Public License as published by
11 : * the Free Software Foundation; either version 3 of the License, or
12 : * (at your option) any later version.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program; if not, write to the Free Software
21 : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 : */
23 :
24 : #pragma once
25 :
26 : #ifdef HAVE_CONFIG_H
27 : #include "config.h"
28 : #endif
29 :
30 : #include "sip/sipaccountbase.h"
31 : #include "sip/siptransport.h"
32 : #include "noncopyable.h"
33 : #include "ring_types.h" // enable_if_base_of
34 : #include "sipaccount_config.h"
35 :
36 : #include <pjsip/sip_transport_tls.h>
37 : #include <pjsip/sip_types.h>
38 : #include <pjsip-ua/sip_regc.h>
39 :
40 : #include <vector>
41 : #include <map>
42 :
43 : namespace jami {
44 :
45 : typedef std::vector<pj_ssl_cipher> CipherArray;
46 :
47 : class SIPPresence;
48 : class SIPCall;
49 :
50 : /**
51 : * @file sipaccount.h
52 : * @brief A SIP Account specify SIP specific functions and object = SIPCall/SIPVoIPLink)
53 : */
54 : class SIPAccount : public SIPAccountBase
55 : {
56 : public:
57 : constexpr static auto ACCOUNT_TYPE = ACCOUNT_TYPE_SIP;
58 :
59 20 : std::shared_ptr<SIPAccount> shared()
60 : {
61 20 : return std::static_pointer_cast<SIPAccount>(shared_from_this());
62 : }
63 : std::shared_ptr<SIPAccount const> shared() const
64 : {
65 : return std::static_pointer_cast<SIPAccount const>(shared_from_this());
66 : }
67 6 : std::weak_ptr<SIPAccount> weak()
68 : {
69 6 : return std::static_pointer_cast<SIPAccount>(shared_from_this());
70 : }
71 : std::weak_ptr<SIPAccount const> weak() const
72 : {
73 : return std::static_pointer_cast<SIPAccount const>(shared_from_this());
74 : }
75 :
76 : /**
77 : * Constructor
78 : * @param accountID The account identifier
79 : */
80 : SIPAccount(const std::string& accountID, bool presenceEnabled);
81 :
82 : ~SIPAccount() noexcept;
83 :
84 838 : const SipAccountConfig& config() const
85 : {
86 838 : return *static_cast<const SipAccountConfig*>(&Account::config());
87 : }
88 :
89 24 : std::unique_ptr<AccountConfig> buildConfig() const override
90 : {
91 24 : return std::make_unique<SipAccountConfig>(getAccountID());
92 : }
93 21 : inline void editConfig(std::function<void(SipAccountConfig& conf)>&& edit)
94 : {
95 21 : Account::editConfig(
96 21 : [&](AccountConfig& conf) { edit(*static_cast<SipAccountConfig*>(&conf)); });
97 21 : }
98 :
99 26 : std::string_view getAccountType() const override { return ACCOUNT_TYPE; }
100 :
101 : pjsip_host_port getHostPortFromSTUN(pj_pool_t* pool);
102 :
103 : void updateDialogViaSentBy(pjsip_dialog* dlg);
104 :
105 : void resetAutoRegistration();
106 :
107 : /**
108 : * Update NAT address, Via and Contact header from the REGISTER response
109 : * @param param pjsip reg cbparam
110 : * @param pool
111 : * @return update status
112 : */
113 : bool checkNATAddress(pjsip_regc_cbparam* param, pj_pool_t* pool);
114 :
115 : /**
116 : * Returns true if this is the IP2IP account
117 : */
118 : bool isIP2IP() const override;
119 :
120 : /**
121 : * Retrieve volatile details such as recent registration errors
122 : * @return std::map< std::string, std::string > The account volatile details
123 : */
124 : virtual std::map<std::string, std::string> getVolatileAccountDetails() const override;
125 :
126 : /**
127 : * Return the TLS settings, mainly used to return security information to
128 : * a client application
129 : */
130 : std::map<std::string, std::string> getTlsSettings() const;
131 :
132 : /**
133 : * Actually useless, since config loading is done in init()
134 : */
135 : void loadConfig() override;
136 :
137 : /**
138 : * Initialize the SIP voip link with the account parameters and send registration
139 : */
140 : void doRegister() override;
141 :
142 : /**
143 : * Send unregistration.
144 : */
145 : void doUnregister(std::function<void(bool)> cb = std::function<void(bool)>()) override;
146 :
147 : /**
148 : * Build and send SIP registration request
149 : */
150 : void sendRegister();
151 :
152 : /**
153 : * Build and send SIP unregistration request
154 : * @param destroy_transport If true, attempt to destroy the transport.
155 : */
156 : void sendUnregister();
157 :
158 13 : const pjsip_cred_info* getCredInfo() const { return cred_.data(); }
159 :
160 : /**
161 : * Get the number of credentials defined for
162 : * this account.
163 : * @param none
164 : * @return int The number of credentials set for this account.
165 : */
166 13 : unsigned getCredentialCount() const { return config().credentials.size(); }
167 :
168 10 : bool hasCredentials() const { return not config().credentials.empty(); }
169 :
170 0 : std::vector<std::map<std::string, std::string>> getCredentials() const
171 : {
172 0 : return config().getCredentials();
173 : }
174 :
175 : virtual void setRegistrationState(RegistrationState state,
176 : int code = 0,
177 : const std::string& detail_str = {}) override;
178 :
179 : /**
180 : * A client sendings a REGISTER request MAY suggest an expiration
181 : * interval that indicates how long the client would like the
182 : * registration to be valid.
183 : *
184 : * @return the expiration value.
185 : */
186 3 : unsigned getRegistrationExpire() const
187 : {
188 3 : unsigned re = config().registrationExpire;
189 3 : return re ? re : PJSIP_REGC_EXPIRATION_NOT_SPECIFIED;
190 : }
191 :
192 : /**
193 : * Registration flag
194 : */
195 4 : bool isRegistered() const { return bRegister_; }
196 :
197 : /**
198 : * Get the registration structure that is used
199 : * for PJSIP in the registration process.
200 : * Settings are loaded from configuration file.
201 : * @return pjsip_regc* A pointer to the registration structure
202 : */
203 4 : pjsip_regc* getRegistrationInfo() { return regc_; }
204 :
205 : /**
206 : * Set the registration structure that is used
207 : * for PJSIP in the registration process;
208 : * @pram A pointer to the new registration structure
209 : * @return void
210 : */
211 3 : void setRegistrationInfo(pjsip_regc* regc)
212 : {
213 3 : if (regc_)
214 1 : destroyRegistrationInfo();
215 3 : regc_ = regc;
216 3 : }
217 :
218 : void destroyRegistrationInfo();
219 :
220 : /**
221 : * Get the port on which the transport/listener should use, or is
222 : * actually using.
223 : * @return pj_uint16 The port used for that account
224 : */
225 : uint16_t getLocalPort() const { return config().localPort; }
226 :
227 21 : void setLocalPort(uint16_t port)
228 : {
229 21 : editConfig([&](SipAccountConfig& config) { config.localPort = port; });
230 21 : }
231 :
232 : /**
233 : * @return pjsip_tls_setting structure, filled from the configuration
234 : * file, that can be used directly by PJSIP to initialize
235 : * TLS transport.
236 : */
237 0 : pjsip_tls_setting* getTlsSetting() { return &tlsSetting_; }
238 :
239 : /**
240 : * Get the local port for TLS listener.
241 : * @return pj_uint16 The port used for that account
242 : */
243 : pj_uint16_t getTlsListenerPort() const { return config().tlsListenerPort; }
244 :
245 : pj_str_t getStunServerName() const { return stunServerName_; }
246 :
247 : static const std::vector<std::string>& getSupportedTlsCiphers();
248 : static const std::vector<std::string>& getSupportedTlsProtocols();
249 :
250 : /**
251 : * @return pj_uint8_t structure, filled from the configuration
252 : * file, that can be used directly by PJSIP to initialize
253 : * an alternate UDP transport.
254 : */
255 0 : pj_uint16_t getStunPort() const override { return stunPort_; }
256 :
257 : /**
258 : * @return bool Tells if current transport for that
259 : * account is set to OTHER.
260 : */
261 23 : bool isStunEnabled() const override { return config().stunEnabled; }
262 :
263 : /**
264 : * @return pj_str_t , filled from the configuration
265 : * file, that can be used directly by PJSIP to initialize
266 : * an alternate UDP transport.
267 : */
268 : std::string getStunServer() const { return config().stunServer; }
269 :
270 : /**
271 : * @return pj_str_t "From" uri based on account information.
272 : * From RFC3261: "The To header field first and foremost specifies the desired
273 : * logical" recipient of the request, or the address-of-record of the
274 : * user or resource that is the target of this request. [...] As such, it is
275 : * very important that the From URI not contain IP addresses or the FQDN
276 : * of the host on which the UA is running, since these are not logical
277 : * names."
278 : */
279 : std::string getFromUri() const override;
280 :
281 : /**
282 : * This method adds the correct scheme, hostname and append
283 : * the ;transport= parameter at the end of the uri, in accordance with RFC3261.
284 : * It is expected that "port" is present in the internal hostname_.
285 : *
286 : * @return pj_str_t "To" uri based on @param username
287 : * @param username A string formatted as : "username"
288 : */
289 : std::string getToUri(const std::string& username) const override;
290 :
291 : /**
292 : * In the current version, "srv" uri is obtained in the preformatted
293 : * way: hostname:port. This method adds the correct scheme and append
294 : * the ;transport= parameter at the end of the uri, in accordance with RFC3261.
295 : *
296 : * @return pj_str_t "server" uri based on @param hostPort
297 : * @param hostPort A string formatted as : "hostname:port"
298 : */
299 : std::string getServerUri() const;
300 :
301 : /**
302 : * Get the contact address
303 : * @return The current contact address
304 : */
305 : dhtnet::IpAddr getContactAddress() const;
306 : /**
307 : * Get the contact header
308 : * @return The current contact header
309 : */
310 : std::string getContactHeader() const;
311 :
312 0 : std::string getServiceRoute() const { return config().serviceRoute; }
313 :
314 18 : bool hasServiceRoute() const { return not config().serviceRoute.empty(); }
315 :
316 12 : virtual bool isTlsEnabled() const override { return config().tlsEnable; }
317 :
318 0 : virtual bool getSrtpFallback() const override { return config().srtpFallback; }
319 :
320 : void setReceivedParameter(const std::string& received)
321 : {
322 : receivedParameter_ = received;
323 : via_addr_.host = sip_utils::CONST_PJ_STR(receivedParameter_);
324 : }
325 :
326 3 : const std::string& getReceivedParameter() const { return receivedParameter_; }
327 :
328 0 : pjsip_host_port* getViaAddr() { return &via_addr_; }
329 :
330 : int getRPort() const
331 : {
332 : if (rPort_ == -1)
333 : return config().localPort;
334 : else
335 : return rPort_;
336 : }
337 :
338 : void setRPort(int rPort)
339 : {
340 : rPort_ = rPort;
341 : via_addr_.port = rPort;
342 : }
343 :
344 3 : bool isRegistrationRefreshEnabled() const { return config().registrationRefreshEnabled; }
345 :
346 : void setTransport(const std::shared_ptr<SipTransport>& = nullptr);
347 :
348 0 : virtual inline std::shared_ptr<SipTransport> getTransport() { return transport_; }
349 :
350 1 : inline pjsip_transport_type_e getTransportType() const { return transportType_; }
351 :
352 : /**
353 : * Shortcut for SipTransport::getTransportSelector(account.getTransport()).
354 : */
355 : pjsip_tpselector getTransportSelector();
356 :
357 : /* Returns true if the username and/or hostname match this account */
358 : MatchRank matches(std::string_view username, std::string_view hostname) const override;
359 :
360 : /**
361 : * Presence management
362 : */
363 : SIPPresence* getPresence() const;
364 :
365 : /**
366 : * Activate the module.
367 : * @param function Publish or subscribe to enable
368 : * @param enable Flag
369 : */
370 : void enablePresence(const bool& enable);
371 : /**
372 : * Activate the publish/subscribe.
373 : * @param enable Flag
374 : */
375 : void supportPresence(int function, bool enable);
376 :
377 : /**
378 : * Create outgoing SIPCall.
379 : * @param[in] toUrl the address to call
380 : * @param[in] mediaList list of medias
381 : * @return a shared pointer on the created call.
382 : */
383 : std::shared_ptr<Call> newOutgoingCall(std::string_view toUrl,
384 : const std::vector<libjami::MediaMap>& mediaList) override;
385 :
386 : /**
387 : * Create incoming SIPCall.
388 : * @param[in] from The origin of the call
389 : * @param mediaList A list of media
390 : * @param sipTr: SIP Transport
391 : * @return A shared pointer on the created call.
392 : */
393 : std::shared_ptr<SIPCall> newIncomingCall(
394 : const std::string& from,
395 : const std::vector<libjami::MediaMap>& mediaList,
396 : const std::shared_ptr<SipTransport>& sipTr = {}) override;
397 :
398 : void onRegister(pjsip_regc_cbparam* param);
399 :
400 : virtual void sendMessage(const std::string& to,
401 : const std::string& deviceId,
402 : const std::map<std::string, std::string>& payloads,
403 : uint64_t id,
404 : bool retryOnTimeout = true,
405 : bool onlyConnected = false) override;
406 :
407 : void connectivityChanged() override;
408 :
409 : std::string getUserUri() const override;
410 :
411 : /**
412 : * Create the Ip address that the transport uses
413 : * @return IpAddr created
414 : */
415 : dhtnet::IpAddr createBindingAddress();
416 :
417 : void setActiveCodecs(const std::vector<unsigned>& list) override;
418 32 : bool isSrtpEnabled() const override
419 : {
420 32 : return config().srtpKeyExchange != KeyExchangeProtocol::NONE;
421 : }
422 :
423 : bool setPushNotificationToken(const std::string& pushDeviceToken = "") override;
424 : bool setPushNotificationConfig(const std::map<std::string, std::string>& data) override;
425 :
426 : /**
427 : * To be called by clients with relevant data when a push notification is received.
428 : */
429 : void pushNotificationReceived(const std::string& from,
430 : const std::map<std::string, std::string>& data);
431 :
432 : private:
433 : void doRegister1_();
434 : void doRegister2_();
435 :
436 : // Initialize the address to be used in contact header. Might
437 : // be updated (as the contact header)after the registration.
438 : bool initContactAddress();
439 : void updateContactHeader();
440 :
441 : void setCredentials(const std::vector<SipAccountConfig::Credentials>& creds);
442 :
443 : void setUpTransmissionData(pjsip_tx_data* tdata, long transportKeyType);
444 :
445 : NON_COPYABLE(SIPAccount);
446 :
447 : std::shared_ptr<Call> newRegisteredAccountCall(const std::string& id, const std::string& toUrl);
448 :
449 : /**
450 : * Start a SIP Call
451 : * @param call The current call
452 : * @return true if all is correct
453 : */
454 : bool SIPStartCall(std::shared_ptr<SIPCall>& call);
455 :
456 : void usePublishedAddressPortInVIA();
457 : void useUPnPAddressPortInVIA();
458 : bool fullMatch(std::string_view username, std::string_view hostname) const;
459 : bool userMatch(std::string_view username) const;
460 : bool hostnameMatch(std::string_view hostname) const;
461 : bool proxyMatch(std::string_view hostname) const;
462 :
463 : /**
464 : * Callback called by the transport layer when the registration
465 : * transport state changes.
466 : */
467 : virtual void onTransportStateChanged(pjsip_transport_state state,
468 : const pjsip_transport_state_info* info);
469 :
470 : struct
471 : {
472 : pj_bool_t active {false}; /**< Flag of reregister status. */
473 : pj_timer_entry timer {}; /**< Timer for reregistration. */
474 : unsigned attempt_cnt {0}; /**< Attempt counter. */
475 : } auto_rereg_ {}; /**< Reregister/reconnect data. */
476 :
477 : std::uniform_int_distribution<int> delay10ZeroDist_ {-10000, 10000};
478 : std::uniform_int_distribution<unsigned int> delay10PosDist_ {0, 10000};
479 :
480 : void scheduleReregistration();
481 : void autoReregTimerCb();
482 :
483 : std::shared_ptr<SipTransport> transport_ {};
484 :
485 : std::shared_ptr<TlsListener> tlsListener_ {};
486 :
487 : /**
488 : * Transport type used for this sip account. Currently supported types:
489 : * PJSIP_TRANSPORT_UNSPECIFIED
490 : * PJSIP_TRANSPORT_UDP
491 : * PJSIP_TRANSPORT_TLS
492 : */
493 : pjsip_transport_type_e transportType_ {PJSIP_TRANSPORT_UNSPECIFIED};
494 :
495 : /**
496 : * Maps a string description of the SSL method
497 : * to the corresponding enum value in pjsip_ssl_method.
498 : * @param method The string representation
499 : * @return pjsip_ssl_method The corresponding value in the enum
500 : */
501 : static pj_uint32_t tlsProtocolFromString(const std::string& method);
502 :
503 : /**
504 : * Initializes tls settings from configuration file.
505 : */
506 : void initTlsConfiguration();
507 :
508 : /**
509 : * PJSIP aborts if the string length of our cipher list is too
510 : * great, so this function forces our cipher list to fit this constraint.
511 : */
512 : void trimCiphers();
513 :
514 : /**
515 : * Initializes STUN config from the config file
516 : */
517 : void initStunConfiguration();
518 :
519 : /**
520 : * If username is not provided, as it happens for Direct ip calls,
521 : * fetch the Real Name field of the user that is currently
522 : * running this program.
523 : * @return std::string The login name under which the software is running.
524 : */
525 : static std::string getLoginName();
526 :
527 : /**
528 : * Maps require port via UPnP
529 : */
530 : bool mapPortUPnP();
531 :
532 : /**
533 : * Print contact header in certain format
534 : */
535 : static std::string printContactHeader(const std::string& username,
536 : const std::string& displayName,
537 : const std::string& address,
538 : pj_uint16_t port,
539 : bool secure,
540 : const std::string& deviceKey = {});
541 :
542 : /**
543 : * Resolved IP of hostname_ (for registration)
544 : */
545 : dhtnet::IpAddr hostIp_;
546 :
547 : /**
548 : * The pjsip client registration information
549 : */
550 : pjsip_regc* regc_ {nullptr};
551 :
552 : /**
553 : * To check if the account is registered
554 : */
555 : bool bRegister_;
556 :
557 : /**
558 : * Credential information stored for further registration.
559 : * Points to credentials_ members.
560 : */
561 : std::vector<pjsip_cred_info> cred_;
562 :
563 : /**
564 : * The TLS settings, used only if tls is chosen as a sip transport.
565 : */
566 : pjsip_tls_setting tlsSetting_;
567 :
568 : /**
569 : * Allocate a vector to be used by pjsip to store the supported ciphers on this system.
570 : */
571 : CipherArray ciphers_;
572 :
573 : /**
574 : * The STUN server name (hostname)
575 : */
576 : pj_str_t stunServerName_ {nullptr, 0};
577 :
578 : /**
579 : * The STUN server port
580 : */
581 : pj_uint16_t stunPort_ {PJ_STUN_PORT};
582 :
583 : /**
584 : * Send Request Callback
585 : */
586 : static void onComplete(void* token, pjsip_event* event);
587 :
588 : /**
589 : * Details about the registration state.
590 : * This is a protocol Code:Description pair.
591 : */
592 : std::pair<int, std::string> registrationStateDetailed_;
593 :
594 : /**
595 : * Optional: "received" parameter from VIA header
596 : */
597 : std::string receivedParameter_;
598 :
599 : /**
600 : * Optional: "rport" parameter from VIA header
601 : */
602 : int rPort_ {-1};
603 :
604 : /**
605 : * Optional: via_addr construct from received parameters
606 : */
607 : pjsip_host_port via_addr_;
608 :
609 : // This is used at runtime . Mainly by SIPAccount::usePublishedAddressPortInVIA()
610 : std::string publishedIpStr_ {};
611 :
612 : /**
613 : * Temporary storage for getUPnPIpAddress().toString()
614 : * Used only by useUPnPAddressPortInVIA().
615 : */
616 : std::string upnpIpAddr_;
617 :
618 : mutable std::mutex contactMutex_;
619 : // Contact header
620 : std::string contactHeader_;
621 : // Contact address (the address part of a SIP URI)
622 : dhtnet::IpAddr contactAddress_ {};
623 : pjsip_transport* via_tp_ {nullptr};
624 :
625 : /**
626 : * Presence data structure
627 : */
628 : SIPPresence* presence_;
629 :
630 : /**
631 : * SIP port actually used,
632 : * this holds the actual port used for SIP, which may not be the port
633 : * selected in the configuration in the case that UPnP is used and the
634 : * configured port is already used by another client
635 : */
636 : pj_uint16_t publishedPortUsed_ {sip_utils::DEFAULT_SIP_PORT};
637 : };
638 :
639 : } // namespace jami
|