diff --git a/sflphone-client-gnome/src/callable_obj.c b/sflphone-client-gnome/src/callable_obj.c index 4b1d075c6c1b000c8421afaae9bc3593acb1ece8..8cff3894f7e88fe714cd8ab5a93ba3d0e567db67 100644 --- a/sflphone-client-gnome/src/callable_obj.c +++ b/sflphone-client-gnome/src/callable_obj.c @@ -18,6 +18,8 @@ */ #include <callable_obj.h> +#include <sflphone_const.h> +#include <time.h> gint is_callID_callstruct ( gconstpointer a, gconstpointer b) { @@ -239,8 +241,9 @@ gchar* get_call_duration (callable_obj_t *obj) if (start == end) return g_markup_printf_escaped("<small>Duration:</small> 0:00"); - duration = (int)end - (int)start; + duration = (int) difftime(end, start); + DEBUG("END: %d START: %d DURATION: %d", end, start, duration); if( duration / 60 == 0 ) { if( duration < 10 ) diff --git a/sflphone-client-gnome/src/config/accountwindow.c b/sflphone-client-gnome/src/config/accountwindow.c index 43c4ec66f35268bab1d7b493f6fcd66a83c2860d..49683dc52e64ea8cac55f1b3859a1d3520b6943e 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/contacts/calltree.c b/sflphone-client-gnome/src/contacts/calltree.c index c90853a4c0945b73487522532eedab485ae252dc..469444f10334624cacc6b2644e960cb442951df6 100644 --- a/sflphone-client-gnome/src/contacts/calltree.c +++ b/sflphone-client-gnome/src/contacts/calltree.c @@ -157,14 +157,14 @@ calltree_reset (calltab_t* tab) void focus_on_calltree_out(){ - DEBUG("set_focus_on_calltree_out \n"); + DEBUG("set_focus_on_calltree_out"); // gtk_widget_grab_focus(GTK_WIDGET(sw)); focus_is_on_calltree = FALSE; } void focus_on_calltree_in(){ - DEBUG("set_focus_on_calltree_in \n"); + DEBUG("set_focus_on_calltree_in"); // gtk_widget_grab_focus(GTK_WIDGET(sw)); focus_is_on_calltree = TRUE; } @@ -615,7 +615,7 @@ void calltree_display (calltab_t *tab) { } else - ERROR ("calltree.c line 1050 . This is probably a bug in the application"); + ERROR ("calltree.c line %d . This is probably a bug in the application", __LINE__); gtk_widget_hide (active_calltree->tree); diff --git a/sflphone-client-gnome/src/contacts/history.c b/sflphone-client-gnome/src/contacts/history.c index 5ce53416f65c3120f79739d92033776cab2cba65..6d18b39471b02f8510022d7206dc9df6a88b1ade 100644 --- a/sflphone-client-gnome/src/contacts/history.c +++ b/sflphone-client-gnome/src/contacts/history.c @@ -57,7 +57,7 @@ static GtkTreeModel* history_create_filter (GtkTreeModel* child) { GtkTreeModel* ret; - DEBUG("Create Filter\n"); + DEBUG("Create Filter"); ret = gtk_tree_model_filter_new (child, NULL); gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (ret), history_is_visible, NULL, NULL); return GTK_TREE_MODEL (ret); diff --git a/sflphone-client-gnome/src/contacts/searchbar.c b/sflphone-client-gnome/src/contacts/searchbar.c index 80a7cf55bf43786f00bfba456f43167ea0d09307..2044b4badd022dd103b60e32bad63cbbaf3c1fef 100644 --- a/sflphone-client-gnome/src/contacts/searchbar.c +++ b/sflphone-client-gnome/src/contacts/searchbar.c @@ -116,14 +116,14 @@ static void text_changed_cb (GtkEntry *entry, GParamSpec *pspec) void focus_on_searchbar_out(){ - DEBUG("set_focus_on_searchbar_out \n"); + DEBUG("set_focus_on_searchbar_out"); // gtk_widget_grab_focus(GTK_WIDGET(sw)); focus_is_on_searchbar = FALSE; } void focus_on_searchbar_in(){ - DEBUG("set_focus_on_searchbar_in \n"); + DEBUG("set_focus_on_searchbar_in"); // gtk_widget_grab_focus(GTK_WIDGET(sw)); focus_is_on_searchbar = TRUE; } @@ -199,7 +199,6 @@ GtkWidget* history_searchbar_new (void) gtk_widget_show_all (menu); #else - searchbox = sexy_icon_entry_new(); image = gtk_image_new_from_stock( GTK_STOCK_FIND , GTK_ICON_SIZE_SMALL_TOOLBAR); sexy_icon_entry_set_icon( SEXY_ICON_ENTRY(searchbox), SEXY_ICON_ENTRY_PRIMARY , GTK_IMAGE(image) ); diff --git a/sflphone-client-gnome/src/dbus/dbus.c b/sflphone-client-gnome/src/dbus/dbus.c index 5e83cbb0372300807823cb29fb8c0d403fa9c878..ad4fc09a2a5810a8c5fb9cb1e07045225f195e16 100644 --- a/sflphone-client-gnome/src/dbus/dbus.c +++ b/sflphone-client-gnome/src/dbus/dbus.c @@ -121,9 +121,9 @@ call_state_cb (DBusGProxy *proxy UNUSED, { if(c->_state==CALL_STATE_CURRENT) { - // peer hung up, the conversation was established, so _start has been initialized with the current time value + // peer hung up, the conversation was established, so _stop has been initialized with the current time value DEBUG("call state current"); - set_timestamp (&c->_time_start); + set_timestamp (&c->_time_stop); calltree_update_call( history, c ); } stop_notification(); diff --git a/sflphone-client-gnome/src/mainwindow.c b/sflphone-client-gnome/src/mainwindow.c index d481473024f30dfcfc20cb8d4455417d554bfed5..df5b9ce9e2d94746f1c600c1965c9a600876f4ad 100644 --- a/sflphone-client-gnome/src/mainwindow.c +++ b/sflphone-client-gnome/src/mainwindow.c @@ -104,7 +104,6 @@ on_key_released (GtkWidget *widget, GdkEventKey *event, gpointer user_data UNUSE { DEBUG("On key released from Main Window : %s\n", gtk_widget_get_name(widget)); - if (focus_is_on_searchbar == FALSE) { // If a modifier key is pressed, it's a shortcut, pass along if(event->state & GDK_CONTROL_MASK || @@ -119,8 +118,7 @@ on_key_released (GtkWidget *widget, GdkEventKey *event, gpointer user_data UNUSE ) return FALSE; else - sflphone_keypad(event->keyval, event->string); - + sflphone_keypad(event->keyval, event->string); } return TRUE; diff --git a/sflphone-client-gnome/src/sflphone_const.h b/sflphone-client-gnome/src/sflphone_const.h index 57820d70c99a15de58dfc78737ce8721df5ac254..ce0c829739eb88ac1cbe4eb6a58641f66723ae32 100644 --- a/sflphone-client-gnome/src/sflphone_const.h +++ b/sflphone-client-gnome/src/sflphone_const.h @@ -46,14 +46,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 97e0b2bb3cbfa8510a03e675f0f8578a392d5a50..0f3e3239b968c7762b32c33a7c8e2f619212b69e 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 0b020633f33d574497ca97173bc1ae83586adeb2..2f5a2b720a6e11ac706379717f446c8126e419b7 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 3d141db0ef0c50572fb22aa3ebc6be74aadf56ee..cfb333972d0a1918b6494a9db09ba12a01343267 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 */ @@ -56,10 +57,15 @@ int SIPAccount::registerVoIPLink() /* 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)); - + _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 a9925d734f8d67a46c4d438fdfd3154a9046594a..e1db28ce1ebd0286b29dabf3b0fca97441c770a3 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 6d01264343029c39b7af4ba873e1fde3a681e84c..fadfc65986a00c64043d33df49d420331881ee79 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) {