Merge branch 'dev'
commit
f071b3669f
@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
cat <<EOF
|
||||
Dry-running fetch script
|
||||
|
||||
EOF
|
||||
/bin/php php/fetch-servers.php --verbose --dry-run > log.txt 2>&1;
|
||||
cat <<EOF
|
||||
Grep of log for each known server URL:
|
||||
|
||||
EOF
|
||||
for url in $(jq -r 'map(.base_url) | .[] | ltrimstr("http://") | ltrimstr("https://")' cache/rooms.json); do
|
||||
echo "Results for $url:";
|
||||
echo;
|
||||
grep "$url" log.txt;
|
||||
echo ">";
|
||||
read -r;
|
||||
done
|
@ -0,0 +1,106 @@
|
||||
|
||||
[regional]
|
||||
name=Regional Communities
|
||||
rating=safe
|
||||
rooms[]=brasil+118d
|
||||
rooms[]=deutsch+118d
|
||||
rooms[]=espanol+118d
|
||||
rooms[]=francais+118d
|
||||
rooms[]=iom+118d
|
||||
rooms[]=italiano+118d
|
||||
rooms[]=nl+118d
|
||||
rooms[]=persian+118d
|
||||
rooms[]=portugues+118d
|
||||
rooms[]=uk+118d
|
||||
rooms[]=russian+118d
|
||||
rooms[]=bangladesh+13f6
|
||||
rooms[]=czsk+13f6
|
||||
rooms[]=india+13f6
|
||||
rooms[]=indonesia+13f6
|
||||
rooms[]=korea+13f6
|
||||
rooms[]=poland+13f6
|
||||
rooms[]=scandinavia+2812
|
||||
rooms[]=fi+2812
|
||||
rooms[]=br+2b92
|
||||
rooms[]=germanpoliticssocietyphilosophy+8183
|
||||
sogs[]=fe93941471c07f294255391dba92ae3cf356efc4fdd287d8ba1ffef096dbaf56
|
||||
|
||||
[tech]
|
||||
name=Tech Communities
|
||||
rating=safe
|
||||
rooms[]=android+118d
|
||||
rooms[]=ai+118d
|
||||
rooms[]=gaming+118d
|
||||
rooms[]=im+118d
|
||||
rooms[]=linux+118d
|
||||
rooms[]=webdev+118d
|
||||
rooms[]=programming+13f6
|
||||
rooms[]=tech+2054
|
||||
rooms[]=ev-en+2812
|
||||
rooms[]=pv-en+2812
|
||||
rooms[]=gee+2b92
|
||||
rooms[]=mathnodes-dvpn-oxen-dero+8585
|
||||
rooms[]=plex+c01b
|
||||
|
||||
[china]
|
||||
name=Chinese-language Communities
|
||||
rating=unknown
|
||||
sogs[]=45674f4135e2dd929279a72e1e73957eed741c7bec00c87b1797ad52c235ea36
|
||||
sogs[]=7f55510a392324988041e7a97191f618a32dc05f2f6343de917fcfe1cb424e51
|
||||
|
||||
[powerusers]
|
||||
name=Communities for Powerusers
|
||||
rating=safe
|
||||
rooms[]=snops+118d
|
||||
rooms[]=sogops+118d
|
||||
rooms[]=indexloki+2cbd
|
||||
rooms[]=SNappsDevs+2cbd
|
||||
rooms[]=sessiondev+e56f
|
||||
|
||||
[misc]
|
||||
name=Miscellanous
|
||||
rating=unknown
|
||||
rooms[]=health+118d
|
||||
rooms[]=music+118d
|
||||
rooms[]=modernsurvival+118d
|
||||
rooms[]=philosophy+118d
|
||||
rooms[]=pol+2054
|
||||
rooms[]=biz+2b92
|
||||
rooms[]=guns+2b92
|
||||
rooms[]=hall+7242
|
||||
rooms[]=camping+c01b
|
||||
rooms[]=offtopic+e56f
|
||||
rooms[]=AISFW+fc30
|
||||
|
||||
[oxen]
|
||||
name=Official Communities
|
||||
rating=safe
|
||||
sogs[]=a03c383cf63c3c4efe67acc52112a6dd734b3a946b9545f488aaa93da7991238
|
||||
|
||||
[cryptocurrency]
|
||||
name=Cryptocurrency
|
||||
rooms[]=bitcoinaustralia+4bec
|
||||
rooms[]=moneroaustralia+4bec
|
||||
rooms[]=crypto+a03c
|
||||
|
||||
[privsec]
|
||||
name=Privacy & Security
|
||||
rating=safe
|
||||
rooms[]=im+118d
|
||||
rooms[]=privacy+118d
|
||||
rooms[]=security+118d
|
||||
rooms[]=degoogle+48e9
|
||||
rooms[]=privacyaustralia+4bec
|
||||
|
||||
[casual]
|
||||
name=Casual Communities
|
||||
rating=safe
|
||||
rooms[]=general-chat+8c12
|
||||
rooms[]=midnight-madness+9be4
|
||||
|
||||
[nsfw]
|
||||
name=18+ Communities
|
||||
rating=nsfw
|
||||
rooms[]=womanbodybeauty+13f6
|
||||
rooms[]=piao+2cd5
|
||||
rooms[]=AINSFW+fc30
|
@ -0,0 +1,116 @@
|
||||
<?php
|
||||
require_once "getenv.php";
|
||||
require_once "$PROJECT_ROOT/php/utils/servers-rooms.php";
|
||||
require_once "$PROJECT_ROOT/php/utils/logging.php";
|
||||
|
||||
class CommunityListing implements JsonSerializable {
|
||||
public readonly string $name;
|
||||
public readonly string $rating;
|
||||
public readonly array $rooms;
|
||||
|
||||
/**
|
||||
* @param \CommunityRoom[] $rooms
|
||||
*/
|
||||
public function __construct(string $name, ?string $rating, array $rooms) {
|
||||
$this->name = $name;
|
||||
$this->rating = $rating ?? "unknown";
|
||||
$this->rooms = $rooms;
|
||||
}
|
||||
|
||||
public function jsonSerialize(): mixed {
|
||||
// TODO: Careful serialization
|
||||
$details = get_object_vars($this);
|
||||
$details['rooms'] = array_map(function(\CommunityRoom $room){
|
||||
return $room->to_listing_data();
|
||||
}, $this->rooms);
|
||||
return $details;
|
||||
}
|
||||
|
||||
public function to_summary(): array {
|
||||
return array(
|
||||
'name' => $this->name,
|
||||
'rating' => $this->rating,
|
||||
'rooms' => count($this->rooms)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \CommunityListing[]
|
||||
*/
|
||||
function resolve_listings_config(): array {
|
||||
global $LISTINGS_INI, $ROOMS_FILE;
|
||||
$listings_raw = parse_ini_file($LISTINGS_INI, process_sections: true);
|
||||
$servers_raw = file_get_contents($ROOMS_FILE);
|
||||
$server_data = json_decode($servers_raw, true);
|
||||
$servers = CommunityServer::from_details_array($server_data);
|
||||
$rooms_by_id = [];
|
||||
foreach (CommunityServer::enumerate_rooms($servers) as $room) {
|
||||
$rooms_by_id[$room->get_room_identifier()] = $room;
|
||||
}
|
||||
$sogs_by_pubkey = [];
|
||||
foreach ($servers as $server) {
|
||||
$sogs_by_pubkey[$server->get_pubkey()] = $server;
|
||||
}
|
||||
$listings = [];
|
||||
foreach ($listings_raw as $id => $listing_props) {
|
||||
$rooms = [];
|
||||
if (isset($listing_props['rooms'])) {
|
||||
foreach ($listing_props['rooms'] as $room_id) {
|
||||
if (isset($rooms_by_id[$room_id])) {
|
||||
$rooms[] = $rooms_by_id[$room_id];
|
||||
} else {
|
||||
log_warning("Could not find room $room_id from listing $id.");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isset($listing_props['sogs'])) {
|
||||
foreach ($listing_props['sogs'] as $public_key) {
|
||||
if (isset($sogs_by_pubkey[$public_key])) {
|
||||
/** @var \CommunityServer $sogs */
|
||||
$sogs = $sogs_by_pubkey[$public_key];
|
||||
array_push($rooms, ...$sogs->rooms);
|
||||
} else {
|
||||
log_warning("Could not find sogs $public_key from listing $id.");
|
||||
}
|
||||
}
|
||||
}
|
||||
$listings[$id] = new CommunityListing(
|
||||
$listing_props['name'],
|
||||
$listing_props['rating'],
|
||||
$rooms
|
||||
);
|
||||
}
|
||||
|
||||
return $listings;
|
||||
}
|
||||
|
||||
function generate_listings() {
|
||||
global $LISTING_PROVIDER_LISTING_SUMMARY, $LISTING_PROVIDER_LISTINGS;
|
||||
log_info("Generating listings...");
|
||||
|
||||
$listings_resolved = resolve_listings_config();
|
||||
log_value($listings_resolved);
|
||||
$summaries = array_map(function(\CommunityListing $listing) {
|
||||
return $listing->to_summary();
|
||||
}, $listings_resolved);
|
||||
file_put_contents($LISTING_PROVIDER_LISTING_SUMMARY, json_encode($summaries));
|
||||
foreach ($listings_resolved as $id => $listing) {
|
||||
file_put_contents(
|
||||
"$LISTING_PROVIDER_LISTINGS/$id",
|
||||
json_encode($listing)
|
||||
);
|
||||
}
|
||||
$listings_count = count($listings_resolved);
|
||||
log_info("Generated $listings_count listings.");
|
||||
}
|
||||
|
||||
file_exists($LISTING_PROVIDER_LISTINGS) or mkdir($LISTING_PROVIDER_LISTINGS, 0755, true);
|
||||
|
||||
$options = getopt("v", ["verbose"]);
|
||||
if (isset($options["v"]) or isset($options["verbose"])) {
|
||||
$LOGGING_VERBOSITY = LoggingVerbosity::Debug;
|
||||
}
|
||||
|
||||
generate_listings();
|
||||
?>
|
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
require_once 'fetch-servers.php';
|
||||
require_once 'generate-html.php';
|
||||
require_once 'generate-listings.php';
|
||||
?>
|
@ -0,0 +1,332 @@
|
||||
<?php
|
||||
require_once 'utils.php';
|
||||
|
||||
/**
|
||||
* @template TReturn
|
||||
*/
|
||||
class FetchingCoroutine {
|
||||
/**
|
||||
* @var \Generator<int,CurlHandle,CurlHandle|false,TReturn> $generator
|
||||
*/
|
||||
private Generator $generator;
|
||||
|
||||
private bool $consumed = false;
|
||||
|
||||
/**
|
||||
* @var \Closure():bool $response_filter
|
||||
*/
|
||||
private Closure $response_filter;
|
||||
|
||||
/**
|
||||
* Creates a new Fetching Couroutine instance.
|
||||
* @param \Generator<int,CurlHandle,CurlHandle|false,TReturn> $generator
|
||||
* An instantiated generator yielding `string => CurlHandle` pairs.
|
||||
*/
|
||||
public function __construct(\Generator $generator) {
|
||||
$this->generator = $generator;
|
||||
$this->response_filter = function(CurlHandle $handle): bool {
|
||||
$code = curl_getinfo($handle, CURLINFO_RESPONSE_CODE);
|
||||
$url = curl_getinfo($handle, CURLINFO_EFFECTIVE_URL);
|
||||
log_debug("Got code $code for $url in default request arbitrator.");
|
||||
return $code < 300 && $code != 0;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new FetchingCoroutine to fetch the contents of a URL.
|
||||
* @param string $url URL to fetch.
|
||||
* @param array $curlopts Addition cURL options.
|
||||
* @return \FetchingCoroutine<CurlHandle|false> Coroutine returning
|
||||
*/
|
||||
public static function from_url(string $url, array $curlopts = []): \FetchingCoroutine {
|
||||
/**
|
||||
* @var Generator<int,CurlHandle,CurlHandle|false,CurlHandle|false> $oneshot
|
||||
*/
|
||||
$oneshot = (function() use ($url, $curlopts) {
|
||||
return yield make_curl_handle($url, $curlopts);
|
||||
})();
|
||||
return new FetchingCoroutine($oneshot);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set callback deciding valid responses.
|
||||
* @param Closure $response_filter Predicate on a processed CurlHandle.
|
||||
* @return \FetchingCoroutine
|
||||
*/
|
||||
public function set_response_filter(Closure $response_filter): \FetchingCoroutine {
|
||||
$this->response_filter = $response_filter;
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function assert_not_consumed() {
|
||||
if ($this->consumed) {
|
||||
throw new Error("This FetchingCoroutine has been used up by a transforming call");
|
||||
}
|
||||
}
|
||||
|
||||
private function consume() {
|
||||
$this->assert_not_consumed();
|
||||
$this->consumed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies the current coroutine to halt on failed fetches. Consumes current coroutine.
|
||||
* Resulting coroutine will not produce further fetches.
|
||||
* @return \FetchingCoroutine<TReturn|null> New FetchingCoroutine instance.
|
||||
*/
|
||||
public function stop_on_failure(): \FetchingCoroutine {
|
||||
$this->consume();
|
||||
$haltable = function () {
|
||||
foreach ($this->generator as $id => $handle) {
|
||||
if (!(yield $id => $handle)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
return $this->generator->getReturn();
|
||||
};
|
||||
return $this->project_coroutine_parameters(new FetchingCoroutine($haltable()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies the current coroutine to retry fetches. Consumes current coroutine.
|
||||
* @param int $retries Number of additional retries made for curl handles returned.
|
||||
* @param bool $tallied_retries If true, the retry count applies to the whole coroutine.
|
||||
* If false, each request is afforded the given retries.
|
||||
* @return \FetchingCoroutine<TReturn> New FetchingCoroutine instance.
|
||||
*/
|
||||
public function retryable(int $retries, bool $tallied_retries = true): \FetchingCoroutine {
|
||||
$this->consume();
|
||||
$coroutine = $this;
|
||||
$retryable = function () use ($retries, $coroutine, $tallied_retries) {
|
||||
processing_new_coroutine:
|
||||
while ($coroutine->valid()) {
|
||||
$retries_current = $retries;
|
||||
$id = $coroutine->current_key();
|
||||
$handle = $coroutine->current_request();
|
||||
$attempt_no = 1;
|
||||
do {
|
||||
if (!($attempt_handle = curl_copy_handle($handle))) {
|
||||
log_error("Failed to clone cURL handle");
|
||||
$coroutine->send(false);
|
||||
goto processing_new_coroutine;
|
||||
}
|
||||
|
||||
/** @var CurlHandle|false $response_handle */
|
||||
$response_handle = yield $id => $attempt_handle;
|
||||
$url = curl_getinfo($attempt_handle, CURLINFO_EFFECTIVE_URL);
|
||||
|
||||
if ($response_handle) {
|
||||
$retcode = curl_getinfo($response_handle, CURLINFO_HTTP_CODE);
|
||||
$url = curl_getinfo($response_handle, CURLINFO_EFFECTIVE_URL) ?? $url;
|
||||
log_debug("Attempt #$attempt_no for $url returned code $retcode.");
|
||||
$coroutine->send($response_handle);
|
||||
goto processing_new_coroutine;
|
||||
}
|
||||
|
||||
log_debug("Attempt #$attempt_no for $url failed or was rejected upstream.");
|
||||
|
||||
$attempt_no++;
|
||||
} while ($retries_current-- > 0);
|
||||
|
||||
// failed to fetch handle
|
||||
$coroutine->send(false);
|
||||
|
||||
// decrease the remaining retries
|
||||
if ($tallied_retries) {
|
||||
$retries = $retries_current;
|
||||
}
|
||||
}
|
||||
return $coroutine->return_value();
|
||||
};
|
||||
return $this->project_coroutine_parameters(new FetchingCoroutine($retryable()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies the current coroutine to attempt HTTPS->HTTP downgrade after failure.
|
||||
* Consumes current coroutine.
|
||||
* @param bool $did_downgrade Set to true if a downgrade to HTTP has taken place.
|
||||
* @return \FetchingCoroutine<TReturn> New FetchingCoroutine instance.
|
||||
*/
|
||||
public function downgradeable(mixed &$did_downgrade = NULL): \FetchingCoroutine {
|
||||
$this->consume();
|
||||
$coroutine = $this;
|
||||
$has_downgrade_ref = func_num_args() >= 1;
|
||||
if ($has_downgrade_ref) $did_downgrade = false;
|
||||
$downgradeable = function () use ($coroutine, &$did_downgrade, $has_downgrade_ref) {
|
||||
while ($coroutine->valid()) {
|
||||
$id = $coroutine->current_key();
|
||||
$handle = $coroutine->current_request();
|
||||
$handle_downgraded = curl_handle_downgrade($handle);
|
||||
// Try HTTPS first
|
||||
if ($handle_downgraded) {
|
||||
// Skip to next handle on success
|
||||
if ($coroutine->send(yield $id => $handle)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($has_downgrade_ref) $did_downgrade = true;
|
||||
$handle = $handle_downgraded;
|
||||
}
|
||||
|
||||
// Use HTTP
|
||||
$coroutine->send(yield $id => $handle);
|
||||
}
|
||||
return $coroutine->return_value();
|
||||
};
|
||||
return $this->project_coroutine_parameters(new FetchingCoroutine($downgradeable()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign non-generator parameters to given FetchingCoroutine.
|
||||
*/
|
||||
private function project_coroutine_parameters(\FetchingCoroutine $coroutine): \FetchingCoroutine {
|
||||
return $coroutine->set_response_filter($this->response_filter);
|
||||
}
|
||||
|
||||
private function is_valid_response(CurlHandle $handle) {
|
||||
$response_filter = $this->response_filter;
|
||||
return $response_filter($handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the key of the handle yielded at this point in the coroutine, if applicable.
|
||||
*/
|
||||
public function current_key() {
|
||||
return $this->generator->key();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cURL handle yielded at this point in the coroutine, if applicable.
|
||||
*/
|
||||
public function current_request(): CurlHandle|null {
|
||||
return $this->generator->current();
|
||||
}
|
||||
|
||||
private function valid(): bool {
|
||||
return $this->generator->valid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the current coroutine. Consumes coroutine.
|
||||
* @return \Generator<int,CurlHandle,CurlHandle|false,TReturn>
|
||||
*/
|
||||
public function run() {
|
||||
$this->consume();
|
||||
// passthrough
|
||||
return yield from $this->generator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the return value of the wrapped generator object once finished.
|
||||
* @return TReturn
|
||||
*/
|
||||
public function return_value(): mixed {
|
||||
return $this->generator->getReturn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Step coroutine until next yield point or end.
|
||||
* Coroutine must not be consumed by any transformations.
|
||||
* @param CurlHandle|false $response
|
||||
* Processed handle corresponding to yielded handle or false in case of failure.
|
||||
*/
|
||||
public function advance(CurlHandle|false $response_handle): bool {
|
||||
$this->assert_not_consumed();
|
||||
return $this->send($response_handle);
|
||||
}
|
||||
|
||||
private function send(CurlHandle|false $handle): bool {
|
||||
if ($handle && $this->is_valid_response($handle)) {
|
||||
$this->generator->send($handle);
|
||||
return true;
|
||||
} else {
|
||||
$this->generator->send(false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FetchingCoroutineRunner {
|
||||
/**
|
||||
* Collection of enroled transfers.
|
||||
*/
|
||||
private CurlMultiHandle $transfers;
|
||||
|
||||
/**
|
||||
* Coroutines executed by runner.
|
||||
* @var \FetchingCoroutine[] $coroutines
|
||||
*/
|
||||
private array $coroutines;
|
||||
|
||||
/**
|
||||
* Create new FetchingCoroutineRunner instance with the given coroutines.
|
||||
* @param \FetchingCoroutine[] $coroutines Coroutines to run in parallel.
|
||||
*/
|
||||
public function __construct(array $coroutines = []) {
|
||||
$this->coroutines = $coroutines;
|
||||
|
||||
$this->initialize_coroutines();
|
||||
}
|
||||
|
||||
/**
|
||||
* Launches all coroutines in parallel.
|
||||
* @return int CURLM_* status.
|
||||
*/
|
||||
public function run_all(): int {
|
||||
do {
|
||||
$curlm_status = curl_multi_exec($this->transfers, $curlm_active_transfer);
|
||||
if ($curlm_active_transfer) {
|
||||
// Block 1 second for pending transfers
|
||||
curl_multi_select($this->transfers, timeout: 1.0);
|
||||
// curl_multi_select($transfers, timeout: 6.0);
|
||||
}
|
||||
$this->process_curl_activity();
|
||||
} while ($curlm_active_transfer && $curlm_status == CURLM_OK);
|
||||
|
||||
return $curlm_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enrol initial transfers from all coroutines.
|
||||
*/
|
||||
private function initialize_coroutines() {
|
||||
$this->transfers = curl_multi_init();
|
||||
|
||||
foreach ($this->coroutines as $id => $coroutine) {
|
||||
$this->poll_coroutine_for_transfer($id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enrol latest transfer from coroutine with given id.
|
||||
*/
|
||||
private function poll_coroutine_for_transfer(int $id) {
|
||||
$coroutine = $this->coroutines[$id];
|
||||
$handle = $coroutine->current_request();
|
||||
if (!$handle) return;
|
||||
curl_setopt($handle, CURLOPT_PRIVATE, $id);
|
||||
curl_multi_add_handle($this->transfers, $handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Respond to new activity on enroled transfers.
|
||||
*/
|
||||
private function process_curl_activity() {
|
||||
while (false !== ($info = curl_multi_info_read($this->transfers))) {
|
||||
if ($info['msg'] != CURLMSG_DONE) continue;
|
||||
/**
|
||||
* @var \CurlHandle $handle
|
||||
*/
|
||||
$handle = $info['handle'];
|
||||
curl_multi_remove_handle($this->transfers, $handle);
|
||||
$coroutine_id = curl_getinfo($handle, CURLINFO_PRIVATE);
|
||||
if (!isset($this->coroutines[$coroutine_id])) {
|
||||
throw new Error("Invalid coroutine ID: " + $coroutine_id);
|
||||
}
|
||||
$this->coroutines[$coroutine_id]->advance($handle);
|
||||
$this->poll_coroutine_for_transfer($coroutine_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
include_once "$PROJECT_ROOT/php/utils/logging.php";
|
||||
|
||||
// Read the -v|--verbose option increasing logging verbosity to debug.
|
||||
$options = getopt("vn", ["verbose", "fast", "no-color", "dry-run"]);
|
||||
if (isset($options["v"]) or isset($options["verbose"])) {
|
||||
$LOGGING_VERBOSITY = LoggingVerbosity::Debug;
|
||||
}
|
||||
|
||||
$FAST_FETCH_MODE = (isset($options["fast"]));
|
||||
|
||||
$DO_DRY_RUN = (isset($options["n"]) || isset($options["dry-run"]));
|
||||
|
||||
if (isset($options["no-color"])) {
|
||||
LoggingVerbosity::$showColor = false;
|
||||
}
|
||||
|
||||
// set timeout for file_get_contents()
|
||||
ini_set('default_socket_timeout', 6); // in seconds, default is 60
|
||||
|
||||
// curl timeout in milliseconds
|
||||
|
||||
// max time for initiation of the connection
|
||||
$CURL_CONNECT_TIMEOUT_MS = 2000;
|
||||
|
||||
// max time for each connection (incl. transfer)
|
||||
$CURL_TIMEOUT_MS = $FAST_FETCH_MODE ? 3000 : 9000;
|
||||
|
||||
// delay between retries in miliseconds
|
||||
$CURL_RETRY_SLEEP = 2000;
|
||||
?>
|
Loading…
Reference in New Issue