Skip to content
Snippets Groups Projects
Select Git revision
  • master
  • release/202005
  • release/202001
  • release/201912
  • release/201911
  • release/201910
  • release/201908
  • release/201906
  • release/201905
  • release/201904
  • release/201903
  • release/201902
  • release/201901
  • release/201812
  • release/201811
  • release/201808
  • releases/beta1
  • packaging
  • native
  • release-0.2.x
  • 1.0.0
  • 0.2.0
  • 0.1.1
  • 0.1.0
24 results

.gitmodules

  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    sipvoiplink.h 16.69 KiB
    /*
     *  Copyright (C) 2004, 2005, 2006, 2009, 2008, 2009, 2010 Savoir-Faire Linux Inc.
     *
     *  Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
     *  Author: Yun Liu <yun.liu@savoirfairelinux.com>
     *  Author: Pierre-Luc Bacon <pierre-luc.bacon@savoirfairelinux.com>
     *  Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
     *
     *  This program is free software; you can redistribute it and/or modify
     *  it under the terms of the GNU General Public License as published by
     *  the Free Software Foundation; either version 3 of the License, or
     *  (at your option) any later version.
     *
     *  This program is distributed in the hope that it will be useful,
     *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     *  GNU General Public License for more details.
     *
     *  You should have received a copy of the GNU General Public License
     *  along with this program; if not, write to the Free Software
     *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     *
     *  Additional permission under GNU GPL version 3 section 7:
     *
     *  If you modify this program, or any covered work, by linking or
     *  combining it with the OpenSSL project's OpenSSL library (or a
     *  modified version of that library), containing parts covered by the
     *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
     *  grants you additional permission to convey the resulting work.
     *  Corresponding Source for a non-source form of such a combination
     *  shall include the source code for the parts of OpenSSL used as well
     *  as that of the covered work.
     */
    
    #ifndef SIPVOIPLINK_H
    #define SIPVOIPLINK_H
    
    #include "voiplink.h"
    #include "hooks/urlhook.h"
    #include "../im/InstantMessaging.h"
    
    //////////////////////////////
    /* PJSIP imports */
    #include <pjsip.h>
    #include <pjlib.h>
    #include <pjsip_ua.h>
    #include <pjlib-util.h>
    #include <pjnath/stun_config.h>
    ///////////////////////////////
    
    #include <map>
    #include <sstream>
    
    class EventThread;
    class SIPCall;
    
    #define RANDOM_LOCAL_PORT ((rand() % 27250) + 5250)*2
    #define RANDOM_SIP_PORT   rand() % 64000 + 1024
    
    // To set the verbosity. From 0 (min) to 6 (max)
    #define PJ_LOG_LEVEL 0
    
    #define SipTransportMap std::map<std::string, pjsip_transport*>
    
    /**
     * @file sipvoiplink.h
     * @brief Specific VoIPLink for SIP (SIP core for incoming and outgoing events).
     *          This class is based on the singleton design pattern.
     *          One SIPVoIPLink can handle multiple SIP accounts, but all the SIP accounts have all the same SIPVoIPLink
     */
    
    class SIPVoIPLink : public VoIPLink
    {
        public:
    
            /**
             * Singleton method. Enable to retrieve the unique static instance
             * @return SIPVoIPLink* A pointer on the object
             */
            static SIPVoIPLink* instance (const AccountID& id);
    
            /**
             * Destructor
             */
            ~SIPVoIPLink();
    
            /* Copy Constructor */
            SIPVoIPLink (const SIPVoIPLink& rh);
    
            /* Assignment Operator */
            SIPVoIPLink& operator= (const SIPVoIPLink& rh);
    
            /**
             * Try to initiate the pjsip engine/thread and set config
             * @return bool True if OK
             */
            bool init (void);
    
            /**
             * Shut the library and clean up
             */
            void terminate (void);
    
            /**
             * Event listener. Each event send by the call manager is received and handled from here
             */
            void getEvent (void);
    
            /**
             * Build and send SIP registration request
             * @return bool True on success
             *		  false otherwise
             */
            int sendRegister (AccountID id);
    
            /**
             * Build and send SIP unregistration request
             * @return bool True on success
             *		  false otherwise
             */
            int sendUnregister (AccountID id);
    
            /**
             * Place a new call
             * @param id  The call identifier
             * @param toUrl  The Sip address of the recipient of the call
             * @return Call* The current call
             */
            Call* newOutgoingCall (const CallID& id, const std::string& toUrl);
    
            /**
             * Answer the call
             * @param id The call identifier
             * @return int True on success
             */
            bool answer (const CallID& id);
    
            /**
             * Hang up the call
             * @param id The call identifier
             * @return bool True on success
             */
            bool hangup (const CallID& id);
    
            /**
             * Hang up the call
             * @param id The call identifier
             * @return bool True on success
             */
            bool peerHungup (const CallID& id);
    
            /**
             * Cancel the call
             * @param id The call identifier
             * @return bool True on success
             */
            bool cancel (const CallID& id);
    
            /**
             * Put the call on hold
             * @param id The call identifier
             * @return bool True on success
             */
            bool onhold (const CallID& id);
    
            /**
             * Put the call off hold
             * @param id The call identifier
             * @return bool True on success
             */
            bool offhold (const CallID& id);
    
            /**
             * Transfer the call
             * @param id The call identifier
             * @param to The recipient of the transfer
             * @return bool True on success
             */
            bool transfer (const CallID& id, const std::string& to);
    
            /** Handle the incoming refer msg, not finished yet */
            bool transferStep2 (SIPCall* call);
    
            /**
             * Refuse the call
             * @param id The call identifier
             * @return bool True on success
             */
            bool refuse (const CallID& id);
    
            /**
             * Send DTMF refering to account configuration
             * @param id The call identifier
             * @param code  The char code
             * @return bool True on success
             */
            bool carryingDTMFdigits (const CallID& id, char code);
    
            /**
             * Send Dtmf using SIP INFO message
             */
            bool dtmfSipInfo (SIPCall *call, char code);
    
            /**
             * Send Dtmf over RTP
             */
            bool dtmfOverRtp (SIPCall* call, char code);
    
            /**
             * Terminate every call not hangup | brutal | Protected by mutex
             */
            void terminateSIPCall();
    
            /**
             * Terminate only one call
             */
            void terminateOneCall (const CallID& id);
    
            /**
             * Send an outgoing call invite
             * @param call  The current call
             * @return bool True if all is correct
             */
            bool SIPOutgoingInvite (SIPCall* call);
    
            /**
             * Start a SIP Call
             * @param call  The current call
             * @param subject Undocumented
             * @return true if all is correct
             */
            bool SIPStartCall (SIPCall* call, const std::string& subject);
    
            /**
             * Tell the user that the call was answered
             * @param
             */
            void SIPCallAnswered (SIPCall *call, pjsip_rx_data *rdata);
    
            /**
             * Handling 5XX/6XX error
             * @param
             */
            void SIPCallServerFailure (SIPCall *call);
    
            /**
             * Peer close the connection
             * @param
             */
            void SIPCallClosed (SIPCall *call);
    
            /**
             * The call pointer was released
             * If the call was not cleared before, report an error
             * @param
             */
            void SIPCallReleased (SIPCall *call);
    
            /**
             * Handle a re-invite request by the remote peer.
             * A re-invite is an invite request inside a dialog.
             * When receiving a re-invite, we close the current rtp session and create a new one with the updated information
             */
            void handle_reinvite (SIPCall *call);
    
            /**
             * SIPCall accessor
             * @param id  The call identifier
             * @return SIPCall*	  A pointer on SIPCall object
             */
            SIPCall* getSIPCall (const CallID& id);
    
            /** when we init the listener, how many times we try to bind a port? */
            int _nbTryListenAddr;
    
            /** Increment the number of SIP account connected to this link */
            void incrementClients (void) {
                _clients++;
            }
    
            /** Decrement the number of SIP account connected to this link */
            void decrementClients (void);
    
            /**
            	* Set Recording
            	* @param id The call identifier
            	*/
            void setRecording (const CallID& id);
    
            /**
             * Returning state (true recording)
             * @param id The call identifier
             */
            bool isRecording (const CallID& id);
    
            /**
             * Return the codec protocol used for this call
             * @param id The call identifier
             */
            std::string getCurrentCodecName();
    
            int inv_session_reinvite (SIPCall *call, std::string direction="");
    
            bool new_ip_to_ip_call (const CallID& id, const std::string& to);
    
            std::string get_useragent_name (const AccountID& id);
    
            /**
             * List all the interfaces on the system and return
             * a vector list containing their IPV4 address.
             * @param void
             * @return std::vector<std::string> A std::string vector
             * of IPV4 address available on all of the interfaces on
             * the system.
             */
            std::vector<std::string> getAllIpInterface (void);
    
    
            /**
            * List all the interfaces on the system and return
            * a vector list containing their name (eth0, eth0:1 ...).
            * @param void
            * @return std::vector<std::string> A std::string vector
            * of interface name available on all of the interfaces on
            * the system.
            */
            std::vector<std::string> getAllIpInterfaceByName (void);
    
    
            /**
                 * List all the interfaces on the system and return
                 * a vector list containing their name (eth0, eth0:1 ...).
                 * @param void
                 * @return std::vector<std::string> A std::string vector
                 * of interface name available on all of the interfaces on
                 * the system.
                 */
            std::string getInterfaceAddrFromName (std::string ifaceName);
    
    
            /**
             * Initialize the transport selector
             * @param transport		A transport associated with an account
             * @param tp_sel		A pointer to receive the transport selector structure
             *
             * @return pj_status_t		PJ_SUCCESS if the structure was successfully initialized
             */
            pj_status_t init_transport_selector (pjsip_transport *transport, pjsip_tpselector **tp_sel);
    
            /**
             * Requests PJSIP library for local IP address, using pj_gethostbyname()
             * @param addr*                 A string to be initialized
             *
             * @return bool                 True if addr successfully initialized
             */
            bool loadSIPLocalIP (std::string *addr);
    
    
            /**
             * This function unset the transport for a given account. It tests wether the
             * associated transport is used by other accounts. If not, it shutdown the transport
             * putting its reference counter to zero. PJSIP assumes transport destruction since
             * this action can be delayed by ongoing SIP transactions.
             */
            void shutdownSipTransport (const AccountID& accountID);
    
    
            /**
             * Send a SIP message to a call identified by its callid
             *
            * @param The InstantMessaging module which contains formating, parsing and sending method
             * @param The Id of the call to send the message to
             * @param The actual message to be transmitted
             * @param The sender of this message (could be another participant of a conference)
             *
             * @return True if the message is sent without error, false elsewhere
             */
            bool sendTextMessage (sfl::InstantMessaging *module, const std::string& callID, const std::string& message, const std::string& from);
    
        private:
            /**
             * Constructor
             * @param accountID The account identifier
             */
            SIPVoIPLink (const AccountID& accountID);
    
            /* The singleton instance */
            static SIPVoIPLink* _instance;
    
            /**
             * Enable the SIP SRV resolver
             * @param endpt     The SIP endpoint
             * @param p_resv    Pointer to receive The DNS resolver instance
             *
             * @return pj_status_t  PJ_SUCCESS on success
             */
            pj_status_t enable_dns_srv_resolver (pjsip_endpoint *endpt, pj_dns_resolver ** p_resv);
    
            void busy_sleep (unsigned msec);
    
            /**
             * Initialize the PJSIP library
             * Must be called before any other calls to the SIP layer
             *
             * @return bool True on success
             */
            bool pjsip_init();
    
            /**
             * Delete link-related stuff like calls
             */
            bool pjsip_shutdown (void);
    
            pj_status_t stunServerResolve (AccountID id);
    
    
            /**
             * Function used to create a new sip transport or get an existing one from the map.
             * The SIP transport is "acquired" according to account's current settings.
             * This function should be called before registering an account
             * @param accountID An account id for which transport is to be set
             *
             * @return bool True if the account is successfully created or successfully obtained
             * from the transport map
             */
            bool acquireTransport (const AccountID& accountID);
    
    
            /**
             * Create the default UDP transport according ot Ip2Ip profile settings
             */
            bool createDefaultSipUdpTransport();
    
    
            /**
             * Create the default TLS litener using IP2IP_PROFILE settings
             */
            void createDefaultSipTlsListener();
    
    
            /**
             * Create the default TLS litener according to account settings.
             */
            void createTlsListener (const AccountID& accountID);
    
    
            /**
             * General Sip transport creation method according to the
             * transport type specified in account settings
             * @param id The account id for which a transport must
             * be created.
             */
            bool createSipTransport (AccountID id);
    
    
            /**
             * Method to store newly created UDP transport in internal transport map.
             * Transports are stored in order to retreive them in case
             * several accounts would share the same port number for UDP transprt.
             * @param key The transport's port number
             * @param transport A pointer to the UDP transport
             */
            bool addTransportToMap (std::string key, pjsip_transport* transport);
    
            /**
            * Create SIP UDP transport from account's setting
            * @param id The account id for which a transport must
            * be created.
            * @return pj_status_t PJ_SUCCESS on success
            */
            int createUdpTransport (AccountID = "");
    
            /**
             * Create a TLS transport from the default TLS listener from
             * @param id The account id for which a transport must
             * be created.
             * @return pj_status_t PJ_SUCCESS on success
             */
            pj_status_t createTlsTransport (const AccountID& id,  std::string remoteAddr);
    
            /**
             * Create a UDP transport using stun server to resove public address
             * @param id The account id for which a transport must
             * be created.
             * @return pj_status_t PJ_SUCCESS on success
             */
            pj_status_t createAlternateUdpTransport (AccountID id);
    
    
            /**
             * UDP Transports are stored in this map in order to retreive them in case
             * several accounts would share the same port number.
             */
            SipTransportMap _transportMap;
    
            /** For registration use only */
            int _regPort;
    
            /** Threading object */
            EventThread* _evThread;
            ost::Mutex _mutexSIP;
    
            /* Number of SIP accounts connected to the link */
            int _clients;
    
            /*
             * Get the correct address to use (ie advertised) from
                 * a uri. The corresponding transport that should be used
                 * with that uri will be discovered.
                 *
                 * @param uri The uri from which we want to discover the address to use
                 * @param transport The transport to use to discover the address
                 * @return pj_str_t The extern (public) address
                 */
            std::string findLocalAddressFromUri (const std::string& uri, pjsip_transport *transport);
    
            /*
             * Does the same as findLocalAddressFromUri but returns a port.
             * @param uri The uri from which we want to discover the port to use
             * @param transport The transport to use to discover the port
             * @return int The extern (public) port
             */
            int findLocalPortFromUri (const std::string& uri, pjsip_transport *transport);
    
    
            friend class SIPTest;
    };
    
    
    #endif