LCOV - code coverage report
Current view: top level - src/sip - sipaccount.h (source / functions) Coverage Total Hit
Test: jami-coverage-filtered.info Lines: 84.2 % 38 32
Test Date: 2026-07-06 08:25:38 Functions: 79.3 % 29 23

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

Generated by: LCOV version 2.0-1