httprl.install in HTTP Parallel Request & Threading Library 7
Same filename and directory in other branches
Handle HTTP Parallel Request Library installation and upgrade tasks.
File
httprl.installView source
<?php
/**
* @file
* Handle HTTP Parallel Request Library installation and upgrade tasks.
*/
/**
* Implements hook_uninstall().
*/
function httprl_uninstall() {
variable_del('httprl_server_addr');
variable_del('httprl_server_hostname');
variable_del('httprl_server_port');
variable_del('httprl_server_schema');
variable_del('httprl_background_callback');
variable_del('httprl_dns_timeout');
variable_del('httprl_connect_timeout');
variable_del('httprl_ttfb_timeout');
variable_del('httprl_timeout');
variable_del('httprl_global_timeout');
variable_del('httprl_url_inbound_alter');
variable_del('httprl_non_blocking_fclose_delay');
}
/**
* Implements hook_requirements().
*/
function httprl_requirements($phase) {
$requirements = array();
// Ensure translations don't break at install time.
$t = get_t();
if ($phase == 'runtime' || $phase == 'install') {
$function_list = array(
'stream_socket_client',
'stream_select',
'stream_set_blocking',
'stream_get_meta_data',
'stream_socket_get_name',
);
// Check each function to make sure it exists.
foreach ($function_list as $function_name) {
if (!function_exists($function_name)) {
$requirements['httprl_function_' . $function_name] = array(
'title' => $t('HTTPRL'),
'value' => $phase == 'install' ? FALSE : $function_name,
'severity' => REQUIREMENT_ERROR,
'description' => $t('<a href="!url">%name()</a> is disabled on this server. Please contact your hosting provider and see if they can re-enable this function for you.', array(
'!url' => 'http://php.net/' . str_replace('_', '-', $function_name),
'%name' => $function_name,
)),
);
}
}
}
if ($phase == 'runtime') {
// Check that the menu router item is working. If it is not working, the
// rest of the tests below will be pointless.
$item = menu_get_item('httprl_async_function_callback');
if (empty($item['page_callback']) || strpos($item['page_callback'], 'httprl') === FALSE) {
$requirements['httprl_callback'] = array(
'title' => $t('HTTPRL - Menu Callback'),
'severity' => REQUIREMENT_WARNING,
'value' => $t('Flush your caches'),
'description' => $t('You need to flush your menu cache. The background callback for httprl is not there.'),
);
return $requirements;
}
if (defined('VERSION') && substr(VERSION, 0, 1) >= 7 && httprl_variable_get('maintenance_mode', 0) || httprl_variable_get('site_offline', 0)) {
if (empty($requirements)) {
$requirements['httprl'] = array(
'title' => $t('HTTPRL'),
'severity' => REQUIREMENT_INFO,
'value' => $phase == 'install' ? TRUE : $t('All the required functions are enabled, but non blocking requests can not be tested while the site is in maintenance mode.'),
);
}
return $requirements;
}
// Test the non-blocking url.
list($success, $msg_non_blocking) = httprl_install_http_test(2, FALSE);
if (!$success) {
// Test the blocking url.
list($success, $msg_blocking) = httprl_install_http_test(2, TRUE);
if (!$success) {
// Test that drupal_http_request() works.
list($success, $msg_core) = httprl_install_http_test(1);
if (!$success) {
$requirements['httprl_callback'] = array(
'title' => $t('HTTPRL - Core'),
'severity' => REQUIREMENT_ERROR,
'value' => $t('drupal_http_request()'),
'description' => $t('Your system or network configuration does not allow Drupal to access web pages. This could be due to your webserver configuration or PHP settings. Debug info: !debug <br />For more info go here: <a href="!link">"HTTP request status Fails" error</a>', array(
'!link' => 'http://drupal.org/node/588186',
'!debug' => httprl_pr($GLOBALS['_httprl']['install']['debug'], TRUE),
)),
);
return $requirements;
}
$requirements['httprl_blocking'] = array(
'title' => $t('HTTPRL - Blocking'),
'severity' => REQUIREMENT_ERROR,
'value' => $t('Problem with stream_select()'),
'description' => $t('This server can not issue self http requests with stream_select(). Debug info: !debug <br />', array(
'!debug' => httprl_pr($GLOBALS['_httprl']['install']['debug'], TRUE),
)),
);
return $requirements;
}
$requirements['httprl_nonblocking'] = array(
'title' => $t('HTTPRL - Non Blocking'),
'severity' => REQUIREMENT_WARNING,
'value' => $t('This server does not handle hanging connections.'),
'description' => $t('Using non blocking mode on this server may not work correctly. Debug info: !debug <br />', array(
'!debug' => httprl_pr($GLOBALS['_httprl']['install']['debug'], TRUE),
)),
);
}
}
if (!empty($msg_non_blocking)) {
$requirements['httprl_settings_change_a'] = array(
'title' => $t('HTTPRL - Settings'),
'severity' => REQUIREMENT_WARNING,
'value' => $t('The current configuration does not work.'),
'description' => $msg_non_blocking,
);
}
if (!empty($msg_blocking)) {
$requirements['httprl_settings_change_b'] = array(
'title' => $t('HTTPRL - Settings'),
'severity' => REQUIREMENT_WARNING,
'value' => $t('The current configuration does not work.'),
'description' => $msg_blocking,
);
}
if (!empty($msg_core)) {
$requirements['httprl_settings_change_c'] = array(
'title' => $t('HTTPRL - Settings'),
'severity' => REQUIREMENT_WARNING,
'value' => $t('The current configuration does not work.'),
'description' => $msg_core,
);
}
if (empty($requirements)) {
$requirements['httprl'] = array(
'title' => $t('HTTPRL'),
'severity' => REQUIREMENT_OK,
'value' => $phase == 'install' ? TRUE : $t('All the required functions are enabled and non blocking requests are working.'),
);
}
return $requirements;
}
/**
* Issue a HTTP request to admin/httprl-test, verifying that the server got it.
*
* @param int $mode
* 1: use drupal_http_request()
* 2: use httprl_request()
* @param bool $blocking
* (Optional) HTTPRL blocking mode.
*
* @return array
* (bool, msg).
*/
function httprl_install_http_test($mode, $blocking = FALSE, $depth = 0) {
$t = get_t();
$depth++;
set_time_limit(0);
// 512 bits = 64 bytes.
if (function_exists('drupal_random_bytes')) {
$id = 'httprl_' . hash('sha512', drupal_random_bytes(64));
}
elseif (function_exists('openssl_random_pseudo_bytes')) {
$id = 'httprl_' . hash('sha512', openssl_random_pseudo_bytes(64));
}
else {
$id = 'httprl_' . hash('sha512', mt_rand() . microtime(TRUE) . serialize($_SERVER));
}
$msg = '';
$hostname = httprl_get_hostname();
// Set the headers to point to this hostname.
$headers = array(
'Host' => $hostname,
'Connection' => 'closed',
);
// Setup the arguments for releasing the lock.
$timing = array(
httprl_variable_get('httprl_install_lock_time', 7),
httprl_variable_get('httprl_install_connection_time', 5),
);
$args = array(
array(
'function' => 'httprl_lock_release',
// Setup options array.
'options' => array(
'blocking' => $blocking,
'timeout' => $timing[0],
'max_redirects' => 0,
'headers' => $headers,
),
),
$id,
);
// Get a lock & start the timer.
lock_acquire($id, $args[0]['options']['timeout']);
timer_start($id);
if ($mode == 2) {
// Queue up the request.
if ($blocking) {
$args[0]['return'] = '';
$args[0]['printed'] = '';
}
// Enable background callbacks even if disabled.
$old_var = httprl_variable_get('httprl_background_callback', HTTPRL_BACKGROUND_CALLBACK);
$GLOBALS['conf']['httprl_background_callback'] = HTTPRL_BACKGROUND_CALLBACK;
$url = httprl_queue_background_callback($args);
if (empty($url)) {
return array(
FALSE,
$t('The background callbacks setting is disabled.'),
);
}
else {
$url = array_keys($url);
$url = array_pop($url);
// Execute request.
$output = httprl_send_request();
}
// Restore the background callbacks setting.
$GLOBALS['conf']['httprl_background_callback'] = $old_var;
}
else {
// Get options.
$callback_options = array_shift($args);
// Build URL to point to httprl_async_function_callback on this server.
$url = httprl_build_url_self('httprl_async_function_callback?count=0', TRUE);
// Create lock name for this run.
$available = FALSE;
$lock_counter = 0;
while (!$available && $lock_counter < 20) {
// 512 bits = 64 bytes.
if (function_exists('drupal_random_bytes')) {
$name = 'httprl_' . hash('sha512', drupal_random_bytes(64));
}
elseif (function_exists('openssl_random_pseudo_bytes')) {
$name = 'httprl_' . hash('sha512', openssl_random_pseudo_bytes(64));
}
else {
$name = 'httprl_' . hash('sha512', mt_rand() . microtime(TRUE) . serialize($_SERVER));
}
$available = lock_may_be_available($name);
$lock_counter++;
}
$callback_options['options']['lock_name'] = $name;
lock_acquire($name, $callback_options['options']['timeout']);
// Create data array and options for request.
$options = array(
'data' => array(
'master_key' => hash('sha512', httprl_drupal_get_private_key()),
'temp_key' => $name,
'mode' => TRUE,
'php_timeout' => $callback_options['options']['timeout'],
'function' => $callback_options['function'],
// Follow rfc4648 for base64url
// @see http://tools.ietf.org/html/rfc4648#page-7
'args' => strtr(base64_encode(serialize($args)), array(
'+' => '-',
'/' => '_',
)),
),
'method' => 'POST',
'headers' => $headers,
'timeout' => $callback_options['options']['timeout'],
'max_redirects' => $callback_options['options']['max_redirects'],
);
httprl_handle_data($options);
// Execute the request using core.
if (defined('VERSION') && substr(VERSION, 0, 1) >= 7) {
$output = drupal_http_request($url, $options);
}
else {
$output = drupal_http_request($url, $options['headers'], $options['method'], $options['data'], $options['max_redirects'], $options['timeout']);
}
}
// Wait for the lock and stop the timer.
while (lock_wait($id)) {
usleep(25000);
}
$time = timer_stop($id);
// Add in debugging info.
$time['mode'] = $mode;
$time['blocking'] = $blocking;
$time['url'] = $url;
$time['request'] = $output;
$GLOBALS['_httprl']['install']['debug'][] = $time;
// See if the request came back in under 5 seconds, or if it timed out.
if ($time['time'] / 1000 > $timing[1]) {
if ($depth <= 1) {
list($success, $msg) = httprl_install_try_different_settings_checker($mode, $blocking, $depth);
if ($success) {
return array(
$success,
$msg,
);
}
}
}
else {
$hostname = httprl_get_hostname();
// Check if the httprl_server_hostname needs to be set to HTTP_HOST or
// SERVER_NAME.
if (!empty($hostname) && $hostname !== 'default' && ip2long($hostname) === FALSE && httprl_variable_get('httprl_server_hostname', FALSE) != $hostname) {
$msg = $t('The "Host name of the server to send all self server requests to" setting needs to be changed to @hostname on the <a href="@url">configuration page</a>,', array(
'@url' => url('admin/config/development/httprl'),
'@hostname' => $hostname,
));
}
return array(
TRUE,
$msg,
);
}
}
function httprl_install_fclose_delay_check($mode, $blocking, $depth) {
$t = get_t();
$msg = '';
if (httprl_variable_get('httprl_non_blocking_fclose_delay', HTTPRL_NON_BLOCKING_FCLOSE_DELAY) != 0 || $blocking != FALSE) {
return;
}
// Try again with a fclose_delay of 25ms.
$GLOBALS['conf']['httprl_non_blocking_fclose_delay'] = 25;
list($success, $msg) = httprl_install_http_test($mode, $blocking, $depth);
if ($success) {
// Try again with a fclose_delay of 5ms.
$GLOBALS['conf']['httprl_non_blocking_fclose_delay'] = 5;
list($success, $msg) = httprl_install_http_test($mode, $blocking, $depth);
if ($success) {
$msg = $t('The Millisecond Delay For Non-Blocking Requests setting needs to be changed to 5 on the <a href="@url">configuration page</a>,', array(
'@url' => url('admin/config/development/httprl'),
));
}
else {
$msg = $t('The Millisecond Delay For Non-Blocking Requests setting needs to be changed to 25 on the <a href="@url">configuration page</a>,', array(
'@url' => url('admin/config/development/httprl'),
));
}
}
$GLOBALS['conf']['httprl_non_blocking_fclose_delay'] = 0;
return array(
$success,
$msg,
);
}
function httprl_install_try_different_settings_checker($mode, $blocking, $depth) {
$t = get_t();
list($success, $msg) = httprl_install_fclose_delay_check($mode, $blocking, $depth);
if ($success) {
return array(
$success,
$msg,
);
}
$msg = '';
$ip = httprl_variable_get('httprl_server_addr', FALSE);
// Try with it empty.
$GLOBALS['conf']['httprl_server_addr'] = FALSE;
httprl_build_url_self('', FALSE, TRUE);
list($success, $msg) = httprl_install_http_test($mode, $blocking, $depth);
if ($success) {
$msg = $t('The "IP Address to send all self server requests to" setting needs to be empty on the <a href="@url">configuration page</a>,', array(
'@url' => url('admin/config/development/httprl'),
));
}
else {
list($success, $msg) = httprl_install_fclose_delay_check($mode, $blocking, $depth);
if ($success) {
$msg .= ' ' . $t('The "IP Address to send all self server requests to" setting needs to be empty on the <a href="@url">configuration page</a>,', array(
'@url' => url('admin/config/development/httprl'),
));
}
// Try again with -1.
$GLOBALS['conf']['httprl_server_addr'] = -1;
httprl_build_url_self('', FALSE, TRUE);
list($success, $msg) = httprl_install_http_test($mode, $blocking, $depth);
if ($success) {
$msg = $t('The "IP Address to send all self server requests to" setting needs to be changed to -1 on the <a href="@url">configuration page</a>,', array(
'@url' => url('admin/config/development/httprl'),
));
}
else {
list($success, $msg) = httprl_install_fclose_delay_check($mode, $blocking, $depth);
if ($success) {
$msg .= ' ' . $t('The "IP Address to send all self server requests to" setting needs to be changed to -1 on the <a href="@url">configuration page</a>,', array(
'@url' => url('admin/config/development/httprl'),
));
}
}
}
$GLOBALS['conf']['httprl_server_addr'] = $ip;
httprl_build_url_self('', FALSE, TRUE);
return array(
$success,
$msg,
);
}
Functions
Name | Description |
---|---|
httprl_install_fclose_delay_check | |
httprl_install_http_test | Issue a HTTP request to admin/httprl-test, verifying that the server got it. |
httprl_install_try_different_settings_checker | |
httprl_requirements | Implements hook_requirements(). |
httprl_uninstall | Implements hook_uninstall(). |