diff --git a/drucall.admin.inc b/drucall.admin.inc index 69050135a3f6abcbc70932c93a896f7d8b59fb64..8608668820bb3edc63a616d794c7a1701adf395c 100644 --- a/drucall.admin.inc +++ b/drucall.admin.inc @@ -47,6 +47,49 @@ function drucall_admin($form, &$form_state) { '#description' => t('Whether or not to show a DTMF dialing pad during calls.'), ); + $form['sip_domain'] = array( + '#type' => 'textfield', + '#title' => t('SIP domain'), + '#default_value' => variable_get('sip_domain', ''), + '#cols' => 40, + '#rows' => 1, + '#description' => t('The SIP domain to be used to construct the From: header for calls made by logged-in Drupal users.'), + ); + + $form['ws_cookie_secret'] = array( + '#type' => 'textfield', + '#title' => t('WebSocket Cookie Shared Secret'), + '#default_value' => variable_get('ws_cookie_secret', ''), + '#cols' => 40, + '#rows' => 1, + '#description' => t('The shared secret used to authenticate WebSocket cookies. Must match the WSCookieAuthSharedSecret in the repro SIP proxy.'), + ); + + $form['ws_cookie_domain'] = array( + '#type' => 'textfield', + '#title' => t('WebSocket Cookie Domain'), + '#default_value' => variable_get('ws_cookie_domain', ''), + '#cols' => 40, + '#rows' => 1, + '#description' => t('The domain to set in cookies if using SIP over WebSocket cookie authentication. This may just be part of the domain and it must match both the Drupal web server domain and the WebSocket URL (below). E.g. if the web site is www.example.org and WebSocket server is wss://sip-ws.example.org then you must put example.org in this field.'), + ); + + $form['ws_cookie_timeout'] = array( + '#type' => 'textfield', + '#title' => t('WebSocket Cookie Timeout'), + '#default_value' => variable_get('ws_cookie_timeout', '900'), + '#cols' => 40, + '#rows' => 1, + '#description' => t('Specify the duration, in seconds, that the authentication code is valid. This also sets the expiration time of the cookies.'), + ); + + $form['ws_cookies_in_url'] = array( + '#type' => 'checkbox', + '#title' => t('Send WebSocket authentication as URL parameters'), + '#default_value' => variable_get('ws_cookies_in_url', true), + '#description' => t('If the WebSocket server doesn\'t have the same domain name or domain suffix as the Drupal web site, the browser will not send the cookies. Select this option to append the cookie values to the WebSocket URL so authentication will work across domains.'), + ); + $form['display_name'] = array( '#type' => 'textfield', '#title' => t('Display name for caller'), @@ -156,6 +199,11 @@ function drucall_admin_submit($form, &$form_state) { variable_set('enable_video', $form_state['values']['enable_video']); variable_set('enable_chat', $form_state['values']['enable_chat']); variable_set('enable_dtmf_pad', $form_state['values']['enable_dtmf_pad']); + variable_set('sip_domain', $form_state['values']['sip_domain']); + variable_set('ws_cookie_secret', $form_state['values']['ws_cookie_secret']); + variable_set('ws_cookie_domain', $form_state['values']['ws_cookie_domain']); + variable_set('ws_cookie_timeout', $form_state['values']['ws_cookie_timeout']); + variable_set('ws_cookies_in_url', $form_state['values']['ws_cookies_in_url']); variable_set('display_name', $form_state['values']['display_name']); variable_set('from_uri', $form_state['values']['from_uri']); variable_set('auth_user', $form_state['values']['auth_user']); diff --git a/drucall.module b/drucall.module index f7a1ba6f37833877a47b329f024dea26e4b1bf1e..683bbe7acaa3ed1470c89b224d50c23e41adb8e9 100644 --- a/drucall.module +++ b/drucall.module @@ -48,6 +48,7 @@ function drucall_theme() { function drucall_call() { global $language; + global $user; // Make sure the necessary jQuery UI components are available on // the page, Drupal loads core jQuery automatically but not jQuery UI @@ -72,6 +73,63 @@ function drucall_call() { libraries_load($libname); } + $caller_domain = variable_get('sip_domain'); + $display_name = ''; + $caller_uri = ''; + $caller_auth_user = ''; + $caller_password = ''; + $sip_register = FALSE; + if($user->uid != 0 && !empty($caller_domain)) { + // A user is logged in + $display_name = $user->name; + // FIXME: should check that Drupal username is valid for SIP + $caller_uri = 'sip:' . $user->name . '@' . $caller_domain; + $sip_register = TRUE; + } else { + // Guest user + $display_name = variable_get('display_name'); + $caller_uri = variable_get('from_uri'); + $caller_auth_user = variable_get('auth_user'); + $caller_password = variable_get('auth_password'); + } + + $ws_cookie_secret = variable_get('ws_cookie_secret'); + $websocket_server_url = variable_get('websocket_server_url'); + $ws_cookies_in_url = variable_get('ws_cookies_in_url'); + if(!empty($ws_cookie_secret)) { + $ws_cookie_timeout = variable_get('ws_cookie_timeout'); // seconds + $sip_from = explode(':', $caller_uri)[1]; + $sip_to = '*@*'; + $ws_cookie_domain = variable_get('ws_cookie_domain'); + $ws_url = parse_url($websocket_server_url); + if(empty($ws_cookie_domain)) { + $ws_cookie_domain = $ws_url['host']; + } + + $time_limit = REQUEST_TIME + $ws_cookie_timeout; // seconds + $cookie_value = '1:' . REQUEST_TIME . ':' . $time_limit . ':' . $sip_from . ':' . $sip_to; + $cookie_value_encoded = urlencode($cookie_value); + $extra_value = ''; // TODO - a shopping cart ID, + // order ID, customer ID or some other value + // Example sending the Drupal session ID through SIP + if(!empty($user->ssid)) + $extra_value = 'drupal:ssid:' . $user->ssid; + else + $extra_value = 'drupal:sid:' . $user->sid; + $extra_value_encoded = urlencode($extra_value); + $digest_input = $cookie_value . ':' . $extra_value; + $cookie_mac = hash_hmac ('sha1', $digest_input, $ws_cookie_secret); + + setrawcookie("WSSessionInfo", $cookie_value_encoded, $time_limit, '/', $ws_cookie_domain); + setrawcookie("WSSessionExtra", $extra_value_encoded, $time_limit, '/', $ws_cookie_domain); + setrawcookie("WSSessionMAC", $cookie_mac, $time_limit, '/', $ws_cookie_domain); + if($ws_cookies_in_url) { + if(empty($ws_url['path'])) + $websocket_server_url = $websocket_server_url . '/'; + $websocket_server_url = $websocket_server_url . ';WSSessionInfo=' . $cookie_value_encoded . ';WSSessionExtra=' . $extra_value_encoded . ';WSSessionMAC=' . $cookie_mac; + } + } + $my_settings = array( 'mod_path' => drupal_get_path('module', 'drucall'), 'phone_number' => variable_get('default_destination'), @@ -79,17 +137,19 @@ function drucall_call() { 'enable_video' => variable_get('enable_video'), 'enable_chat' => variable_get('enable_chat'), 'enable_dtmf_pad' => variable_get('enable_dtmf_pad'), - 'display_name' => variable_get('display_name'), - 'impi' => variable_get('auth_user'), - 'impu' => variable_get('from_uri'), - 'password' => variable_get('auth_password'), + 'display_name' => $display_name, + 'impi' => $caller_auth_user, + 'impu' => $caller_uri, + 'password' => $caller_password, 'realm' => variable_get('auth_realm'), - 'websocket_server_url' => variable_get('websocket_server_url'), + 'websocket_server_url' => $websocket_server_url, 'sip_outboundproxy_url' => variable_get('sip_outboundproxy_url'), 'turn_server_url' => variable_get('turn_server_url'), 'turn_username' => variable_get('turn_username'), 'turn_password' => variable_get('turn_password'), 'language_code' => $language->language, + 'sip_register' => $sip_register, + 'extra_header_value' => $extra_value, ); drupal_add_js( diff --git a/js/drucall.js b/js/drucall.js index d6dbced8d1cc9ff4c1f15f12b804760ca465614a..fdc1df10537e32064549ce4b5af308f408d99250 100644 --- a/js/drucall.js +++ b/js/drucall.js @@ -39,7 +39,7 @@ // User SIP registration registration : { - on_startup: false, // Register when websocket link starts? + on_startup: dcsettings.sip_register, // Register when websocket link starts? expiry: 3600, // Registration expiry (seconds) user_control: false, // Show button for user to (de)register server: null, // Registration server @@ -84,7 +84,7 @@ }, extra_headers : [ - // 'X-WS-Session-Extra: some_token=value' + 'X-WS-Session-Extra: ' + dcsettings.extra_header_value ] };