This commit is contained in:
Daniil Gentili 2019-09-02 15:30:29 +02:00
parent 0f7ffc2da7
commit d1bbc86d21
11 changed files with 104 additions and 44 deletions

View File

@ -266,6 +266,36 @@ class Connection extends Session
return $this->ctx;
}
/**
* Check if is an HTTP connection.
*
* @return boolean
*/
public function isHttp(): bool
{
return \in_array($this->ctx->getStreamName(), [HttpStream::getName(), HttpsStream::getName()]);
}
/**
* Check if is a media connection
*
* @return boolean
*/
public function isMedia(): bool
{
return $this->ctx->isMedia();
}
/**
* Check if is a CDN connection
*
* @return boolean
*/
public function isCDN(): bool
{
return $this->ctx->isCDN();
}
/**
* Connects to a telegram DC using the specified protocol, proxy and connection parameters.
*

View File

@ -41,9 +41,9 @@ use Amp\Socket\ClientTlsContext;
use Amp\Socket\ConnectException;
use Amp\Socket\Socket;
use Amp\TimeoutException;
use danog\MadelineProto\AuthKey\AuthKey;
use danog\MadelineProto\AuthKey\PermAuthKey;
use danog\MadelineProto\AuthKey\TempAuthKey;
use danog\MadelineProto\MTProto\AuthKey;
use danog\MadelineProto\MTProto\PermAuthKey;
use danog\MadelineProto\MTProto\TempAuthKey;
use danog\MadelineProto\Stream\Common\BufferedRawStream;
use danog\MadelineProto\Stream\ConnectionContext;
use danog\MadelineProto\Stream\MTProtoTransport\AbridgedStream;

View File

@ -18,9 +18,10 @@
namespace danog\MadelineProto;
use danog\MadelineProto\AuthKey\AuthKey;
use danog\MadelineProto\AuthKey\PermAuthKey;
use danog\MadelineProto\AuthKey\TempAuthKey;
use danog\MadelineProto\Loop\Generic\PeriodicLoop;
use danog\MadelineProto\MTProto\AuthKey;
use danog\MadelineProto\MTProto\PermAuthKey;
use danog\MadelineProto\MTProto\TempAuthKey;
use danog\MadelineProto\Stream\ConnectionContext;
use danog\MadelineProto\Stream\MTProtoTransport\HttpsStream;
use danog\MadelineProto\Stream\MTProtoTransport\HttpStream;
@ -229,7 +230,11 @@ class DataCenterConnection implements JsonSerializable
*/
public function authorized(bool $authorized)
{
$this->getTempAuthKey()->authorized($authorized);
if ($authorized) {
$this->getTempAuthKey()->authorized($authorized);
} else if ($this->hasTempAuthKey()) {
$this->getTempAuthKey()->authorized($authorized);
}
}
/**
@ -297,7 +302,7 @@ class DataCenterConnection implements JsonSerializable
if ($count > 1) {
if (!$this->robinLoop) {
$this->robinLoop = new PeriodicLoop($this, [$this, 'even'], "Robin loop DC {$this->datacenter}", 10);
$this->robinLoop = new PeriodicLoop($this->API, [$this, 'even'], "Robin loop DC {$this->datacenter}", 10);
}
$this->robinLoop->start();
}
@ -363,7 +368,7 @@ class DataCenterConnection implements JsonSerializable
*/
public function getConnection(): Connection
{
if (\count($this->availableConnections) === 1) {
if (\count($this->availableConnections) <= 1) {
return $this->connections[0];
}
\max($this->availableConnections);
@ -440,11 +445,31 @@ class DataCenterConnection implements JsonSerializable
*
* @return boolean
*/
public function isHttp()
public function isHttp(): bool
{
return \in_array($this->ctx->getStreamName(), [HttpStream::getName(), HttpsStream::getName()]);
}
/**
* Check if is a media connection
*
* @return boolean
*/
public function isMedia(): bool
{
return $this->ctx->isMedia();
}
/**
* Check if is a CDN connection
*
* @return boolean
*/
public function isCDN(): bool
{
return $this->ctx->isCDN();
}
/**
* Get DC-specific settings
*

View File

@ -19,6 +19,7 @@
namespace danog\MadelineProto\Loop\Generic;
use danog\MadelineProto\Loop\Impl\ResumableSignalLoop;
use danog\MadelineProto\MTProto;
/**
* Periodic loop.
@ -30,14 +31,16 @@ class PeriodicLoop extends ResumableSignalLoop
private $callback;
private $name;
private $timeout;
/**
* Constructor.
*
*
* @param \danog\MadelineProto\MTProto $API Instance of MTProto class
* @param callable $callback Callback to call
* @param string $name Loop name
* @param int $timeout Loop timeout
*/
public function __construct($API, $callback, $name, $timeout)
public function __construct(MTProto $API, $callback, string $name, $timeout)
{
$this->API = $API;
$this->callback = $callback;

View File

@ -99,7 +99,7 @@ trait AckHandler
&& $this->shared->hasTempAuthKey() === !$this->outgoing_messages[$message_id]['unencrypted']
&& $this->outgoing_messages[$message_id]['_'] !== 'msgs_state_req'
) {
if ($pfs && !$this->shared->getTempAuthKey()->bound() && $this->outgoing_messages[$message_id]['_'] !== 'auth.bindTempAuthKey') {
if ($pfs && !$this->shared->getTempAuthKey()->isBound() && $this->outgoing_messages[$message_id]['_'] !== 'auth.bindTempAuthKey') {
continue;
}
@ -128,7 +128,7 @@ trait AckHandler
&& $this->shared->hasTempAuthKey() === !$this->outgoing_messages[$message_id]['unencrypted']
&& $this->outgoing_messages[$message_id]['_'] !== 'msgs_state_req'
) {
if ($pfs && !$this->shared->getTempAuthKey()->bound() && $this->outgoing_messages[$message_id]['_'] !== 'auth.bindTempAuthKey') {
if ($pfs && !$this->shared->getTempAuthKey()->isBound() && $this->outgoing_messages[$message_id]['_'] !== 'auth.bindTempAuthKey') {
continue;
}

View File

@ -149,7 +149,7 @@ trait CallHandler
if (isset($args['multiple'])) {
$aargs['multiple'] = true;
}
if (isset($args['message']) && \is_string($args['message']) && \mb_strlen($args['message'], 'UTF-8') > $this->API->config['message_length_max'] && \mb_strlen((yield $this->parse_mode_async($args))['message'], 'UTF-8') > $this->API->config['message_length_max']) {
if (isset($args['message']) && \is_string($args['message']) && \mb_strlen($args['message'], 'UTF-8') > (yield $this->API->get_config_async())['message_length_max'] && \mb_strlen((yield $this->parse_mode_async($args))['message'], 'UTF-8') > (yield $this->API->get_config_async())['message_length_max']) {
$args = yield $this->split_to_chunks_async($args);
$promises = [];
$aargs['queue'] = $method;

View File

@ -20,6 +20,7 @@
namespace danog\MadelineProto\MTProtoSession;
use Amp\Loop;
use danog\MadelineProto\MTProto;
/**
* Manages responses.
@ -118,8 +119,8 @@ trait ResponseHandler
$this->ack_incoming_message_id($current_msg_id);
// Acknowledge that I received the server's response
if ($this->authorized === self::LOGGED_IN && !$this->initing_authorization && $this->API->datacenter->getDataCenterConnection($this->API->datacenter->curdc)->hasTempAuthKey() && isset($this->updaters[false])) {
$this->updaters[false]->resumeDefer();
if ($this->API->authorized === MTProto::LOGGED_IN && !$this->API->isInitingAuthorization() && $this->API->datacenter->getDataCenterConnection($this->API->datacenter->curdc)->hasTempAuthKey() && isset($this->API->updaters[false])) {
$this->API->updaters[false]->resumeDefer();
}
unset($this->incoming_messages[$current_msg_id]['content']);
@ -190,7 +191,7 @@ trait ResponseHandler
*$this->got_response_for_outgoing_message_id($msg_id);
*}
*/
foreach (self::MSGS_INFO_FLAGS as $flag => $description) {
foreach (MTProto::MSGS_INFO_FLAGS as $flag => $description) {
if (($info & $flag) !== 0) {
$status .= $description;
}
@ -263,7 +264,7 @@ trait ResponseHandler
case 'Updates':
unset($this->new_incoming[$current_msg_id]);
if (\strpos($this->datacenter, 'cdn') === false) {
if (!$this->isCdn()) {
$this->callForkDefer($this->API->handle_updates_async($this->incoming_messages[$current_msg_id]['content']));
}
@ -408,9 +409,9 @@ trait ResponseHandler
$this->logger->logger($response['error_message'], \danog\MadelineProto\Logger::FATAL_ERROR);
foreach ($this->API->datacenter->getDataCenterConnections() as $socket) {
$socket->authKey(null, true);
$socket->authKey(null, false);
$socket->authorized(false);
$socket->setTempAuthKey(null);
$socket->setPermAuthKey(null);
$socket->resetSession();
}
@ -435,7 +436,7 @@ trait ResponseHandler
return;
case 'AUTH_KEY_UNREGISTERED':
case 'AUTH_KEY_INVALID':
if ($this->authorized !== self::LOGGED_IN) {
if ($this->API->authorized !== MTProto::LOGGED_IN) {
$this->got_response_for_outgoing_message_id($request_id);
$this->callFork((function () use (&$request, &$response) {
@ -452,14 +453,14 @@ trait ResponseHandler
$this->logger->logger('Auth key not registered, resetting temporary and permanent auth keys...', \danog\MadelineProto\Logger::ERROR);
if ($this->API->authorized_dc === $this->datacenter && $this->authorized === self::LOGGED_IN) {
if ($this->API->authorized_dc === $this->datacenter && $this->API->authorized === MTProto::LOGGED_IN) {
$this->got_response_for_outgoing_message_id($request_id);
$this->logger->logger('Permanent auth key was main authorized key, logging out...', \danog\MadelineProto\Logger::FATAL_ERROR);
foreach ($this->API->datacenter->getDataCenterConnections() as $socket) {
$socket->authKey(null, true);
$socket->authKey(null, false);
$socket->authorized(false);
$socket->setTempAuthKey(null);
$socket->setPermAuthKey(null);
}
$this->logger->logger('!!!!!!! WARNING !!!!!!!', \danog\MadelineProto\Logger::FATAL_ERROR);
@ -531,7 +532,7 @@ trait ResponseHandler
break;
case 'bad_server_salt':
case 'bad_msg_notification':
$this->logger->logger('Received bad_msg_notification: '.self::BAD_MSG_ERROR_CODES[$response['error_code']], \danog\MadelineProto\Logger::WARNING);
$this->logger->logger('Received bad_msg_notification: '.MTProto::BAD_MSG_ERROR_CODES[$response['error_code']], \danog\MadelineProto\Logger::WARNING);
switch ($response['error_code']) {
case 48:
$this->getTempAuthKey()->setServerSalt($response['new_server_salt']);
@ -552,7 +553,7 @@ trait ResponseHandler
return;
}
$this->got_response_for_outgoing_message_id($request_id);
$this->handle_reject($request, new \danog\MadelineProto\RPCErrorException('Received bad_msg_notification: '.self::BAD_MSG_ERROR_CODES[$response['error_code']], $response['error_code'], isset($request['_']) ? $request['_'] : ''));
$this->handle_reject($request, new \danog\MadelineProto\RPCErrorException('Received bad_msg_notification: '.MTProto::BAD_MSG_ERROR_CODES[$response['error_code']], $response['error_code'], isset($request['_']) ? $request['_'] : ''));
return;
}
@ -568,7 +569,7 @@ trait ResponseHandler
return;
}
$botAPI = isset($request['botAPI']) && $request['botAPI'];
if (isset($response['_']) && \strpos($this->datacenter, 'cdn') === false && $this->API->constructors->find_by_predicate($response['_'])['type'] === 'Updates') {
if (isset($response['_']) && !$this->isCdn() && $this->API->constructors->find_by_predicate($response['_'])['type'] === 'Updates') {
$response['request'] = $request;
$this->callForkDefer($this->API->handle_updates_async($response));
}

View File

@ -20,9 +20,9 @@
namespace danog\MadelineProto\MTProtoTools;
use Amp\Artax\Request;
use danog\MadelineProto\AuthKey\AuthKey;
use danog\MadelineProto\AuthKey\PermAuthKey;
use danog\MadelineProto\AuthKey\TempAuthKey;
use danog\MadelineProto\MTProto\AuthKey;
use danog\MadelineProto\MTProto\PermAuthKey;
use danog\MadelineProto\MTProto\TempAuthKey;
use danog\MadelineProto\DataCenterConnection;
use phpseclib\Math\BigInteger;
@ -64,9 +64,9 @@ trait AuthKeyHandler
*/
public function create_auth_key_async(int $expires_in, string $datacenter): \Generator
{
$cdn = \strpos($datacenter, 'cdn');
$req_pq = $cdn ? 'req_pq' : 'req_pq_multi';
$connection = $this->datacenter->getAuthConnection($datacenter);
$cdn = $connection->isCDN();
$req_pq = $cdn ? 'req_pq' : 'req_pq_multi';
for ($retry_id_total = 1; $retry_id_total <= $this->settings['max_tries']['authorization']; $retry_id_total++) {
try {
@ -430,7 +430,7 @@ trait AuthKeyHandler
$this->logger->logger('An exception occurred while generating the authorization key: '.$e.PHP_EOL.' Retrying (try number '.$retry_id_total.')...', \danog\MadelineProto\Logger::WARNING);
}
}
if (\strpos($datacenter, 'cdn') === false) {
if (!$cdn) {
throw new \danog\MadelineProto\SecurityException('Auth Failed');
}
}
@ -653,7 +653,7 @@ trait AuthKeyHandler
$dcs = [];
$postpone = [];
foreach ($this->datacenter->getDataCenterConnections() as $id => $socket) {
if (\strpos($id, 'media') !== false) {
if ($socket->isMedia()) {
$oid = \intval($id);
if (isset($dcs[$oid])) {
$postpone[$id] = $socket;
@ -711,13 +711,13 @@ trait AuthKeyHandler
$connection->session_in_seq_no = 0;
$connection->session_out_seq_no = 0;
}
$cdn = \strpos($id, 'cdn');
$media = \strpos($id, 'media');
$cdn = $socket->isCDN();
$media = $socket->isMedia();
if (!$socket->hasTempAuthKey() || !$socket->hasPermAuthKey()) {
if (!$socket->hasPermAuthKey() && !$cdn && !$media) {
$this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['gen_perm_auth_key'], $id), \danog\MadelineProto\Logger::NOTICE);
$socket->setPermAuthKey(yield $this->create_auth_key_async(-1, $id));
$socket->authorized(false);
//$socket->authorized(false);
}
if ($media) {
$socket->link(\intval($id));
@ -778,7 +778,7 @@ trait AuthKeyHandler
if ($this->authorized_dc !== -1 && $authorized_dc_id !== $this->authorized_dc) {
continue;
}
if ($authorized_socket->hasTempAuthKey() && $authorized_socket->hasPermAuthKey() && $authorized_socket->isAuthorized() && $this->authorized === self::LOGGED_IN && !$socket->isAuthorized() && \strpos($authorized_dc_id, 'cdn') === false) {
if ($authorized_socket->hasTempAuthKey() && $authorized_socket->hasPermAuthKey() && $authorized_socket->isAuthorized() && $this->authorized === self::LOGGED_IN && !$socket->isAuthorized() && !$authorized_socket->isCDN()) {
try {
$this->logger->logger('Trying to copy authorization from dc '.$authorized_dc_id.' to dc '.$id);
$exported_authorization = yield $this->method_call_async_read('auth.exportAuthorization', ['dc_id' => \preg_replace('|_.*|', '', $id)], ['datacenter' => $authorized_dc_id]);

View File

@ -19,6 +19,8 @@
namespace danog\MadelineProto\MTProtoTools;
use Amp\Promise;
/**
* Manages method and object calls.
*/

View File

@ -785,7 +785,6 @@ trait TL
if (!isset($type['subtype'])) {
$type['subtype'] = '';
}
return $this->deserialize(gzdecode($this->deserialize($stream, ['type' => 'bytes'])), ['type' => '', 'connection' => $type['connection'], 'subtype' => $type['subtype']]);
}
if ($constructorData['type'] === 'Vector t') {
@ -849,8 +848,8 @@ trait TL
$arg['subtype'] = str_replace(['Vector<', '>'], '', $type['connection']->outgoing_messages[$x['req_msg_id']]['type']);
}
}
if (isset($type['datacenter'])) {
$arg['datacenter'] = $type['datacenter'];
if (isset($type['connection'])) {
$arg['connection'] = $type['connection'];
}
$x[$arg['name']] = $this->deserialize($stream, $arg);
if ($arg['name'] === 'random_bytes') {

View File

@ -19,7 +19,7 @@
namespace danog\MadelineProto\Wrappers;
use danog\MadelineProto\AuthKey\PermAuthKey;
use danog\MadelineProto\MTProto\PermAuthKey;
use danog\MadelineProto\MTProtoTools\PasswordCalculator;
/**