From 14d4f141e43bfec75c3e4ef3b7e76e6e1866f990 Mon Sep 17 00:00:00 2001 From: pierre-luc <pierre-luc@aqra.ca> Date: Mon, 20 Jul 2009 18:31:06 -0400 Subject: [PATCH] [#1852] If chosen by the user, the hostname can now be solved and used for the whole time the user is connected to his/her SIP provider. This should be considered as a workaround, waiting to see if PJSIP will implement a non rfc-compliant solution to that issue. --- .../src/config/accountwindow.c | 26 ++++++-- sflphone-client-gnome/src/sflphone_const.h | 13 ++-- sflphone-common/src/account.h | 2 + sflphone-common/src/managerimpl.cpp | 2 + sflphone-common/src/sipaccount.cpp | 6 +- sflphone-common/src/sipaccount.h | 3 + sflphone-common/src/sipvoiplink.cpp | 66 ++++++++++++++++++- 7 files changed, 101 insertions(+), 17 deletions(-) diff --git a/sflphone-client-gnome/src/config/accountwindow.c b/sflphone-client-gnome/src/config/accountwindow.c index 198d0c9eba..3db8a4ee86 100644 --- a/sflphone-client-gnome/src/config/accountwindow.c +++ b/sflphone-client-gnome/src/config/accountwindow.c @@ -50,6 +50,7 @@ GtkWidget * entryUsername; GtkWidget * entryHostname; GtkWidget * entryPassword; GtkWidget * entryMailbox; +GtkWidget * entryResolveNameOnlyOnce; /* Signal to entryProtocol 'changed' */ void @@ -78,6 +79,7 @@ show_account_window (account_t * a) // Default settings gchar * curAccountID = ""; gchar * curAccountEnabled = "TRUE"; + gchar * curAccountResolveOnce = "FALSE"; gchar * curAccountType = "SIP"; gchar * curAlias = ""; gchar * curUsername = ""; @@ -102,6 +104,7 @@ show_account_window (account_t * a) curPassword = g_hash_table_lookup(currentAccount->properties, ACCOUNT_PASSWORD); curUsername = g_hash_table_lookup(currentAccount->properties, ACCOUNT_USERNAME); curMailbox = g_hash_table_lookup(currentAccount->properties, ACCOUNT_MAILBOX); + curAccountResolveOnce = g_hash_table_lookup(currentAccount->properties, ACCOUNT_RESOLVE_ONCE); } else { @@ -126,7 +129,7 @@ show_account_window (account_t * a) gtk_box_pack_start(GTK_BOX(dialog->vbox), frame, FALSE, FALSE, 0); gtk_widget_show(frame); - table = gtk_table_new ( 8, 2 , FALSE/* homogeneous */); + table = gtk_table_new (10, 2 , FALSE/* homogeneous */); gtk_table_set_row_spacings( GTK_TABLE(table), 10); gtk_table_set_col_spacings( GTK_TABLE(table), 10); gtk_widget_show(table); @@ -194,8 +197,14 @@ show_account_window (account_t * a) gtk_entry_set_text(GTK_ENTRY(entryHostname), curHostname); gtk_table_attach ( GTK_TABLE( table ), entryHostname, 1, 2, 5, 6, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + entryResolveNameOnlyOnce = gtk_check_button_new_with_mnemonic(_("_Resolve host name only once for the session")); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(entryResolveNameOnlyOnce), + g_strcasecmp(curAccountResolveOnce,"TRUE") == 0 ? TRUE: FALSE); + gtk_table_attach ( GTK_TABLE( table ), entryResolveNameOnlyOnce, 0, 2, 6, 7, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_widget_set_sensitive( GTK_WIDGET( entryResolveNameOnlyOnce ) , TRUE ); + label = gtk_label_new_with_mnemonic (_("_User name")); - gtk_table_attach ( GTK_TABLE( table ), label, 0, 1, 6, 7, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_table_attach ( GTK_TABLE( table ), label, 0, 1, 7, 8, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_misc_set_alignment(GTK_MISC (label), 0, 0.5); #if GTK_CHECK_VERSION(2,16,0) entryUsername = gtk_entry_new(); @@ -207,10 +216,10 @@ show_account_window (account_t * a) #endif gtk_label_set_mnemonic_widget (GTK_LABEL (label), entryUsername); gtk_entry_set_text(GTK_ENTRY(entryUsername), curUsername); - gtk_table_attach ( GTK_TABLE( table ), entryUsername, 1, 2, 6, 7, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_table_attach ( GTK_TABLE( table ), entryUsername, 1, 2, 7, 8, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); label = gtk_label_new_with_mnemonic (_("_Password")); - gtk_table_attach ( GTK_TABLE( table ), label, 0, 1, 7, 8, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_table_attach ( GTK_TABLE( table ), label, 0, 1, 8, 9, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_misc_set_alignment(GTK_MISC (label), 0, 0.5); #if GTK_CHECK_VERSION(2,16,0) entryPassword = gtk_entry_new(); @@ -223,15 +232,15 @@ show_account_window (account_t * a) gtk_entry_set_visibility(GTK_ENTRY(entryPassword), FALSE); gtk_label_set_mnemonic_widget (GTK_LABEL (label), entryPassword); gtk_entry_set_text(GTK_ENTRY(entryPassword), curPassword); - gtk_table_attach ( GTK_TABLE( table ), entryPassword, 1, 2, 7, 8, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_table_attach ( GTK_TABLE( table ), entryPassword, 1, 2, 8, 9, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); label = gtk_label_new_with_mnemonic (_("_Voicemail number")); - gtk_table_attach ( GTK_TABLE( table ), label, 0, 1, 8, 9, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_table_attach ( GTK_TABLE( table ), label, 0, 1, 9, 10, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_misc_set_alignment(GTK_MISC (label), 0, 0.5); entryMailbox = gtk_entry_new(); gtk_label_set_mnemonic_widget (GTK_LABEL (label), entryMailbox); gtk_entry_set_text(GTK_ENTRY(entryMailbox), curMailbox); - gtk_table_attach ( GTK_TABLE( table ), entryMailbox, 1, 2, 8, 9, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_table_attach ( GTK_TABLE( table ), entryMailbox, 1, 2, 9, 10, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_widget_show_all( table ); gtk_container_set_border_width (GTK_CONTAINER(table), 10); @@ -244,6 +253,9 @@ show_account_window (account_t * a) g_hash_table_replace(currentAccount->properties, g_strdup(ACCOUNT_ENABLED), g_strdup(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(entryEnabled)) ? "TRUE": "FALSE")); + g_hash_table_replace(currentAccount->properties, + g_strdup(ACCOUNT_RESOLVE_ONCE), + g_strdup(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(entryResolveNameOnlyOnce)) ? "TRUE": "FALSE")); g_hash_table_replace(currentAccount->properties, g_strdup(ACCOUNT_ALIAS), g_strdup((gchar *)gtk_entry_get_text(GTK_ENTRY(entryAlias)))); diff --git a/sflphone-client-gnome/src/sflphone_const.h b/sflphone-client-gnome/src/sflphone_const.h index a98c08525b..387098d4cb 100644 --- a/sflphone-client-gnome/src/sflphone_const.h +++ b/sflphone-client-gnome/src/sflphone_const.h @@ -44,14 +44,15 @@ #define UNUSED __attribute__((__unused__)) #define ACCOUNT_TYPE "Account.type" -#define ACCOUNT_ALIAS "Account.alias" -#define ACCOUNT_ENABLED "Account.enable" -#define ACCOUNT_MAILBOX "Account.mailbox" -#define ACCOUNT_HOSTNAME "hostname" -#define ACCOUNT_USERNAME "username" -#define ACCOUNT_PASSWORD "password" +#define ACCOUNT_ALIAS "Account.alias" +#define ACCOUNT_ENABLED "Account.enable" +#define ACCOUNT_MAILBOX "Account.mailbox" +#define ACCOUNT_HOSTNAME "hostname" +#define ACCOUNT_USERNAME "username" +#define ACCOUNT_PASSWORD "password" #define ACCOUNT_SIP_STUN_SERVER "STUN.server" #define ACCOUNT_SIP_STUN_ENABLED "STUN.enable" +#define ACCOUNT_RESOLVE_ONCE "Account.resolveOnce" /** * Global logger diff --git a/sflphone-common/src/account.h b/sflphone-common/src/account.h index 97e0b2bb3c..0f3e3239b9 100644 --- a/sflphone-common/src/account.h +++ b/sflphone-common/src/account.h @@ -58,6 +58,8 @@ typedef enum RegistrationState { #define CONFIG_ACCOUNT_ALIAS "Account.alias" #define CONFIG_ACCOUNT_MAILBOX "Account.mailbox" #define CONFIG_ACCOUNT_ENABLE "Account.enable" +#define CONFIG_ACCOUNT_RESOLVE_ONCE "Account.resolveOnce" + #define HOSTNAME "hostname" #define USERNAME "username" #define PASSWORD "password" diff --git a/sflphone-common/src/managerimpl.cpp b/sflphone-common/src/managerimpl.cpp index 0b020633f3..2f5a2b720a 100644 --- a/sflphone-common/src/managerimpl.cpp +++ b/sflphone-common/src/managerimpl.cpp @@ -2449,6 +2449,7 @@ std::map< std::string, std::string > ManagerImpl::getAccountDetails (const Accou a.insert (std::pair<std::string, std::string> (CONFIG_ACCOUNT_ALIAS, getConfigString (accountID, CONFIG_ACCOUNT_ALIAS))); a.insert (std::pair<std::string, std::string> (CONFIG_ACCOUNT_ENABLE, getConfigString (accountID, CONFIG_ACCOUNT_ENABLE) == "1" ? "TRUE": "FALSE")); + a.insert (std::pair<std::string, std::string> (CONFIG_ACCOUNT_RESOLVE_ONCE, getConfigString (accountID, CONFIG_ACCOUNT_RESOLVE_ONCE) == "1" ? "TRUE": "FALSE")); a.insert (std::pair<std::string, std::string> ( "Status", (state == Registered ? "REGISTERED": @@ -2483,6 +2484,7 @@ void ManagerImpl::setAccountDetails (const std::string& accountID, const std::ma setConfig (accountID, CONFIG_ACCOUNT_ALIAS, (*details.find (CONFIG_ACCOUNT_ALIAS)).second); setConfig (accountID, CONFIG_ACCOUNT_ENABLE, (*details.find (CONFIG_ACCOUNT_ENABLE)).second == "TRUE" ? "1": "0"); + setConfig (accountID, CONFIG_ACCOUNT_RESOLVE_ONCE, (*details.find (CONFIG_ACCOUNT_RESOLVE_ONCE)).second == "TRUE" ? "1": "0"); setConfig (accountID, CONFIG_ACCOUNT_TYPE, accountType); setConfig (accountID, USERNAME, (*details.find (USERNAME)).second); setConfig (accountID, PASSWORD, (*details.find (PASSWORD)).second); diff --git a/sflphone-common/src/sipaccount.cpp b/sflphone-common/src/sipaccount.cpp index 3d141db0ef..09e4b5364e 100644 --- a/sflphone-common/src/sipaccount.cpp +++ b/sflphone-common/src/sipaccount.cpp @@ -25,8 +25,9 @@ SIPAccount::SIPAccount (const AccountID& accountID) : Account (accountID, "sip") , _cred (NULL) - , _contact ("") , _bRegister (false) + , _contact ("") + , _resolveOnce (false) , _regc() { /* SIPVoIPlink is used as a singleton, because we want to have only one link for all the SIP accounts created */ @@ -59,7 +60,8 @@ int SIPAccount::registerVoIPLink() setHostname (Manager::instance().getConfigString (_accountID, HOSTNAME)); setUsername (Manager::instance().getConfigString (_accountID, USERNAME)); setPassword (Manager::instance().getConfigString (_accountID, PASSWORD)); - + _resolveOnce = Manager::instance().getConfigString (_accountID, CONFIG_ACCOUNT_RESOLVE_ONCE) == "1" ? true : false; + /* Start registration */ status = _link->sendRegister (_accountID); ASSERT (status , SUCCESS); diff --git a/sflphone-common/src/sipaccount.h b/sflphone-common/src/sipaccount.h index a9925d734f..e1db28ce1e 100644 --- a/sflphone-common/src/sipaccount.h +++ b/sflphone-common/src/sipaccount.h @@ -85,6 +85,7 @@ class SIPAccount : public Account bool isRegister() {return _bRegister;} void setRegister(bool result) {_bRegister = result;} + inline bool isResolveOnce(void) { return _resolveOnce; } private: @@ -107,6 +108,8 @@ class SIPAccount : public Account * SIP address */ std::string _contact; + + bool _resolveOnce; }; #endif diff --git a/sflphone-common/src/sipvoiplink.cpp b/sflphone-common/src/sipvoiplink.cpp index 6d01264343..fadfc65986 100644 --- a/sflphone-common/src/sipvoiplink.cpp +++ b/sflphone-common/src/sipvoiplink.cpp @@ -24,6 +24,7 @@ #include "sipcall.h" #include "sipaccount.h" #include "audio/audiortp.h" +#include "pjsip/sip_endpoint.h" #include <netinet/in.h> #include <arpa/nameser.h> @@ -31,6 +32,11 @@ #define CAN_REINVITE 1 +struct result +{ + pj_status_t status; + pjsip_server_addresses servers; +}; const pj_str_t STR_USER_AGENT = { (char*) "User-Agent", 10 }; @@ -141,6 +147,11 @@ void on_rx_offer (pjsip_inv_session *inv, const pjmedia_sdp_session *offer); */ void regc_cb (struct pjsip_regc_cbparam *param); +/* + * DNS Callback used in workaround for bug #1852 + */ +static void dns_cb(pj_status_t status, void *token, const struct pjsip_server_addresses *addr); + /* * Called to handle incoming requests outside dialogs * @param rdata @@ -329,18 +340,59 @@ SIPVoIPLink::getEvent() int SIPVoIPLink::sendRegister (AccountID id) { - pj_status_t status; int expire_value; char contactTmp[256]; + + pj_status_t status; pj_str_t svr, aor, contact, useragent; pjsip_tx_data *tdata; + pjsip_host_info destination; + std::string tmp, hostname, username, password; - SIPAccount *account; + SIPAccount *account = NULL; pjsip_regc *regc; pjsip_generic_string_hdr *h; pjsip_hdr hdr_list; account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount (id)); + if(account == NULL) { + _debug("In sendRegister: account is null"); + return false; + } + + if(account->isResolveOnce()) { + struct result result; + destination.type = PJSIP_TRANSPORT_UNSPECIFIED; + destination.flag = pjsip_transport_get_flag_from_type(PJSIP_TRANSPORT_UNSPECIFIED); + destination.addr.host = pj_str(const_cast<char*> ((account->getHostname()).c_str())); + destination.addr.port = 0; + + result.status = 0x12345678; + + pjsip_endpt_resolve(_endpt, _pool, &destination, &result, &dns_cb); + + /* The following magic number and construct are inspired from dns_test.c + * in test-pjsip directory. + */ + while (result.status == 0x12345678) { + pj_time_val timeout = { 1, 0 }; + pjsip_endpt_handle_events(_endpt, &timeout); + _debug("status : %d\n", result.status); + } + + if(result.status != PJ_SUCCESS) { + _debug("Failed to resolve hostname only once." + " Default resolver will be used on" + " hostname for all requests.\n"); + } else { + _debug("%d servers where obtained from name resolution.\n", result.servers.count); + char addr_buf[80]; + + pj_sockaddr_print((pj_sockaddr_t*) &result.servers.entry[0].addr, addr_buf, sizeof(addr_buf), 3); + account->setHostname(addr_buf); + } + } + hostname = account->getHostname(); username = account->getUsername(); password = account->getPassword(); @@ -1813,6 +1865,16 @@ int getModId() return _mod_ua.id; } +static void dns_cb(pj_status_t status, void *token, const struct pjsip_server_addresses *addr) +{ + struct result * result = (struct result*) token; + + result->status = status; + if (status == PJ_SUCCESS) { + pj_memcpy(&result->servers, addr, sizeof(*addr)); + } +} + void set_voicemail_info (AccountID account, pjsip_msg_body *body) { -- GitLab