diff --git a/src/call.cpp b/src/call.cpp index b1625d346e3bc726bb6c48c66cf91a49e1323ad5..45ee195eee3aa6bfb5a32c6410e70983c166db05 100644 --- a/src/call.cpp +++ b/src/call.cpp @@ -30,6 +30,7 @@ Call::Call(const CallID& id, Call::CallType type) , _type(type) , _connectionState(Call::Disconnected) , _callState(Call::Inactive) + , _callConfig (Call::Classic) , _peerName() , _peerNumber() { diff --git a/src/call.h b/src/call.h index d82ff7ba583c2253571532ddcd7f80561cf3aad2..836ee3daa6cf444ee65e1531d9f5ac6d8a7d89a8 100644 --- a/src/call.h +++ b/src/call.h @@ -1,5 +1,6 @@ /* - * Copyright (C) 2004-2006 Savoir-Faire Linux inc. + * Copyright (C) 2004-2009 Savoir-Faire Linux inc. + * Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> * Author: Yan Morin <yan.morin@savoirfairelinux.com> * Author : Laurielle Lea <laurielle.lea@savoirfairelinux.com> * @@ -25,6 +26,9 @@ #include "plug-in/audiorecorder/audiorecord.h" +#define IP_TO_IP_PATTERN "ip:" + +#define CallConfigNULL NULL /* * @file call.h * @brief A call is the base class for protocol-based calls @@ -35,219 +39,232 @@ typedef std::string CallID; class AudioRecord; class Call{ - public: - /** - * This determines if the call originated from the local user (Outgoing) - * or from some remote peer (Incoming). - */ - enum CallType {Incoming, Outgoing}; - - /** - * Tell where we're at with the call. The call gets Connected when we know - * from the other end what happened with out call. A call can be 'Connected' - * even if the call state is Busy, Refused, or Error. - * - * Audio should be transmitted when ConnectionState = Connected AND - * CallState = Active. - */ - enum ConnectionState {Disconnected, Trying, Progressing, Ringing, Connected}; - - /** - * The Call State. - */ - enum CallState {Inactive, Active, Hold, Busy, Refused, Error}; - - /** - * Constructor of a call - * @param id Unique identifier of the call - * @param type set definitely this call as incoming/outgoing - */ - Call(const CallID& id, Call::CallType type); - virtual ~Call(); - - /** - * Return a reference on the call id - * @return call id - */ - CallID& getCallId() {return _id; } - - /** - * Set the peer number (destination on outgoing) - * not protected by mutex (when created) - * @param number peer number - */ - void setPeerNumber(const std::string& number) { _peerNumber = number; } - - /** - * Get the peer number (destination on outgoing) - * not protected by mutex (when created) - * @return std::string The peer number - */ - const std::string& getPeerNumber() { return _peerNumber; } - - /** - * Set the peer name (caller in ingoing) - * not protected by mutex (when created) - * @param name The peer name - */ - void setPeerName(const std::string& name) { _peerName = name; } - - /** - * Get the peer name (caller in ingoing) - * not protected by mutex (when created) - * @return std::string The peer name - */ - const std::string& getPeerName() { return _peerName; } - - /** - * Tell if the call is incoming - * @return true if yes - * false otherwise - */ - bool isIncoming() { return (_type == Incoming) ? true : false; } - - /** - * Set the connection state of the call (protected by mutex) - * @param state The connection state - */ - void setConnectionState(ConnectionState state); - - /** - * Get the connection state of the call (protected by mutex) - * @return ConnectionState The connection state - */ - ConnectionState getConnectionState(); - - /** - * Set the state of the call (protected by mutex) - * @param state The call state - */ - void setState(CallState state); - - /** - * Get the call state of the call (protected by mutex) - * @return CallState The call state - */ - CallState getState(); - - /** - * Set the audio start boolean (protected by mutex) - * @param start true if we start the audio - * false otherwise - */ - void setAudioStart(bool start); - - /** - * Tell if the audio is started (protected by mutex) - * @return true if it's already started - * false otherwise - */ - bool isAudioStarted(); + public: + + /** + * This determines if the call is a direct IP-to-IP call or a classic call, made with an existing account + */ + enum CallConfiguration {Classic, IPtoIP}; + + /** + * This determines if the call originated from the local user (Outgoing) + * or from some remote peer (Incoming). + */ + enum CallType {Incoming, Outgoing}; + + /** + * Tell where we're at with the call. The call gets Connected when we know + * from the other end what happened with out call. A call can be 'Connected' + * even if the call state is Busy, Refused, or Error. + * + * Audio should be transmitted when ConnectionState = Connected AND + * CallState = Active. + */ + enum ConnectionState {Disconnected, Trying, Progressing, Ringing, Connected}; + + /** + * The Call State. + */ + enum CallState {Inactive, Active, Hold, Busy, Refused, Error}; + + /** + * Constructor of a call + * @param id Unique identifier of the call + * @param type set definitely this call as incoming/outgoing + */ + Call(const CallID& id, Call::CallType type); + virtual ~Call(); + + /** + * Return a reference on the call id + * @return call id + */ + CallID& getCallId() {return _id; } + + /** + * Set the peer number (destination on outgoing) + * not protected by mutex (when created) + * @param number peer number + */ + void setPeerNumber(const std::string& number) { _peerNumber = number; } + + /** + * Get the peer number (destination on outgoing) + * not protected by mutex (when created) + * @return std::string The peer number + */ + const std::string& getPeerNumber() { return _peerNumber; } + + /** + * Set the peer name (caller in ingoing) + * not protected by mutex (when created) + * @param name The peer name + */ + void setPeerName(const std::string& name) { _peerName = name; } + + /** + * Get the peer name (caller in ingoing) + * not protected by mutex (when created) + * @return std::string The peer name + */ + const std::string& getPeerName() { return _peerName; } + + /** + * Tell if the call is incoming + * @return true if yes + * false otherwise + */ + bool isIncoming() { return (_type == Incoming) ? true : false; } + + /** + * Set the connection state of the call (protected by mutex) + * @param state The connection state + */ + void setConnectionState(ConnectionState state); + + /** + * Get the connection state of the call (protected by mutex) + * @return ConnectionState The connection state + */ + ConnectionState getConnectionState(); + + /** + * Set the state of the call (protected by mutex) + * @param state The call state + */ + void setState(CallState state); + + /** + * Get the call state of the call (protected by mutex) + * @return CallState The call state + */ + CallState getState(); + + void setCallConfiguration (Call::CallConfiguration callConfig) { _callConfig = callConfig; } + + Call::CallConfiguration getCallConfiguration (void) { return _callConfig; } + + /** + * Set the audio start boolean (protected by mutex) + * @param start true if we start the audio + * false otherwise + */ + void setAudioStart(bool start); + + /** + * Tell if the audio is started (protected by mutex) + * @return true if it's already started + * false otherwise + */ + bool isAudioStarted(); + + /** + * Set my IP [not protected] + * @param ip The local IP address + */ + void setLocalIp(const std::string& ip) { _localIPAddress = ip; } + + /** + * Set local audio port, as seen by me [not protected] + * @param port The local audio port + */ + void setLocalAudioPort(unsigned int port) { _localAudioPort = port;} + + /** + * Set the audio port that remote will see. + * @param port The external audio port + */ + void setLocalExternAudioPort(unsigned int port) { _localExternalAudioPort = port; } /** - * Set my IP [not protected] - * @param ip The local IP address - */ - void setLocalIp(const std::string& ip) { _localIPAddress = ip; } - - /** - * Set local audio port, as seen by me [not protected] - * @param port The local audio port - */ - void setLocalAudioPort(unsigned int port) { _localAudioPort = port;} - - /** - * Set the audio port that remote will see. - * @param port The external audio port - */ - void setLocalExternAudioPort(unsigned int port) { _localExternalAudioPort = port; } - - /** - * Return the audio port seen by the remote side. - * @return unsigned int The external audio port - */ - unsigned int getLocalExternAudioPort() { return _localExternalAudioPort; } - - /** - * Return my IP [mutex protected] - * @return std::string The local IP - */ - const std::string& getLocalIp(); - - /** - * Return port used locally (for my machine) [mutex protected] - * @return unsigned int The local audio port - */ - unsigned int getLocalAudioPort(); - - /** - * @return Return the file name for this call - */ - std::string getFileName() {return _filename;} - - /** - * A recorder for this call - */ - AudioRecord recAudio; - - /** - * SetRecording - */ - void setRecording(); - - /** - * stopRecording, make sure the recording is stopped (whe transfering call) - */ - void stopRecording(); - - /** - * Return Recording state - */ - bool isRecording(); - - /** - * - */ - void initRecFileName(); - - protected: - /** Protect every attribute that can be changed by two threads */ - ost::Mutex _callMutex; - - bool _audioStarted; - - // Informations about call socket / audio - - /** My IP address */ - std::string _localIPAddress; - - /** Local audio port, as seen by me. */ - unsigned int _localAudioPort; - - /** Port assigned to my machine by the NAT, as seen by remote peer (he connects there) */ - unsigned int _localExternalAudioPort; - - - private: - - /** Unique ID of the call */ - CallID _id; - - /** Type of the call */ - CallType _type; - /** Disconnected/Progressing/Trying/Ringing/Connected */ - ConnectionState _connectionState; - /** Inactive/Active/Hold/Busy/Refused/Error */ - CallState _callState; - - /** Name of the peer */ - std::string _peerName; - - /** Number of the peer */ - std::string _peerNumber; - - /** File name for his call : time YY-MM-DD */ - std::string _filename; + * Return the audio port seen by the remote side. + * @return unsigned int The external audio port + */ + unsigned int getLocalExternAudioPort() { return _localExternalAudioPort; } + + /** + * Return my IP [mutex protected] + * @return std::string The local IP + */ + const std::string& getLocalIp(); + + /** + * Return port used locally (for my machine) [mutex protected] + * @return unsigned int The local audio port + */ + unsigned int getLocalAudioPort(); + + /** + * @return Return the file name for this call + */ + std::string getFileName() {return _filename;} + + /** + * A recorder for this call + */ + AudioRecord recAudio; + + /** + * SetRecording + */ + void setRecording(); + + /** + * stopRecording, make sure the recording is stopped (whe transfering call) + */ + void stopRecording(); + + /** + * Return Recording state + */ + bool isRecording(); + + /** + * + */ + void initRecFileName(); + + protected: + /** Protect every attribute that can be changed by two threads */ + ost::Mutex _callMutex; + + bool _audioStarted; + + // Informations about call socket / audio + + /** My IP address */ + std::string _localIPAddress; + + /** Local audio port, as seen by me. */ + unsigned int _localAudioPort; + + /** Port assigned to my machine by the NAT, as seen by remote peer (he connects there) */ + unsigned int _localExternalAudioPort; + + + private: + + /** Unique ID of the call */ + CallID _id; + + /** Type of the call */ + CallType _type; + /** Disconnected/Progressing/Trying/Ringing/Connected */ + ConnectionState _connectionState; + /** Inactive/Active/Hold/Busy/Refused/Error */ + CallState _callState; + + /** Direct IP-to-IP or classic call */ + CallConfiguration _callConfig; + + /** Name of the peer */ + std::string _peerName; + + /** Number of the peer */ + std::string _peerNumber; + + /** File name for his call : time YY-MM-DD */ + std::string _filename; }; #endif diff --git a/src/managerimpl.cpp b/src/managerimpl.cpp index 4ad23121b347059f92cc050def291349b38f7c52..356170a29ab9bbb624ffbeac70f3153d37dce500 100644 --- a/src/managerimpl.cpp +++ b/src/managerimpl.cpp @@ -80,6 +80,7 @@ ManagerImpl::ManagerImpl (void) , _hasZeroconf(false) , _callAccountMap() , _callAccountMapMutex() + , _callConfigMap() , _accountMap() { @@ -188,14 +189,36 @@ ManagerImpl::switchCall(const CallID& id ) { // Management of events' IP-phone user /////////////////////////////////////////////////////////////////////////////// /* Main Thread */ + bool ManagerImpl::outgoingCall(const std::string& accountid, const CallID& id, const std::string& to) { + std::string pattern; + Call::CallConfiguration callConfig; + SIPVoIPLink *siplink; + _debug("ManagerImpl::outgoingCall() method \n"); stopTone(false); playTone(); + /* Check what kind of call we are dealing with */ + check_call_configuration (id, to, &callConfig); + + if (callConfig == Call::IPtoIP) { + _debug ("Start IP to IP call\n"); + /* We need to retrieve the sip voiplink instance */ + siplink = SIPVoIPLink::instance(""); + if (siplink->new_ip_to_ip_call (id, to)) { + switchCall (id); + return true; + } + else { + callFailure (id); + } + return false; + } + if (!accountExists(accountid)) { _debug("! Manager Error: Outgoing Call: account doesn't exist\n"); return false; @@ -277,9 +300,9 @@ ManagerImpl::answerCall(const CallID& id) removeWaitingCall(id); switchCall(id); - std::string codecName = getCurrentCodecName(id); - _debug("ManagerImpl::hangupCall(): broadcast codec name %s \n",codecName.c_str()); - if (_dbus) _dbus->getCallManager()->currentSelectedCodec(id,codecName.c_str()); + //std::string codecName = getCurrentCodecName(id); + //_debug("ManagerImpl::hangupCall(): broadcast codec name %s \n",codecName.c_str()); + //if (_dbus) _dbus->getCallManager()->currentSelectedCodec(id,codecName.c_str()); return true; } @@ -297,19 +320,24 @@ ManagerImpl::hangupCall(const CallID& id) /* Broadcast a signal over DBus */ if (_dbus) _dbus->getCallManager()->callStateChanged(id, "HUNGUP"); - - accountid = getAccountFromCall( id ); - if (accountid == AccountNULL) { - /** @todo We should tell the GUI that the call doesn't exist, so - * it clears up. This can happen. */ - _debug("! Manager Hangup Call: Call doesn't exists\n"); - return false; + + /* Direct IP to IP call */ + if (getConfigFromCall (id) == Call::IPtoIP) { + returnValue = SIPVoIPLink::instance (AccountNULL)->hangup (id); } - returnValue = getAccountLink(accountid)->hangup(id); + /* Classic call, attached to an account */ + else { + accountid = getAccountFromCall( id ); + if (accountid == AccountNULL) { + _debug("! Manager Hangup Call: Call doesn't exists\n"); + return false; + } + + returnValue = getAccountLink(accountid)->hangup(id); + removeCallAccount(id); + } - _debug("After voip link hungup!\n"); - removeCallAccount(id); switchCall(""); if( _audiodriver->getLayerType() == PULSEAUDIO && getConfigInt( PREFERENCES , CONFIG_PA_VOLUME_CTRL ) ) { @@ -691,14 +719,15 @@ ManagerImpl::incomingMessage(const AccountID& accountId, const std::string& mess void ManagerImpl::peerAnsweredCall(const CallID& id) { - if (isCurrentCall(id)) { - stopTone(false); - } - if (_dbus) _dbus->getCallManager()->callStateChanged(id, "CURRENT"); + if (isCurrentCall(id)) { + stopTone(false); + } - std::string codecName = getCurrentCodecName(id); - _debug("ManagerImpl::hangupCall(): broadcast codec name %s \n",codecName.c_str()); - if (_dbus) _dbus->getCallManager()->currentSelectedCodec(id,codecName.c_str()); + if (_dbus) _dbus->getCallManager()->callStateChanged(id, "CURRENT"); + + //std::string codecName = getCurrentCodecName(id); + //_debug("ManagerImpl::hangupCall(): broadcast codec name %s \n",codecName.c_str()); + //if (_dbus) _dbus->getCallManager()->currentSelectedCodec(id,codecName.c_str()); } //THREAD=VoIP Call=Outgoing @@ -2371,11 +2400,15 @@ void ManagerImpl::restartPJSIP (void) VoIPLink* ManagerImpl::getAccountLink(const AccountID& accountID) { - Account* acc = getAccount(accountID); - if ( acc ) { - return acc->getVoIPLink(); - } - return 0; + if (accountID!=AccountNULL) { + Account* acc = getAccount(accountID); + if ( acc ) { + return acc->getVoIPLink(); + } + return 0; + } + else + return SIPVoIPLink::instance(""); } VoIPLink* ManagerImpl::getSIPAccountLink() @@ -2438,65 +2471,51 @@ void ManagerImpl::registerCurSIPAccounts(VoIPLink *link) } } -#ifdef TEST -/** - * Test accountMap - */ -bool ManagerImpl::testCallAccountMap() -{ - if ( getAccountFromCall(1) != AccountNULL ) { - _debug("TEST: getAccountFromCall with empty list failed\n"); - } - if ( removeCallAccount(1) != false ) { - _debug("TEST: removeCallAccount with empty list failed\n"); - } - CallID newid = getNewCallID(); - if ( associateCallToAccount(newid, "acc0") == false ) { - _debug("TEST: associateCallToAccount with new CallID empty list failed\n"); - } - if ( associateCallToAccount(newid, "acc1") == true ) { - _debug("TEST: associateCallToAccount with a known CallID failed\n"); - } - if ( getAccountFromCall( newid ) != "acc0" ) { - _debug("TEST: getAccountFromCall don't return the good account id\n"); - } - CallID secondnewid = getNewCallID(); - if ( associateCallToAccount(secondnewid, "xxxx") == true ) { - _debug("TEST: associateCallToAccount with unknown account id failed\n"); - } - if ( removeCallAccount( newid ) != true ) { - _debug("TEST: removeCallAccount don't remove the association\n"); - } +void ManagerImpl::check_call_configuration (const CallID& id, const std::string &to, Call::CallConfiguration *callConfig) { - return true; + std::string pattern; + Call::CallConfiguration config; + + /* Check if the call is an IP-to-IP call */ + /* For an IP-to-IP call, we don't need any account */ + /* Pattern looked for : ip:xxx.xxx.xxx.xxx */ + pattern = to.substr (0,3); + if (pattern==IP_TO_IP_PATTERN) { + config = Call::IPtoIP; + } else { + config = Call::Classic; + } + associateConfigToCall (id, config); + *callConfig = config; } -/** - * Test AccountMap - */ -bool ManagerImpl::testAccountMap() -{ - if (loadAccountMap() != 2) { - _debug("TEST: loadAccountMap didn't load 2 account\n"); - } - if (accountExists("acc0") == false) { - _debug("TEST: accountExists didn't find acc0\n"); - } - if (accountExists("accZ") != false) { - _debug("TEST: accountExists found an unknown account\n"); - } - if (getAccount("acc0") == 0) { - _debug("TEST: getAccount didn't find acc0\n"); - } - if (getAccount("accZ") != 0) { - _debug("TEST: getAccount found an unknown account\n"); - } - unloadAccountMap(); - if ( accountExists("acc0") == true ) { - _debug("TEST: accountExists found an account after unloadAccount\n"); - } - return true; + +bool ManagerImpl::associateConfigToCall (const CallID& callID, Call::CallConfiguration config) { + + if (getConfigFromCall(callID) == CallConfigNULL) { // nothing with the same ID + _callConfigMap[callID] = config; + _debug("Associate Call %s with config %i\n", callID.data(), config); + return true; + } else { + return false; + } } +Call::CallConfiguration ManagerImpl::getConfigFromCall(const CallID& callID) { + + CallConfigMap::iterator iter = _callConfigMap.find(callID); + if ( iter == _callConfigMap.end()) { + return (Call::CallConfiguration)CallConfigNULL; + } else { + return iter->second; + } +} + +bool ManagerImpl::removeCallConfig(const CallID& callID) { + + if ( _callConfigMap.erase(callID) ) { + return true; + } + return false; +} -#endif diff --git a/src/managerimpl.h b/src/managerimpl.h index 0765bac47619e05229a9f0fbca829f97a17611f1..dcc63e54b30684920032fc326a964c958508e901 100644 --- a/src/managerimpl.h +++ b/src/managerimpl.h @@ -58,6 +58,8 @@ typedef std::map<AccountID, Account*> AccountMap; /** Define a type for a CallID to AccountID Map inside ManagerImpl */ typedef std::map<CallID, AccountID> CallAccountMap; +typedef std::map<CallID, Call::CallConfiguration> CallConfigMap; + /** Define a type for CallID vector (waiting list, incoming not answered) */ typedef std::set<CallID> CallIDSet; @@ -989,6 +991,14 @@ class ManagerImpl { /** Mutex to lock the call account map (main thread + voiplink thread) */ ost::Mutex _callAccountMapMutex; + CallConfigMap _callConfigMap; + + bool associateConfigToCall (const CallID& callID, Call::CallConfiguration config); + + Call::CallConfiguration getConfigFromCall(const CallID& callID); + + bool removeCallConfig(const CallID& callID); + /** Associate a new CallID to a AccountID * Protected by mutex * @param callID the new CallID not in the list yet @@ -1053,7 +1063,7 @@ public: * @param accountID Account ID to get * @return VoIPLink* The voip link from the account pointer or 0 */ - VoIPLink* getAccountLink(const AccountID& accountID); + VoIPLink* getAccountLink(const AccountID& accountID=AccountNULL); VoIPLink* getSIPAccountLink (void); @@ -1076,6 +1086,11 @@ private: // Assignment Operator ManagerImpl& operator=( const ManagerImpl& rh); + /** + * Check if the call is a classic call or a direct IP-to-IP call + */ + void check_call_configuration (const CallID& id, const std::string& to, Call::CallConfiguration *callConfig); + #ifdef TEST bool testCallAccountMap(); bool testAccountMap(); diff --git a/src/sdp.h b/src/sdp.h index 9bbd0d5344e43b37594a759067e9a9f4b82f7695..a30b18807f7ee780f9257189920ad55fcda9b11b 100644 --- a/src/sdp.h +++ b/src/sdp.h @@ -180,6 +180,7 @@ class Sdp { unsigned int get_remote_audio_port() { return _remote_audio_port; } void fetch_media_transport_info_from_remote_sdp (pjmedia_sdp_session *remote_sdp); + private: /** Codec Map */ std::vector<sdpMedia*> _local_media_cap; diff --git a/src/sipvoiplink.cpp b/src/sipvoiplink.cpp index acb8d8b0e5e38efb266f586b9cff5a078b7f8ea2..b4166d99966020ca2d8032248213cd3af0ff3a81 100644 --- a/src/sipvoiplink.cpp +++ b/src/sipvoiplink.cpp @@ -950,6 +950,7 @@ SIPVoIPLink::SIPStartCall(SIPCall* call, const std::string& subject UNUSED) pj_strdup2(_pool, &to, strTo.data()); pj_strdup2(_pool, &contact, account->getContact().data()); + _debug("%s %s %s\n", from.ptr, contact.ptr, to.ptr); // create the dialog (UAC) status = pjsip_dlg_create_uac(pjsip_ua_instance(), &from, &contact, @@ -1091,7 +1092,7 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam _debug ("Get remote media information from offer\n"); call->getLocalSDP()->fetch_media_transport_info_from_remote_sdp (r_sdp); - _debug ("Update call state\n"); + _debug ("Update call state , id = %s\n", call->getCallId().c_str()); call->setConnectionState(Call::Connected); call->setState(Call::Active); @@ -1133,6 +1134,84 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam } } + bool SIPVoIPLink::new_ip_to_ip_call (const CallID& id, const std::string& to) { + + SIPCall *call; + pj_status_t status; + std::string uri_from, uri_to, hostname; + std::ostringstream uri_contact; + pj_str_t from, str_to, contact; + pjsip_dialog *dialog; + pjsip_inv_session *inv; + pjsip_tx_data *tdata; + + /* Create the call */ + call = new SIPCall(id, Call::Outgoing, _pool); + + if (call) { + + call->setCallConfiguration (Call::IPtoIP); + call->setPeerNumber(getSipTo(to, getLocalIPAddress())); + + // Generate the from URI + hostname = pj_gethostname()->ptr; + uri_from = "sip:" + hostname + "@" + getLocalIPAddress() ; + + // Generate the from URI + uri_to = "sip:" + to.substr (3, to.length()); + + // Generate the to URI + setCallAudioLocal(call, getLocalIPAddress(), useStun(), getStunServer()); + + call->initRecFileName(); + + // Building the local SDP offer + call->getLocalSDP()->set_ip_address(getLocalIP()); + call->getLocalSDP()->create_initial_offer(); + + // Generate the contact URI + uri_contact << "<" << uri_from << ":" << call->getLocalSDP()->get_local_extern_audio_port() << ">"; + + // pjsip need the from and to information in pj_str_t format + pj_strdup2(_pool, &from, uri_from.data()); + pj_strdup2(_pool, &str_to, uri_to.data()); + pj_strdup2(_pool, &contact, uri_contact.str().data()); + + // create the dialog (UAC) + _debug("Try to make a call %s - %s - %s - \n", from.ptr, contact.ptr, str_to.ptr); + status = pjsip_dlg_create_uac(pjsip_ua_instance(), &from, &contact, &str_to, NULL, &dialog); + PJ_ASSERT_RETURN(status == PJ_SUCCESS, false); + + // Create the invite session for this call + status = pjsip_inv_create_uac(dialog, call->getLocalSDP()->get_local_sdp_session(), 0, &inv); + PJ_ASSERT_RETURN(status == PJ_SUCCESS, false); + + // Associate current call in the invite session + inv->mod_data[getModId()] = call; + + status = pjsip_inv_invite(inv, &tdata); + PJ_ASSERT_RETURN(status == PJ_SUCCESS, false); + + // Associate current invite session in the call + call->setInvSession(inv); + + status = pjsip_inv_send_msg(inv, tdata); + if(status != PJ_SUCCESS) { + delete call; call = 0; + return false; + } + + call->setConnectionState(Call::Progressing); + call->setState(Call::Active); + addCall(call); + + return true; + } + else + return false; + } + + /////////////////////////////////////////////////////////////////////////////// // Private functions /////////////////////////////////////////////////////////////////////////////// @@ -1508,11 +1587,11 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam } void SIPVoIPLink::handle_reinvite (SIPCall *call) { - + // Close the previous RTP session _audiortp->closeRtpSession (); call->setAudioStart (false); - + // Create a new one with new info if (_audiortp->createNewSession (call) >= 0) { call->setAudioStart (true); @@ -1609,8 +1688,16 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam // We receive a ACK - The connection is established else if( inv->state == PJSIP_INV_STATE_CONFIRMED ){ _debug ("*************************** PJSIP_INV_STATE_CONFIRMED ***********************************\n"); - accId = Manager::instance().getAccountFromCall(call->getCallId()); - link = dynamic_cast<SIPVoIPLink *> (Manager::instance().getAccountLink(accId)); + + /* If the call is a direct IP-to-IP call */ + if (call->getCallConfiguration () == Call::IPtoIP) { + link = SIPVoIPLink::instance(""); + } + else { + accId = Manager::instance().getAccountFromCall(call->getCallId()); + link = dynamic_cast<SIPVoIPLink *> (Manager::instance().getAccountLink(accId)); + } + if (link) link->SIPCallAnswered(call, rdata); } @@ -1629,7 +1716,7 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam } break; - /* The call connection failed */ + /* The call connection failed */ case PJSIP_SC_NOT_FOUND: /* peer not found */ case PJSIP_SC_REQUEST_TIMEOUT: /* request timeout */ case PJSIP_SC_NOT_ACCEPTABLE_HERE: /* no compatible codecs */ @@ -1641,7 +1728,7 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam link->SIPCallServerFailure(call); } break; - + default: _debug ("sipvoiplink.cpp - line 1635 : Unhandled call state. This is probably a bug.\n"); break; @@ -2292,7 +2379,7 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam } void on_rx_offer( pjsip_inv_session *inv, const pjmedia_sdp_session *offer ){ - + _debug ( "********************************* REINVITE RECEIVED *******************************\n" ); #ifdef CAN_REINVITE @@ -2318,7 +2405,7 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam } -/*****************************************************************************************************************/ + /*****************************************************************************************************************/ bool setCallAudioLocal(SIPCall* call, std::string localIP, bool stun, std::string server) { diff --git a/src/sipvoiplink.h b/src/sipvoiplink.h index 3180dd5c2b6a6e1972cd62cbd4939a43c89b589a..92212c29353f982c147eccdf49356f0f6ce09de6 100644 --- a/src/sipvoiplink.h +++ b/src/sipvoiplink.h @@ -312,6 +312,7 @@ class SIPVoIPLink : public VoIPLink int inv_session_reinvite (SIPCall *call, std::string direction=""); + bool new_ip_to_ip_call (const CallID& id, const std::string& to); private: /**