From 51011b6543dc1c6bebeae36c7804206c8451359a Mon Sep 17 00:00:00 2001 From: pierre-luc <pierre-luc.bacon@savoirfairelinux.com> Date: Tue, 18 Aug 2009 19:40:29 -0400 Subject: [PATCH] [#812] Towards integrating multiple tls listeners at the same time. This commit adds the ability to create the right sip uri depending on the transport selected. This is a BACKUP kind of commit. The code is compilable, but yet UNTESTED ! --- sflphone-common/src/global.h | 2 +- sflphone-common/src/sip/sipaccount.cpp | 175 ++++++++++-- sflphone-common/src/sip/sipaccount.h | 69 ++++- sflphone-common/src/sip/sipvoiplink.cpp | 351 +++++++++++++++--------- sflphone-common/src/sip/sipvoiplink.h | 41 ++- 5 files changed, 440 insertions(+), 198 deletions(-) diff --git a/sflphone-common/src/global.h b/sflphone-common/src/global.h index 875fc47a06..a660b9a8a5 100644 --- a/sflphone-common/src/global.h +++ b/sflphone-common/src/global.h @@ -136,7 +136,7 @@ static const SOUND_FORMAT INT32 = 0x8; #define UNUSED __attribute__((__unused__)) -#define DEFAULT_SIP_PORT 5060 +#define DEFAULT_SIP_PORT "5060" #define DEFAULT_SIP_TLS_PORT "5061" #define HOOK_DEFAULT_SIP_FIELD "X-sflphone-url" diff --git a/sflphone-common/src/sip/sipaccount.cpp b/sflphone-common/src/sip/sipaccount.cpp index 8e8a9b9300..04d647c9c8 100644 --- a/sflphone-common/src/sip/sipaccount.cpp +++ b/sflphone-common/src/sip/sipaccount.cpp @@ -28,11 +28,12 @@ SIPAccount::SIPAccount (const AccountID& accountID) , _cred (NULL) , _regc() , _bRegister (false) - , _contact ("") , _resolveOnce (false) + , _contact ("") + , _displayName ("") , _tlsSetting (NULL) - , _tlsEnabled (false) - , _tlsPort (0) + , _port(DFT_SIP_PORT) + , _transportType(PJSIP_TRANSPORT_UNSPECIFIED) { /* SIPVoIPlink is used as a singleton, because we want to have only one link for all the SIP accounts created */ /* So instead of creating a new instance, we just fetch the static instance, or create one if it is not yet */ @@ -55,23 +56,8 @@ SIPAccount::~SIPAccount() free(_tlsSetting); } -int SIPAccount::registerVoIPLink() +int SIPAccount::initCredential(void) { - int status; - - /* Retrieve the account information */ - /* Stuff needed for SIP registration */ - - if (Manager::instance().getConfigString (_accountID, HOSTNAME).length() >= PJ_MAX_HOSTNAME) { - return !SUCCESS; - } - - setHostname (Manager::instance().getConfigString (_accountID, HOSTNAME)); - setUsername (Manager::instance().getConfigString (_accountID, USERNAME)); - setPassword (Manager::instance().getConfigString (_accountID, PASSWORD)); - _authenticationUsername = Manager::instance().getConfigString (_accountID, AUTHENTICATION_USERNAME); - _realm = Manager::instance().getConfigString (_accountID, REALM); - int credentialCount = 0; credentialCount = Manager::instance().getConfigInt (_accountID, CONFIG_CREDENTIAL_NUMBER); credentialCount += 1; @@ -128,6 +114,22 @@ int SIPAccount::registerVoIPLink() _credentialCount = credentialCount; _cred = cred_info; + return SUCCESS; +} + + +int SIPAccount::registerVoIPLink() +{ + if (Manager::instance().getConfigString (_accountID, HOSTNAME).length() >= PJ_MAX_HOSTNAME) { + return !SUCCESS; + } + + // Init general account settings + setHostname (Manager::instance().getConfigString (_accountID, HOSTNAME)); + setUsername (Manager::instance().getConfigString (_accountID, USERNAME)); + setPassword (Manager::instance().getConfigString (_accountID, PASSWORD)); + _authenticationUsername = Manager::instance().getConfigString (_accountID, AUTHENTICATION_USERNAME); + _realm = Manager::instance().getConfigString (_accountID, REALM); _resolveOnce = Manager::instance().getConfigString (_accountID, CONFIG_ACCOUNT_RESOLVE_ONCE) == "1" ? true : false; if (Manager::instance().getConfigString (_accountID, CONFIG_ACCOUNT_REGISTRATION_EXPIRE).empty()) { @@ -136,15 +138,22 @@ int SIPAccount::registerVoIPLink() _registrationExpire = Manager::instance().getConfigString (_accountID, CONFIG_ACCOUNT_REGISTRATION_EXPIRE); } - /* Init TLS settings if the user wants to use TLS */ - _tlsEnabled = Manager::instance().getConfigBool(_accountID, TLS_ENABLE); - if (_tlsEnabled) { - _tlsPort = (pj_uint16_t) Manager::instance().getConfigInt(_accountID, TLS_PORT); + _port = Manager::instance().getSipPort(); + _transportType = PJSIP_TRANSPORT_UDP; + + // Init set of additional credentials, if supplied by the user + initCredential(); + + // Init TLS settings if the user wants to use TLS + bool tlsEnabled = Manager::instance().getConfigBool(_accountID, TLS_ENABLE); + if (tlsEnabled) { + _port = (pj_uint16_t) Manager::instance().getConfigInt(_accountID, TLS_PORT); + _transportType = PJSIP_TRANSPORT_TLS; initTlsConfiguration(); } - /* Start registration */ - status = _link->sendRegister (_accountID); + // Start registration + int status = _link->sendRegister (_accountID); ASSERT (status , SUCCESS); @@ -243,3 +252,119 @@ bool SIPAccount::hostnameMatch (const std::string& hostname) return (hostname == getHostname()); } +pj_str_t SIPAccount::getFromUri(void) +{ + char uri[PJSIP_MAX_URL_SIZE]; + const char * beginquote, * endquote; + + std::string scheme; + std::string transport; + + // if IPV6, should be set to [] + beginquote = endquote = ""; + + // UDP does not require the transport specification + if (_transportType != PJSIP_TRANSPORT_UDP) { + scheme = "sips"; + transport = ";transport=" + std::string(pjsip_transport_get_type_name(_transportType)); + } else { + scheme = "sip"; + } + + pj_ansi_snprintf(uri, PJSIP_MAX_URL_SIZE, + "<%s:%s%s%s%s:%s%s>", + scheme.c_str(), + beginquote, + _username.c_str(), + _hostname.c_str(), + endquote, + _port.c_str(), + transport.c_str()); + + return pj_str(uri); +} + +pj_str_t SIPAccount::getToUri(const std::string& username) +{ + char uri[PJSIP_MAX_URL_SIZE]; + + std::string scheme; + std::string transport; + + // UDP does not require the transport specification + if (_transportType != PJSIP_TRANSPORT_UDP) { + scheme = "sips"; + transport = ";transport=" + std::string(pjsip_transport_get_type_name(_transportType)); + } else { + scheme = "sip"; + } + + pj_ansi_snprintf(uri, PJSIP_MAX_URL_SIZE, + "<%s:%s@%s%s>", + scheme.c_str(), + username.c_str(), + _hostname.c_str(), + transport.c_str()); + + return pj_str(uri); +} + +pj_str_t SIPAccount::getServerUri(void) +{ + char uri[PJSIP_MAX_URL_SIZE]; + + std::string scheme; + std::string transport; + + // UDP does not require the transport specification + if (_transportType != PJSIP_TRANSPORT_UDP) { + scheme = "sips"; + transport = ";transport=" + std::string(pjsip_transport_get_type_name(_transportType)); + } else { + scheme = "sip"; + } + + pj_ansi_snprintf(uri, PJSIP_MAX_URL_SIZE, + "<%s:%s%s>", + scheme.c_str(), + _hostname.c_str(), + transport.c_str()); + + return pj_str(uri); +} + +pj_str_t SIPAccount::getContactHeader(const std::string& address, const std::string& port) +{ + char contact[PJSIP_MAX_URL_SIZE]; + const char * beginquote, * endquote; + + std::string scheme; + std::string transport; + + // if IPV6, should be set to [] + beginquote = endquote = ""; + + if (_transportType != PJSIP_TRANSPORT_UDP) { + scheme = "sips"; + transport = ";transport=" + std::string(pjsip_transport_get_type_name(_transportType)); + } else { + scheme = "sip"; + } + + pj_ansi_snprintf(contact, PJSIP_MAX_URL_SIZE, + "%s%s<%s:%s%s%s%s%s:%d%s>", + _displayName.c_str(), + (_displayName.empty() ? "" : " "), + scheme.c_str(), + _username.c_str(), + (_username.empty() ? "":"@"), + beginquote, + address.c_str(), + endquote, + atoi(port.c_str()), + transport.c_str()); + + return pj_str(contact); +} + + diff --git a/sflphone-common/src/sip/sipaccount.h b/sflphone-common/src/sip/sipaccount.h index 4cee733797..c493b0ee3f 100644 --- a/sflphone-common/src/sip/sipaccount.h +++ b/sflphone-common/src/sip/sipaccount.h @@ -26,6 +26,7 @@ #include "account.h" #include "sipvoiplink.h" #include "pjsip/sip_transport_tls.h" +#include "pjsip/sip_types.h" class SIPVoIPLink; @@ -96,8 +97,46 @@ class SIPAccount : public Account void setRegister(bool result) {_bRegister = result;} inline pjsip_tls_setting * getTlsSetting(void) { return _tlsSetting; } - inline bool isTlsEnabled(void) { return _tlsEnabled; } - inline pj_uint16_t getTlsPort(void) { return _tlsPort; } + inline bool isTlsEnabled(void) { return (_transportType == PJSIP_TRANSPORT_TLS) ? true: false; } + inline pj_uint16_t getPort(void) { return (pj_uint16_t) atoi(_port.c_str()); } + + /* + * @return pj_str_t "From" uri based on account information. + * From RFC3261: "The To header field first and foremost specifies the desired + * logical" recipient of the request, or the address-of-record of the + * user or resource that is the target of this request. [...] As such, it is + * very important that the From URI not contain IP addresses or the FQDN + * of the host on which the UA is running, since these are not logical + * names." + */ + pj_str_t getFromUri(void); + + /* + * This method adds the correct scheme, hostname and append + * the ;transport= parameter at the end of the uri, in accordance with RFC3261. + * It is expected that "port" is present in the internal _hostname. + * + * @return pj_str_t "To" uri based on @param username + * @param username A string formatted as : "username" + */ + pj_str_t getToUri(const std::string& username); + + /* + * In the current version of SFLPhone, "srv" uri is obtained in the preformated + * way: hostname:port. This method adds the correct scheme and append + * the ;transport= parameter at the end of the uri, in accordance with RFC3261. + * + * @return pj_str_t "server" uri based on @param hostPort + * @param hostPort A string formatted as : "hostname:port" + */ + pj_str_t getServerUri(void); + + /* + * @param port Optional port. Otherwise set to the port defined for that account. + * @param hostname Optional local address. Otherwise set to the hostname defined for that account. + * @return pj_str_t The contact header based on account information + */ + pj_str_t getContactHeader(const std::string& address, const std::string& port); private: /* Maps a string description of the SSL method @@ -112,6 +151,11 @@ class SIPAccount : public Account * */ void initTlsConfiguration(void); + + /* + * Initializes set of additional credentials, if supplied by the user. + */ + int initCredential(void); /** * Credential information @@ -123,19 +167,16 @@ class SIPAccount : public Account */ pjsip_regc *_regc; - /** - * The TLS settings, if tls is chosen as - * a sip transport. - */ - pjsip_tls_setting * _tlsSetting; - - /** - * A flag telling if tls is enabled or not. - */ - bool _tlsEnabled; + std::string _port; - pj_uint16_t _tlsPort; + pjsip_transport_type_e _transportType; + /** + * The TLS settings, if tls is chosen as + * a sip transport. + */ + pjsip_tls_setting * _tlsSetting; + /** * To check if the account is registered */ @@ -148,6 +189,8 @@ class SIPAccount : public Account */ std::string _contact; + std::string _displayName; + std::string _registrationExpire; std::string _authenticationUsername; diff --git a/sflphone-common/src/sip/sipvoiplink.cpp b/sflphone-common/src/sip/sipvoiplink.cpp index dd68a38c20..a7ab83c9f6 100644 --- a/sflphone-common/src/sip/sipvoiplink.cpp +++ b/sflphone-common/src/sip/sipvoiplink.cpp @@ -31,6 +31,7 @@ #include "pjsip/sip_endpoint.h" #include "pjsip/sip_transport_tls.h" +#include "pjsip/sip_uri.h" #include <netinet/in.h> #include <arpa/nameser.h> @@ -212,7 +213,7 @@ SIPVoIPLink::SIPVoIPLink (const AccountID& accountID) , _localExternAddress ("") , _localExternPort (0) , _audiortp (new sfl::AudioRtpFactory()) - ,_regPort (DEFAULT_SIP_PORT) + ,_regPort (atoi(DEFAULT_SIP_PORT)) , _useStun (false) , _clients (0) { @@ -368,10 +369,9 @@ SIPVoIPLink::getEvent() int SIPVoIPLink::sendRegister (AccountID id) { int expire_value; - char contactTmp[256]; - + pj_status_t status; - pj_str_t svr, aor, contact, useragent; + pj_str_t useragent; pjsip_tx_data *tdata; pjsip_host_info destination; @@ -423,14 +423,9 @@ int SIPVoIPLink::sendRegister (AccountID id) } } - hostname = account->getHostname(); - - username = account->getUsername(); - password = account->getPassword(); - _mutexSIP.enterMutex(); - /* Get the client registration information for this particular account */ + // Get the client registration information for this particular account regc = account->getRegistrationInfo(); /* TODO If the registration already exists, delete it */ /*if(regc) { @@ -441,7 +436,7 @@ int SIPVoIPLink::sendRegister (AccountID id) account->setRegister (true); - /* Set the expire value of the message from the config file */ + // Set the expire value of the message from the config file istringstream stream (account->getRegistrationExpire()); stream >> expire_value; @@ -449,7 +444,7 @@ int SIPVoIPLink::sendRegister (AccountID id) expire_value = PJSIP_REGC_EXPIRATION_NOT_SPECIFIED; } - /* Update the state of the voip link */ + // Update the state of the voip link account->setRegistrationState (Trying); if (!validStunServer) { @@ -459,7 +454,7 @@ int SIPVoIPLink::sendRegister (AccountID id) return false; } - /* Create the registration according to the account ID */ + // Create the registration according to the account ID status = pjsip_regc_create (_endpt, (void*) account, ®c_cb, ®c); if (status != PJ_SUCCESS) { @@ -468,23 +463,35 @@ int SIPVoIPLink::sendRegister (AccountID id) return false; } - tmp = "sip:" + hostname; - - pj_strdup2 (_pool, &svr, tmp.data()); - - // tmp = "<sip:" + username + "@" + hostname + ";transport=tls>"; - tmp = "<sip:" + username + "@" + hostname + ">"; - pj_strdup2 (_pool, &aor, tmp.data()); - - _debug ("<sip:%s@%s:%d>\n", username.data(), _localExternAddress.data(), _localExternPort); - sprintf (contactTmp, "<sip:%s@%s:%d>", username.data(), _localExternAddress.data(), _localExternPort); - pj_strdup2 (_pool, &contact, contactTmp); - account->setContact (contactTmp); - - status = pjsip_regc_init (regc, &svr, &aor, &aor, 1, &contact, expire_value); //timeout); + // Creates URI + pj_str_t fromUri; + pj_str_t contactUri; + pj_str_t srvUri; + + fromUri = account->getFromUri(); + srvUri = account->getServerUri(); + + pj_str_t address = findLocalAddressFromUri(&srvUri); + int port = findLocalPortFromUri(&srvUri); + std::stringstream ss; + std::string portStr; + ss << port; + ss >> portStr; + contactUri = account->getContactHeader(std::string(address.ptr, address.slen), portStr); + + _debug("sendRegister: fromUri: %.*s serverUri: %.*s contactUri: %.*s\n", + (int)fromUri.slen, + fromUri.ptr, + (int)srvUri.slen, + srvUri.ptr, + (int)contactUri.slen, + contactUri.ptr); + + // Initializes registration + status = pjsip_regc_init (regc, &srvUri, &fromUri, &fromUri, 1, &contactUri, expire_value); if (status != PJ_SUCCESS) { - _debug ("UserAgent: Unable to initialize regc. %d\n", status); //, regc->str_srv_url.ptr); + _debug ("UserAgent: Unable to initialize regc. %d\n", status); _mutexSIP.leaveMutex(); return false; } @@ -513,6 +520,7 @@ int SIPVoIPLink::sendRegister (AccountID id) return false; } + // Send registration request status = pjsip_regc_send (regc, tdata); if (status != PJ_SUCCESS) { @@ -572,15 +580,14 @@ SIPVoIPLink::sendUnregister (AccountID id) Call* SIPVoIPLink::newOutgoingCall (const CallID& id, const std::string& toUrl) { - Account* account; + SIPAccount * account = NULL; pj_status_t status; SIPCall* call = new SIPCall (id, Call::Outgoing, _pool); if (call) { account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount (Manager::instance().getAccountFromCall (id))); - - if (!account) { + if (account == NULL) { _debug ("Error retrieving the account to the make the call with\n"); call->setConnectionState (Call::Disconnected); call->setState (Call::Error); @@ -589,7 +596,8 @@ SIPVoIPLink::newOutgoingCall (const CallID& id, const std::string& toUrl) return call; } - call->setPeerNumber (getSipTo (toUrl, account->getHostname())); + pj_str_t toUri = account->getToUri(toUrl); + call->setPeerNumber(std::string(toUri.ptr, toUri.slen)); setCallAudioLocal (call, getLocalIPAddress(), useStun(), getStunServer()); @@ -918,33 +926,28 @@ SIPVoIPLink::transfer (const CallID& id, const std::string& to) pj_status_t status; pj_str_t dest; AccountID account_id; - Account* account; + SIPAccount * account = NULL; call = getSIPCall (id); call->stopRecording(); account_id = Manager::instance().getAccountFromCall (id); account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount (account_id)); + if (account == NULL) { + _debug("SIPVoIPLink::transfer account is null. Returning.\n"); + return false; + } + if (call==0) { _debug ("! SIP Failure: Call doesn't exist\n"); return false; } - tmp_to = SIPToHeader (to); - - if (account) { - if (tmp_to.find ("@") == std::string::npos) { - tmp_to = tmp_to + "@" + account->getHostname(); - } + if (to.find ("@") == std::string::npos) { + dest = account->getToUri(to); } - else { - - } - - _debug ("In transfer, tmp_to is %s\n", tmp_to.data()); - - pj_strdup2 (_pool, &dest, tmp_to.data()); + _debug ("Transfering to %.*s\n", (int)dest.slen, dest.ptr); /* Create xfer client subscription. */ pj_bzero (&xfer_cb, sizeof (xfer_cb)); @@ -1153,42 +1156,51 @@ SIPVoIPLink::SIPOutgoingInvite (SIPCall* call) bool SIPVoIPLink::SIPStartCall (SIPCall* call, const std::string& subject UNUSED) { - std::string strTo, strFrom; pj_status_t status; + pjsip_inv_session *inv; pjsip_dialog *dialog; pjsip_tx_data *tdata; - pj_str_t from, to, contact; + AccountID id; - SIPAccount *account; - pjsip_inv_session *inv; - if (!call) + if (call == NULL) return false; id = Manager::instance().getAccountFromCall (call->getCallId()); // Get the basic information about the callee account + SIPAccount * account = NULL; account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount (id)); - - strTo = getSipTo (call->getPeerNumber(), account->getHostname()); - - // Generate the from URI - strFrom = "sip:" + account->getUsername() + "@" + account->getHostname(); - - _debug ("Placing new call: \nTo: %s\nFrom: %s\n", strTo.data(), strFrom.c_str()); - - // pjsip need the from and to information in pj_str_t format - pj_strdup2 (_pool, &from, strFrom.data()); - - 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, - &to, + if (account == NULL) { + _debug("Account is null in SIPStartCall\n"); + return false; + } + + // Creates URI + pj_str_t fromUri, toUri, contactUri; + fromUri = account->getFromUri(); + toUri = account->getToUri(call->getPeerNumber()); // expecting number@hostname + + pj_str_t address = findLocalAddressFromUri(&toUri); + int port = findLocalPortFromUri(&toUri); + std::stringstream ss; + std::string portStr; + ss << port; + ss >> portStr; + contactUri = account->getContactHeader(std::string(address.ptr, address.slen), portStr); + + _debug("SIPStartCall: fromUri: %.*s toUri: %.*s contactUri: %.*s\n", + (int)fromUri.slen, + fromUri.ptr, + (int)toUri.slen, + toUri.ptr, + (int)contactUri.slen, + contactUri.ptr); + + // Create the dialog (UAC) + status = pjsip_dlg_create_uac (pjsip_ua_instance(), &fromUri, + &contactUri, + &toUri, NULL, &dialog); @@ -1224,36 +1236,6 @@ SIPVoIPLink::SIPStartCall (SIPCall* call, const std::string& subject UNUSED) return true; } -std::string SIPVoIPLink::getSipTo (const std::string& to_url, std::string hostname) -{ - // Form the From header field basis on configuration panel - //bool isRegistered = (_eXosipRegID == EXOSIP_ERROR_STD) ? false : true; - - // add a @host if we are registered and there is no one inside the url - if (to_url.find ("@") == std::string::npos) { // && isRegistered) { - if (!hostname.empty()) { - return SIPToHeader (to_url + "@" + hostname); - } - } - - return SIPToHeader (to_url); -} - -std::string SIPVoIPLink::SIPToHeader (const std::string& to) -{ - if (to.find ("sip:") == std::string::npos) { - return ("sip:" + to); - } else { - return to; - } -} - -bool -SIPVoIPLink::SIPCheckUrl (const std::string& url UNUSED) -{ - return true; -} - void SIPVoIPLink::SIPCallServerFailure (SIPCall *call) { @@ -1361,9 +1343,6 @@ 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; @@ -1374,20 +1353,18 @@ bool SIPVoIPLink::new_ip_to_ip_call (const CallID& id, const std::string& to) 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 (4, to.length()); - - _debug ("get local ip address: %s \n", getLocalIPAddress().c_str()); - // Generate the to URI setCallAudioLocal (call, getLocalIPAddress(), useStun(), getStunServer()); - call->initRecFileName(); + + SIPAccount * account = NULL; + account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount(id)); + if (account == NULL) { + _debug("Account is null. Returning"); + return !PJ_SUCCESS; + } + + pj_str_t toUri = account->getToUri(to); + call->setPeerNumber(std::string(toUri.ptr, toUri.slen)); // Building the local SDP offer call->getLocalSDP()->set_ip_address (getLocalIP()); @@ -1398,20 +1375,29 @@ bool SIPVoIPLink::new_ip_to_ip_call (const CallID& id, const std::string& to) } catch (...) { _debug ("! SIP Failure: Unable to create RTP Session in SIPVoIPLink::new_ip_to_ip_call (%s:%d)\n", __FILE__, __LINE__); } - - // Generate the contact URI - // uri_contact << "<" << uri_from << ":" << call->getLocalSDP()->get_local_extern_audio_port() << ">"; - uri_contact << "<" << uri_from << ":" << _localExternPort << ">"; - - // 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()); + + pj_str_t fromUri, contactUri; + fromUri = account->getFromUri(); + + pj_str_t address = findLocalAddressFromUri(&toUri); + int port = findLocalPortFromUri(&toUri); + std::stringstream ss; + std::string portStr; + ss << port; + ss >> portStr; + contactUri = account->getContactHeader(std::string(address.ptr, address.slen), portStr); + + _debug("New_ip_to_ip_call: fromUri: %.*s toUri: %.*s contactUri: %.*s\n", + (int)fromUri.slen, + fromUri.ptr, + (int)toUri.slen, + toUri.ptr, + (int)contactUri.slen, + contactUri.ptr); + // create the dialog (UAC) - status = pjsip_dlg_create_uac (pjsip_ua_instance(), &from, &contact, &str_to, NULL, &dialog); + status = pjsip_dlg_create_uac (pjsip_ua_instance(), &fromUri, &contactUri, &toUri, NULL, &dialog); PJ_ASSERT_RETURN (status == PJ_SUCCESS, false); @@ -1794,6 +1780,99 @@ int SIPVoIPLink::createUDPServer (void) return PJ_SUCCESS; } +pj_str_t SIPVoIPLink::findLocalAddressFromUri(const pj_str_t * uri) +{ + pj_str_t localAddress; + pjsip_transport_type_e transportType; + + // Find the transport that must be used with the given uri + pj_str_t tmp; + pj_strdup_with_null(_pool, &tmp, uri); + pjsip_uri * genericUri; + genericUri = pjsip_parse_uri(_pool, tmp.ptr, tmp.slen, 0); + + pjsip_sip_uri * sip_uri = NULL; + sip_uri = (pjsip_sip_uri*)pjsip_uri_get_uri(genericUri); + if (sip_uri == NULL) { + _debug("Invalid uri in findLocalAddressFromTransport\n"); + return *pj_gethostname(); + } + + if (PJSIP_URI_SCHEME_IS_SIPS(sip_uri)) { + transportType = PJSIP_TRANSPORT_TLS; + } else { + transportType = PJSIP_TRANSPORT_UDP; + } + + // Get the transport manager associated with + // this endpoint + pjsip_tpmgr * tpmgr = NULL; + tpmgr = pjsip_endpt_get_tpmgr(_endpt); + if (tpmgr) { + _debug("Unexpected: Cannot get tpmgr from endpoint.\n"); + return *pj_gethostname(); + } + + // Find the local address (and port) based on the registered + // transports and the transport type + int port; + pj_status_t status; + status = pjsip_tpmgr_find_local_addr(tpmgr, _pool, transportType, NULL, &localAddress, &port); + if (status != PJ_SUCCESS) { + _debug("Failed to find local address from transport\n"); + return *pj_gethostname(); + } + + return localAddress; +} + +int SIPVoIPLink::findLocalPortFromUri(const pj_str_t * uri) +{ + pj_str_t localAddress; + pjsip_transport_type_e transportType; + int port; + + // Find the transport that must be used with the given uri + pj_str_t tmp; + pj_strdup_with_null(_pool, &tmp, uri); + pjsip_uri * genericUri; + genericUri = pjsip_parse_uri(_pool, tmp.ptr, tmp.slen, 0); + + pjsip_sip_uri * sip_uri = NULL; + sip_uri = (pjsip_sip_uri*)pjsip_uri_get_uri(genericUri); + if (sip_uri == NULL) { + _debug("Invalid uri in findLocalAddressFromTransport\n"); + return atoi(DEFAULT_SIP_PORT); + } + + if (PJSIP_URI_SCHEME_IS_SIPS(sip_uri)) { + transportType = PJSIP_TRANSPORT_TLS; + port = atoi(DEFAULT_SIP_TLS_PORT); + } else { + transportType = PJSIP_TRANSPORT_UDP; + port = atoi(DEFAULT_SIP_PORT); + } + + // Get the transport manager associated with + // this endpoint + pjsip_tpmgr * tpmgr = NULL; + tpmgr = pjsip_endpt_get_tpmgr(_endpt); + if (tpmgr) { + _debug("Unexpected: Cannot get tpmgr from endpoint.\n"); + return port; + } + + // Find the local address (and port) based on the registered + // transports and the transport type + + pj_status_t status; + status = pjsip_tpmgr_find_local_addr(tpmgr, _pool, transportType, NULL, &localAddress, &port); + if (status != PJ_SUCCESS) { + _debug("Failed to find local address from transport\n"); + } + + return port; +} int SIPVoIPLink::createTLSServer(AccountID id) { pjsip_tpfactory *tls; @@ -1820,7 +1899,7 @@ int SIPVoIPLink::createTLSServer(AccountID id) * be chosen automatically by the OS. */ pj_sockaddr_in_init(&local_addr, 0, 0); - pj_uint16_t localTlsPort = account->getTlsPort(); + pj_uint16_t localTlsPort = account->getPort(); if (localTlsPort != 0) { local_addr.sin_port = pj_htons(localTlsPort); } @@ -2291,7 +2370,7 @@ mod_on_rx_request (pjsip_rx_data *rdata) AccountID account_id; pjsip_uri *uri; pjsip_sip_uri *sip_uri; - std::string userName, server, caller, callerServer, peerNumber; + std::string userName, server; SIPVoIPLink *link; CallID id; SIPCall* call; @@ -2344,15 +2423,15 @@ mod_on_rx_request (pjsip_rx_data *rdata) uri = rdata->msg_info.from->uri; sip_uri = (pjsip_sip_uri *) pjsip_uri_get_uri (uri); - - /* Retrieve only the fisrt characters */ - caller = std::string (sip_uri->user.ptr, sip_uri->user.slen); - callerServer = std::string (sip_uri->host.ptr, sip_uri->host.slen); - peerNumber = caller + "@" + callerServer; + // Store the peer number + char tmp[PJSIP_MAX_URL_SIZE]; + int length = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, + sip_uri, tmp, PJSIP_MAX_URL_SIZE); + + std::string peerNumber(tmp, length); // Get the server voicemail notification // Catch the NOTIFY message - if (rdata->msg_info.msg->line.req.method.id == PJSIP_OTHER_METHOD) { method_name = "NOTIFY"; // Retrieve all the message. Should contains only the method name but ... diff --git a/sflphone-common/src/sip/sipvoiplink.h b/sflphone-common/src/sip/sipvoiplink.h index 23165fb539..68ce2ce433 100644 --- a/sflphone-common/src/sip/sipvoiplink.h +++ b/sflphone-common/src/sip/sipvoiplink.h @@ -210,22 +210,6 @@ class SIPVoIPLink : public VoIPLink */ void terminateOneCall(const CallID& id); - /** - * Build a sip address with the number that you want to call - * Example: sip:124@domain.com - * @param to The header of the recipient - * @return std::string Result as a string - */ - std::string SIPToHeader(const std::string& to); - - /** - * Check if an url is sip-valid - * @param url The url to check - * @return bool True if osip tell that is valid - */ - bool SIPCheckUrl(const std::string& url); - - /** * Send an outgoing call invite * @param call The current call @@ -241,13 +225,6 @@ class SIPVoIPLink : public VoIPLink */ bool SIPStartCall(SIPCall* call, const std::string& subject); - /** - * Get the Sip TO url (add sip:, add @host, etc...) - * @param to_url The To url - * @return std::string The SIP to address - */ - std::string getSipTo(const std::string& to_url, std::string hostname); - /** * Tell the user that the call was answered * @param @@ -396,6 +373,24 @@ class SIPVoIPLink : public VoIPLink /* 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 + * @return pj_str_t The extern (public) address + */ + pj_str_t findLocalAddressFromUri(const pj_str_t * uri); + + /* + * Does the same as findLocalAddressFromUri but returns a port. + * @param uri The uri from which we want to discover the address to use + * @return int The extern (public) port + */ + int findLocalPortFromUri(const pj_str_t * uri); }; + #endif -- GitLab