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