1
0
mirror of https://github.com/danog/MadelineProto.git synced 2024-11-30 09:58:59 +01:00

Async magnaluna and more async bugfixes (#667)

This commit is contained in:
Daniil Gentili 2019-07-18 23:48:35 +02:00 committed by GitHub
parent 005d762a8f
commit a951ae380f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 267 additions and 214 deletions

2
docs

@ -1 +1 @@
Subproject commit ddb2e4f76938b69ceac6e4615901c642accae1ef
Subproject commit dc05dc5cebfcec90ac7851928c522a4d635dbab6

371
magna.php
View File

@ -38,8 +38,117 @@ $MadelineProto->inputEncryptedFileVideo = $MadelineProto->upload_encrypted('test
$MadelineProto->inputEncryptedFileAudio = $MadelineProto->upload_encrypted('tests/mosconi.mp3');
}*/
use danog\MadelineProto\Loop\Impl\ResumableSignalLoop;
class MessageLoop extends ResumableSignalLoop
{
const INTERVAL = 10;
private $timeout;
private $call;
public function __construct($API, $call, $timeout = self::INTERVAL)
{
$this->API = $API;
$this->call = $call;
$this->timeout = $timeout;
}
public function loop()
{
$MadelineProto = $this->API;
$logger = &$MadelineProto->logger;
while (true) {
$result = yield $this->waitSignal($this->pause($this->timeout));
if ($result) {
$logger->logger("Got signal in $this, exiting");
return;
}
try {
yield $MadelineProto->messages->editMessage(['id' => $this->call->mId, 'peer' => $this->call->getOtherID(), 'message' => 'Total running calls: '.count($MadelineProto->getEventHandler()->calls).PHP_EOL.PHP_EOL.$this->call->getDebugString()]);
} catch (\danog\MadelineProto\RPCErrorException $e) {
$MadelineProto->logger($e);
}
}
}
public function __toString(): string
{
return "VoIP message loop ".$this->call->getOtherId();
}
}
class StatusLoop extends ResumableSignalLoop
{
const INTERVAL = 2;
private $timeout;
private $call;
public function __construct($API, $call, $timeout = self::INTERVAL)
{
$this->API = $API;
$this->call = $call;
$this->timeout = $timeout;
}
public function loop()
{
$MadelineProto = $this->API;
$logger = &$MadelineProto->logger;
$call = $this->call;
while (true) {
$result = yield $this->waitSignal($this->pause($this->timeout));
if ($result) {
$logger->logger("Got signal in $this, exiting");
return;
}
if ($call->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
try {
/*yield $this->messages->sendMedia([
'reply_to_msg_id' => $this->times[$call->getOtherID()][1],
'peer' => $call->getOtherID(), 'message' => 'Call statistics by @magnaluna',
'media' => [
'_' => 'inputMediaUploadedDocument',
'file' => "/tmp/stats".$call->getCallID()['id'].".txt",
'attributes' => [
['_' => 'documentAttributeFilename', 'file_name' => "stats".$call->getCallID()['id'].".txt"]
]
],
]);*/
yield $MadelineProto->messages->sendMedia([
'reply_to_msg_id' => $this->call->mId,
'peer' => $call->getOtherID(), 'message' => 'Debug info by @magnaluna',
'media' => [
'_' => 'inputMediaUploadedDocument',
'file' => '/tmp/logs'.$call->getCallID()['id'].'.log',
'attributes' => [
['_' => 'documentAttributeFilename', 'file_name' => 'logs'.$call->getCallID()['id'].'.log'],
],
],
]);
} catch (\danog\MadelineProto\Exception $e) {
$MadelineProto->logger($e);
} catch (\danog\MadelineProto\RPCErrorException $e) {
$MadelineProto->logger($e);
} catch (\danog\MadelineProto\Exception $e) {
$MadelineProto->logger($e);
}
@unlink('/tmp/logs'.$call->getCallID()['id'].'.log');
@unlink('/tmp/stats'.$call->getCallID()['id'].'.txt');
$MadelineProto->getEventHandler()->cleanUpCall($call->getOtherID());
return;
}
}
}
public function __toString(): string
{
return "VoIP status loop ".$this->call->getOtherId();
}
}
class EventHandler extends \danog\MadelineProto\EventHandler
{
const ADMINS = [101374607]; // @danogentili, creator of MadelineProto
private $messageLoops = [];
private $statusLoops = [];
private $programmed_call;
private $my_users;
public function configureCall($call)
{
include 'songs.php';
@ -50,16 +159,74 @@ class EventHandler extends \danog\MadelineProto\EventHandler
//$call->configuration["stats_dump_file_path"] = "/tmp/stats".$call->getCallID()['id'].".txt"; // Default is /dev/null
$call->parseConfig();
$call->playOnHold($songs);
//$this->messages->sendMessage(['message' => var_export($call->configuration, true), 'peer' => $call->getOtherID()]);
if ($call->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_INCOMING) {
if ($call->accept() === false) {
$MadelineProto->logger('DID NOT ACCEPT A CALL');
}
}
if ($call->getCallState() !== \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
$this->calls[$call->getOtherID()] = $call;
try {
$call->mId = yield $this->messages->sendMessage(['peer' => $call->getOtherID(), 'message' => 'Total running calls: '.count($this->calls).PHP_EOL.PHP_EOL.$call->getDebugString()])['id'];
} catch (\Throwable $e) {
$this->logger($e);
}
$this->messageLoops[$call->getOtherID()] = new MessageLoop($this, $call);
$this->statusLoops[$call->getOtherID()] = new StatusLoop($this, $call);
$this->messageLoops[$call->getOtherID()]->start();
$this->statusLoops[$call->getOtherID()]->start();
}
//yield $this->messages->sendMessage(['message' => var_export($call->configuration, true), 'peer' => $call->getOtherID()]);
}
public function cleanUpCall($user)
{
if (isset($this->calls[$user])) {
unset($this->calls[$user]);
}
if (isset($this->messageLoops[$user])) {
$this->messageLoops[$user]->signal(true);
unset($this->messageLoops[$user]);
}
if (isset($this->statusLoops[$user])) {
$this->statusLoops[$user]->signal(true);
unset($this->statusLoops[$user]);
}
}
public function makeCall($user)
{
try {
if (isset($this->calls[$user])) {
if ($this->calls[$user]->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
yield $this->cleanUpCall($user);
} else {
yield $this->messages->sendMessage(['peer' => $user, 'message' => "I'm already in a call with you!"]);
return;
}
}
yield $this->configureCall(yield $this->requestCall($user));
} catch (\danog\MadelineProto\RPCErrorException $e) {
try {
if ($e->rpc === 'USER_PRIVACY_RESTRICTED') {
$e = 'Please disable call privacy settings to make me call you';
}/* elseif (strpos($e->rpc, 'FLOOD_WAIT_') === 0) {
$t = str_replace('FLOOD_WAIT_', '', $e->rpc);
$this->programmed_call[] = [$user, time() + 1 + $t];
$e = "I'll call you back in $t seconds.\nYou can also call me right now.";
}*/
yield $this->messages->sendMessage(['peer' => $user, 'message' => (string) $e]);
} catch (\danog\MadelineProto\RPCErrorException $e) {
}
} catch (\Throwable $e) {
yield $this->messages->sendMessage(['peer' => $user, 'message' => (string) $e]);
}
}
public function handleMessage($chat_id, $from_id, $message)
{
try {
if (!isset($this->my_users[$from_id]) || $message === '/start') {
$this->my_users[$from_id] = true;
$message = '/call';
$this->messages->sendMessage(['no_webpage' => true, 'peer' => $chat_id, 'message' => "Hi, I'm @magnaluna the webradio.
yield $this->messages->sendMessage(['no_webpage' => true, 'peer' => $chat_id, 'message' => "Hi, I'm @magnaluna the webradio.
Call _me_ to listen to some **awesome** music, or send /call to make _me_ call _you_ (don't forget to disable call privacy settings!).
@ -80,50 +247,48 @@ Source code: https://github.com/danog/MadelineProto
Propic art by @magnaluna on [deviantart](https://magnaluna.deviantart.com).", 'parse_mode' => 'Markdown']);
}
if (!isset($this->calls[$from_id]) && $message === '/call') {
$call = $this->request_call($from_id);
$this->configureCall($call);
if ($call->getCallState() !== \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
$this->calls[$call->getOtherID()] = $call;
$this->times[$call->getOtherID()] = [time(), $this->messages->sendMessage(['peer' => $call->getOtherID(), 'message' => 'Total running calls: '.count($this->calls).PHP_EOL.PHP_EOL.$call->getDebugString()])['id']];
}
yield $this->makeCall($from_id);
}
if (strpos($message, '/program') === 0) {
$time = strtotime(str_replace('/program ', '', $message));
if ($time === false) {
$this->messages->sendMessage(['peer' => $chat_id, 'message' => 'Invalid time provided']);
yield $this->messages->sendMessage(['peer' => $chat_id, 'message' => 'Invalid time provided']);
} else if ($time - time() <= 0) {
yield $this->messages->sendMessage(['peer' => $chat_id, 'message' => 'Invalid time provided']);
} else {
yield $this->messages->sendMessage(['peer' => $chat_id, 'message' => 'OK']);
$this->programmed_call[] = [$from_id, $time];
$this->messages->sendMessage(['peer' => $chat_id, 'message' => 'OK']);
$key = count($this->programmed_call) - 1;
yield $this->sleep($time - time());
yield $this->makeCall($from_id);
unset($this->programmed_call[$key]);
}
}
if ($message === '/broadcast' && $from_id === 101374607) {
if ($message === '/broadcast' && in_array(self::ADMINS, $from_id)) {
$time = time() + 100;
$message = explode(' ', $message, 2);
unset($message[0]);
$message = implode(' ', $message);
foreach ($this->get_dialogs() as $peer) {
$this->times_messages[] = [$peer, $time, $message];
if (isset($peer['user_id'])) {
$this->programmed_call[] = [$peer['user_id'], $time];
}
$time += 30;
$params = ['multiple' => true];
foreach (yield $this->get_dialogs() as $peer) {
$params []= ['peer' => $peer, 'message' => $message];
}
yield $this->messages->sendMessage($params);
}
} catch (\danog\MadelineProto\RPCErrorException $e) {
try {
if ($e->rpc === 'USER_PRIVACY_RESTRICTED') {
$e = 'Please disable call privacy settings to make me call you';
} elseif (strpos($e->rpc, 'FLOOD_WAIT_') === 0) {
} /*elseif (strpos($e->rpc, 'FLOOD_WAIT_') === 0) {
$t = str_replace('FLOOD_WAIT_', '', $e->rpc);
$this->programmed_call[] = [$from_id, time() + 1 + $t];
$e = "Too many people used the /call function. I'll call you back in $t seconds.\nYou can also call me right now.";
}
$this->messages->sendMessage(['peer' => $chat_id, 'message' => (string) $e]);
$e = "Too many people used the /call function. I'll be able to call you in $t seconds.\nYou can also call me right now";
}*/
yield $this->messages->sendMessage(['peer' => $chat_id, 'message' => (string) $e]);
} catch (\danog\MadelineProto\RPCErrorException $e) {
}
echo $e;
$this->logger($e);
} catch (\danog\MadelineProto\Exception $e) {
echo $e;
$this->logger($e);
}
}
@ -132,19 +297,19 @@ Propic art by @magnaluna on [deviantart](https://magnaluna.deviantart.com).", 'p
if ($update['message']['out'] || $update['message']['to_id']['_'] !== 'peerUser' || !isset($update['message']['from_id'])) {
return;
}
\danog\MadelineProto\Logger::log($update);
$chat_id = $from_id = $this->get_info($update)['bot_api_id'];
$message = isset($update['message']['message']) ? $update['message']['message'] : '';
$this->handleMessage($chat_id, $from_id, $message);
$this->logger->logger($update);
$chat_id = $from_id = yield $this->get_info($update)['bot_api_id'];
$message = $update['message']['message'] ?? '';
yield $this->handleMessage($chat_id, $from_id, $message);
}
public function onUpdateNewEncryptedMessage($update)
{
return;
$chat_id = $this->get_info($update)['InputEncryptedChat'];
$from_id = $this->get_secret_chat($chat_id)['user_id'];
$chat_id = yield $this->get_info($update)['InputEncryptedChat'];
$from_id = yield $this->get_secret_chat($chat_id)['user_id'];
$message = isset($update['message']['decrypted_message']['message']) ? $update['message']['decrypted_message']['message'] : '';
$this->handleMessage($chat_id, $from_id, $message);
yield $this->handleMessage($chat_id, $from_id, $message);
}
public function onUpdateEncryption($update)
@ -155,132 +320,45 @@ Propic art by @magnaluna on [deviantart](https://magnaluna.deviantart.com).", 'p
if ($update['chat']['_'] !== 'encryptedChat') {
return;
}
$chat_id = $this->get_info($update)['InputEncryptedChat'];
$from_id = $this->get_secret_chat($chat_id)['user_id'];
$chat_id = yield $this->get_info($update)['InputEncryptedChat'];
$from_id = yield $this->get_secret_chat($chat_id)['user_id'];
$message = '';
} catch (\danog\MadelineProto\Exception $e) {
return;
}
$this->handleMessage($chat_id, $from_id, $message);
yield $this->handleMessage($chat_id, $from_id, $message);
}
public function onUpdatePhoneCall($update)
{
if (is_object($update['phone_call']) && isset($update['phone_call']->madeline) && $update['phone_call']->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_INCOMING) {
$this->configureCall($update['phone_call']);
if ($update['phone_call']->accept() === false) {
echo 'DID NOT ACCEPT A CALL';
}
$this->calls[$update['phone_call']->getOtherID()] = $update['phone_call'];
try {
$this->times[$update['phone_call']->getOtherID()] = [time(), $this->messages->sendMessage(['peer' => $update['phone_call']->getOtherID(), 'message' => 'Total running calls: '.count($this->calls).PHP_EOL.PHP_EOL])['id']];
} catch (\danog\MadelineProto\RPCErrorException $e) {
}
yield $this->configureCall($update['phone_call']);
}
}
public function onAny($update)
/*public function onAny($update)
{
\danog\MadelineProto\Logger::log($update);
}
$this->logger->logger($update);
}*/
public function onLoop()
public function __construct($API)
{
foreach ($this->programmed_call as $key => $pair) {
list($user, $time) = $pair;
if ($time < time()) {
if (!isset($this->calls[$user])) {
try {
$call = $this->request_call($user);
$this->configureCall($call);
if ($call->getCallState() !== \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
$this->calls[$call->getOtherID()] = $call;
$this->times[$call->getOtherID()] = [time(), $this->messages->sendMessage(['peer' => $call->getOtherID(), 'message' => 'Total running calls: '.count($this->calls).PHP_EOL.PHP_EOL.$call->getDebugString()])['id']];
}
} catch (\danog\MadelineProto\RPCErrorException $e) {
try {
if ($e->rpc === 'USER_PRIVACY_RESTRICTED') {
$e = 'Please disable call privacy settings to make me call you';
} elseif (strpos($e->rpc, 'FLOOD_WAIT_') === 0) {
$t = str_replace('FLOOD_WAIT_', '', $e->rpc);
$this->programmed_call[] = [$user, time() + 1 + $t];
$e = "I'll call you back in $t seconds.\nYou can also call me right now.";
}
$this->messages->sendMessage(['peer' => $user, 'message' => (string) $e]);
} catch (\danog\MadelineProto\RPCErrorException $e) {
}
}
}
parent::__construct($API);
$this->programmed_call = [];
foreach ($this->programmed_call as $key => list($user, $time)) {
continue;
$sleepTime = $time <= time() ? 0 : $time - time();
$this->callFork((function () use ($sleepTime, $key, $user) {
yield $this->sleep($sleepTime);
yield $this->makeCall($user);
unset($this->programmed_call[$key]);
}
break;
}
foreach ($this->times_messages as $key => $pair) {
list($peer, $time, $message) = $pair;
if ($time < time()) {
try {
$this->messages->sendMessage(['peer' => $peer, 'message' => $message]);
} catch (\danog\MadelineProto\RPCErrorException $e) {
if (strpos($e->rpc, 'FLOOD_WAIT_') === 0) {
$t = str_replace('FLOOD_WAIT_', '', $e->rpc);
$this->times_messages[] = [$peer, time() + 1 + $t, $message];
}
echo $e;
}
unset($this->times_messages[$key]);
}
break;
}
\danog\MadelineProto\Logger::log(count($this->calls).' calls running!');
foreach ($this->calls as $key => $call) {
if ($call->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
try {
if (isset($this->times[$call->getOtherID()][1])) {
/*$this->messages->sendMedia([
'reply_to_msg_id' => $this->times[$call->getOtherID()][1],
'peer' => $call->getOtherID(), 'message' => 'Call statistics by @magnaluna',
'media' => [
'_' => 'inputMediaUploadedDocument',
'file' => "/tmp/stats".$call->getCallID()['id'].".txt",
'attributes' => [
['_' => 'documentAttributeFilename', 'file_name' => "stats".$call->getCallID()['id'].".txt"]
]
],
]);*/
$this->messages->sendMedia([
'reply_to_msg_id' => $this->times[$call->getOtherID()][1],
'peer' => $call->getOtherID(), 'message' => 'Debug info by @magnaluna',
'media' => [
'_' => 'inputMediaUploadedDocument',
'file' => '/tmp/logs'.$call->getCallID()['id'].'.log',
'attributes' => [
['_' => 'documentAttributeFilename', 'file_name' => 'logs'.$call->getCallID()['id'].'.log'],
],
],
]);
}
} catch (\danog\MadelineProto\Exception $e) {
echo $e;
} catch (\danog\MadelineProto\RPCErrorException $e) {
echo $e;
} catch (\danog\MadelineProto\Exception $e) {
echo $e;
}
@unlink('/tmp/logs'.$call->getCallID()['id'].'.log');
@unlink('/tmp/stats'.$call->getCallID()['id'].'.txt');
unset($this->calls[$key]);
} elseif (isset($this->times[$call->getOtherID()]) && $this->times[$call->getOtherID()][0] < time()) {
$this->times[$call->getOtherID()][0] += 30 + count($this->calls);
try {
$this->messages->editMessage(['id' => $this->times[$call->getOtherID()][1], 'peer' => $call->getOtherID(), 'message' => 'Total running calls: '.count($this->calls).PHP_EOL.PHP_EOL.$call->getDebugString()]);
} catch (\danog\MadelineProto\RPCErrorException $e) {
echo $e;
}
}
})());
}
}
public function __sleep()
{
return ['programmed_call', 'my_users'];
}
}
if (!class_exists('\\danog\\MadelineProto\\VoIPServerConfig')) {
@ -295,16 +373,11 @@ if (!class_exists('\\danog\\MadelineProto\\VoIPServerConfig')) {
'audio_congestion_window' => 4 * 1024,
]
);
$MadelineProto = new \danog\MadelineProto\API('session.madeline', ['secret_chats' => ['accept_chats' => false], 'logger' => ['logger' => 3, 'logger_level' => 5, 'logger_param' => getcwd().'/MadelineProto.log']]);
$MadelineProto = new \danog\MadelineProto\API('session.madeline', ['secret_chats' => ['accept_chats' => false], 'logger' => ['logger' => 3, 'logger_level' => 5, 'logger_param' => getcwd().'/MadelineProto.log'], 'updates' => ['getdifference_interval' => 10], 'serialization' => ['serialization_interval' => 30], 'flood_timeout' => ['wait_if_lt' => 86400]]);
$MadelineProto->start();
if (!isset($MadelineProto->programmed_call)) {
$MadelineProto->programmed_call = [];
}
foreach (['my_users', 'times', 'times_messages', 'calls'] as $key) {
if (!isset($MadelineProto->{$key})) {
$MadelineProto->{$key} = [];
foreach (['calls', 'programmed_call', 'my_users'] as $key) {
if (isset($MadelineProto->API->storage[$key])) {
unset($MadelineProto->API->storage[$key]);
}
}

View File

@ -137,10 +137,10 @@ class API extends APIFactory
$deferred->resolve();
yield $this->API->initAsync();
$this->APIFactory();
\danog\MadelineProto\Logger::log('Ping...', Logger::ULTRA_VERBOSE);
//\danog\MadelineProto\Logger::log('Ping...', Logger::ULTRA_VERBOSE);
$this->asyncInitPromise = null;
$pong = yield $this->ping(['ping_id' => 3], ['async' => true]);
\danog\MadelineProto\Logger::log('Pong: '.$pong['ping_id'], Logger::ULTRA_VERBOSE);
//$pong = yield $this->ping(['ping_id' => 3], ['async' => true]);
//\danog\MadelineProto\Logger::log('Pong: '.$pong['ping_id'], Logger::ULTRA_VERBOSE);
\danog\MadelineProto\Logger::log(\danog\MadelineProto\Lang::$current_lang['madelineproto_ready'], Logger::NOTICE);
return;
@ -162,9 +162,9 @@ class API extends APIFactory
yield $this->API->initAsync();
$this->APIFactory();
$this->asyncInitPromise = null;
\danog\MadelineProto\Logger::log('Ping...', Logger::ULTRA_VERBOSE);
$pong = yield $this->ping(['ping_id' => 3], ['async' => true]);
\danog\MadelineProto\Logger::log('Pong: '.$pong['ping_id'], Logger::ULTRA_VERBOSE);
//\danog\MadelineProto\Logger::log('Ping...', Logger::ULTRA_VERBOSE);
//$pong = yield $this->ping(['ping_id' => 3], ['async' => true]);
//\danog\MadelineProto\Logger::log('Pong: '.$pong['ping_id'], Logger::ULTRA_VERBOSE);
\danog\MadelineProto\Logger::log(\danog\MadelineProto\Lang::$current_lang['madelineproto_ready'], Logger::NOTICE);
}

View File

@ -215,13 +215,13 @@ class Connection
$this->disconnect();
yield $this->API->datacenter->dcConnectAsync($this->ctx->getDc());
if ($this->API->hasAllAuth() && !$this->hasPendingCalls()) {
$this->callFork((function () {
/*$this->callFork((function () {
try {
$this->API->method_call_async_read('ping', ['ping_id' => $this->random_int()], ['datacenter' => $this->datacenter]);
} catch (\Throwable $e) {
$this->API->logger("Got an error while pinging on reconnect: $e", Logger::FATAL_ERROR);
}
})());
})());*/
}
}

View File

@ -134,7 +134,6 @@ class FeedLoop extends ResumableSignalLoop
$this->state->pts($update['pts']);
}
$this->save($update);
}
}

View File

@ -24,6 +24,7 @@ use danog\MadelineProto\Async\AsyncConstruct;
use danog\MadelineProto\Loop\Update\FeedLoop;
use danog\MadelineProto\Loop\Update\SeqLoop;
use danog\MadelineProto\Loop\Update\UpdateLoop;
use danog\MadelineProto\Loop\Generic\PeriodicLoop;
use danog\MadelineProto\MTProtoTools\CombinedUpdatesState;
use danog\MadelineProto\MTProtoTools\ReferenceDatabase;
use danog\MadelineProto\MTProtoTools\UpdatesState;
@ -149,6 +150,7 @@ class MTProto extends AsyncConstruct implements TLCallback
private $supportUser = 0;
public $referenceDatabase;
public $phoneConfigWatcherId;
private $callCheckerLoop;
public $feeders = [];
public $updaters = [];
public $destructing = false; // Avoid problems with exceptions thrown by forked strands, see tools
@ -208,6 +210,7 @@ class MTProto extends AsyncConstruct implements TLCallback
$this->logger->logger(\danog\MadelineProto\Lang::$current_lang['TL_translation'], Logger::ULTRA_VERBOSE);
$this->construct_TL($this->settings['tl_schema']['src'], [$this, $this->referenceDatabase]);
yield $this->connect_to_all_dcs_async();
$this->startLoops();
$this->datacenter->curdc = 2;
if ((!isset($this->authorization['user']['bot']) || !$this->authorization['user']['bot']) && $this->datacenter->sockets[$this->datacenter->curdc]->temp_auth_key !== null) {
try {
@ -292,6 +295,20 @@ class MTProto extends AsyncConstruct implements TLCallback
return true;
}
public function startLoops()
{
if (!$this->callCheckerLoop) {
$this->callCheckerLoop = new PeriodicLoop($this, [$this, 'checkCalls'], 'call check', 10);
}
$this->callCheckerLoop->start();
}
public function stopLoops()
{
if ($this->callCheckerLoop) {
$this->callCheckerLoop->signal(true);;
$this->callCheckerLoop = null;
}
}
public function __wakeup()
{
$backtrace = debug_backtrace(0, 3);
@ -469,6 +486,7 @@ class MTProto extends AsyncConstruct implements TLCallback
$controller->setMadeline($this);
}
}
$this->startLoops();
if (yield $this->get_self_async()) {
$this->authorized = self::LOGGED_IN;
}
@ -490,6 +508,7 @@ class MTProto extends AsyncConstruct implements TLCallback
public function __destruct()
{
$this->stopLoops();
if ($this->phoneConfigWatcherId) {
Loop::cancel($this->phoneConfigWatcherId);
}
@ -1143,6 +1162,7 @@ class MTProto extends AsyncConstruct implements TLCallback
);
}
public function __debugInfo()
{
return ['MadelineProto instance '.spl_object_hash($this)];

View File

@ -83,7 +83,7 @@ trait AuthKeyHandler
* ***********************************************************************
* Compute p and q
*/
$pq = new \phpseclib\Math\BigInteger((string) $pq_bytes, 256);
$pq = new \phpseclib\Math\BigInteger($pq_bytes, 256);
$q = new \phpseclib\Math\BigInteger(0);
$p = new \phpseclib\Math\BigInteger(\danog\PrimeModule::auto_single($pq->__toString()));
if (!$p->equals(\danog\MadelineProto\Magic::$zero)) {
@ -256,8 +256,8 @@ trait AuthKeyHandler
throw new \danog\MadelineProto\SecurityException('wrong server nonce');
}
$g = new \phpseclib\Math\BigInteger($server_DH_inner_data['g']);
$g_a = new \phpseclib\Math\BigInteger((string) $server_DH_inner_data['g_a'], 256);
$dh_prime = new \phpseclib\Math\BigInteger((string) $server_DH_inner_data['dh_prime'], 256);
$g_a = new \phpseclib\Math\BigInteger($server_DH_inner_data['g_a'], 256);
$dh_prime = new \phpseclib\Math\BigInteger($server_DH_inner_data['dh_prime'], 256);
/*
* ***********************************************************************
* Time delta

View File

@ -605,7 +605,6 @@ trait ResponseHandler
if ($actual_updates) {
$updates = $actual_updates;
}
$this->logger->logger('Parsing updates ('.$updates['_'].') received via the socket...', \danog\MadelineProto\Logger::VERBOSE);
switch ($updates['_']) {
case 'updates':

View File

@ -63,11 +63,6 @@ trait UpdateHandler
if (!$this->settings['updates']['run_callback']) {
$this->settings['updates']['run_callback'] = true;
}
array_walk($this->calls, function ($controller, $id) {
if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
$controller->discard();
}
});
$params = array_merge(self::DEFAULT_GETUPDATES_PARAMS, $params);

View File

@ -49,7 +49,7 @@ class RSA
{
\danog\MadelineProto\Logger::log(\danog\MadelineProto\Lang::$current_lang['rsa_encrypting'], Logger::VERBOSE);
return (new \phpseclib\Math\BigInteger((string) $data, 256))->powMod($this->e, $this->n)->toBytes();
return (new \phpseclib\Math\BigInteger($data, 256))->powMod($this->e, $this->n)->toBytes();
}
/**
* Accesses a private variable from an object

View File

@ -41,7 +41,7 @@ trait AuthKeyHandler
$dh_config = yield $this->get_dh_config_async();
$this->logger->logger('Generating b...', \danog\MadelineProto\Logger::VERBOSE);
$b = new \phpseclib\Math\BigInteger($this->random(256), 256);
$params['g_a'] = new \phpseclib\Math\BigInteger((string) $params['g_a'], 256);
$params['g_a'] = new \phpseclib\Math\BigInteger($params['g_a'], 256);
$this->check_G($params['g_a'], $dh_config['p']);
$key = ['auth_key' => str_pad($params['g_a']->powMod($b, $dh_config['p'])->toBytes(), 256, chr(0), \STR_PAD_LEFT)];
//$this->logger->logger($key);
@ -87,7 +87,7 @@ trait AuthKeyHandler
return false;
}
$dh_config = yield $this->get_dh_config_async();
$params['g_a_or_b'] = new \phpseclib\Math\BigInteger((string) $params['g_a_or_b'], 256);
$params['g_a_or_b'] = new \phpseclib\Math\BigInteger($params['g_a_or_b'], 256);
$this->check_G($params['g_a_or_b'], $dh_config['p']);
$key = ['auth_key' => str_pad($params['g_a_or_b']->powMod($this->temp_requested_secret_chats[$params['id']], $dh_config['p'])->toBytes(), 256, chr(0), \STR_PAD_LEFT)];
unset($this->temp_requested_secret_chats[$params['id']]);
@ -139,10 +139,10 @@ trait AuthKeyHandler
$my_exchange_id = new \phpseclib\Math\BigInteger($this->secret_chats[$chat]['rekeying'][1], -256);
$other_exchange_id = new \phpseclib\Math\BigInteger($params['exchange_id'], -256);
//$this->logger->logger($my, $params);
if ($my_exchange_id->compare($other_exchange_id) > 0) {
if ($my_exchange_id > $other_exchange_id) {
return;
}
if ($my_exchange_id->compare($other_exchange_id) === 0) {
if ($my_exchange_id === $other_exchange_id) {
$this->secret_chats[$chat]['rekeying'] = [0];
return;
@ -152,7 +152,7 @@ trait AuthKeyHandler
$dh_config = yield $this->get_dh_config_async();
$this->logger->logger('Generating b...', \danog\MadelineProto\Logger::VERBOSE);
$b = new \phpseclib\Math\BigInteger($this->random(256), 256);
$params['g_a'] = new \phpseclib\Math\BigInteger((string) $params['g_a'], 256);
$params['g_a'] = new \phpseclib\Math\BigInteger($params['g_a'], 256);
$this->check_G($params['g_a'], $dh_config['p']);
$key = ['auth_key' => str_pad($params['g_a']->powMod($b, $dh_config['p'])->toBytes(), 256, chr(0), \STR_PAD_LEFT)];
$key['fingerprint'] = substr(sha1($key['auth_key'], true), -8);
@ -175,7 +175,7 @@ trait AuthKeyHandler
}
$this->logger->logger('Committing rekeying of secret chat '.$chat.'...', \danog\MadelineProto\Logger::VERBOSE);
$dh_config = yield $this->get_dh_config_async();
$params['g_b'] = new \phpseclib\Math\BigInteger((string) $params['g_b'], 256);
$params['g_b'] = new \phpseclib\Math\BigInteger($params['g_b'], 256);
$this->check_G($params['g_b'], $dh_config['p']);
$key = ['auth_key' => str_pad($params['g_b']->powMod($this->temp_rekeyed_secret_chats[$params['exchange_id']], $dh_config['p'])->toBytes(), 256, chr(0), \STR_PAD_LEFT)];
$key['fingerprint'] = substr(sha1($key['auth_key'], true), -8);

View File

@ -129,7 +129,7 @@ trait Tools
throw new TL\Exception(\danog\MadelineProto\Lang::$current_lang['length_not_8']);
}
$big = new BigInteger((string) $value, -256);
$big = new BigInteger($value, -256);
return (string) $big;
}

View File

@ -49,11 +49,6 @@ trait AuthKeyHandler
if (!class_exists('\\danog\\MadelineProto\\VoIP')) {
throw new \danog\MadelineProto\Exception(['extension', 'libtgvoip']);
}
array_walk($this->calls, function ($controller, $id) {
if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
$controller->discard();
}
});
$user = yield $this->get_info_async($user);
if (!isset($user['InputUser']) || $user['InputUser']['_'] === 'inputUserSelf') {
throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['peer_not_in_db']);
@ -81,11 +76,6 @@ trait AuthKeyHandler
if (!class_exists('\\danog\\MadelineProto\\VoIP')) {
throw new \danog\MadelineProto\Exception();
}
array_walk($this->calls, function ($controller, $id) {
if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
$controller->discard();
}
});
if ($this->call_status($call['id']) !== \danog\MadelineProto\VoIP::CALL_STATE_ACCEPTED) {
$this->logger->logger(sprintf(\danog\MadelineProto\Lang::$current_lang['call_error_1'], $call['id']));
@ -126,11 +116,6 @@ trait AuthKeyHandler
if (!class_exists('\\danog\\MadelineProto\\VoIP')) {
throw new \danog\MadelineProto\Exception(['extension', 'libtgvoip']);
}
array_walk($this->calls, function ($controller, $id) {
if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
$controller->discard();
}
});
if ($this->call_status($params['id']) !== \danog\MadelineProto\VoIP::CALL_STATE_REQUESTED) {
$this->logger->logger(sprintf(\danog\MadelineProto\Lang::$current_lang['call_error_2'], $params['id']));
@ -138,7 +123,7 @@ trait AuthKeyHandler
}
$this->logger->logger(sprintf(\danog\MadelineProto\Lang::$current_lang['call_confirming'], $this->calls[$params['id']]->getOtherID()), \danog\MadelineProto\Logger::VERBOSE);
$dh_config = yield $this->get_dh_config_async();
$params['g_b'] = new \phpseclib\Math\BigInteger((string) $params['g_b'], 256);
$params['g_b'] = new \phpseclib\Math\BigInteger($params['g_b'], 256);
$this->check_G($params['g_b'], $dh_config['p']);
$key = str_pad($params['g_b']->powMod($this->calls[$params['id']]->storage['a'], $dh_config['p'])->toBytes(), 256, chr(0), \STR_PAD_LEFT);
$res = (yield $this->method_call_async_read('phone.confirmCall', ['key_fingerprint' => substr(sha1($key, true), -8), 'peer' => ['id' => $params['id'], 'access_hash' => $params['access_hash'], '_' => 'inputPhoneCall'], 'g_a' => $this->calls[$params['id']]->storage['g_a'], 'protocol' => ['_' => 'phoneCallProtocol', 'udp_reflector' => true, 'min_layer' => 65, 'max_layer' => \danog\MadelineProto\VoIP::getConnectionMaxLayer()]], ['datacenter' => $this->datacenter->curdc]))['phone_call'];
@ -163,11 +148,6 @@ trait AuthKeyHandler
if (!class_exists('\\danog\\MadelineProto\\VoIP')) {
throw new \danog\MadelineProto\Exception(['extension', 'libtgvoip']);
}
array_walk($this->calls, function ($controller, $id) {
if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
$controller->discard();
}
});
if ($this->call_status($params['id']) !== \danog\MadelineProto\VoIP::CALL_STATE_ACCEPTED || !isset($this->calls[$params['id']]->storage['b'])) {
$this->logger->logger(sprintf(\danog\MadelineProto\Lang::$current_lang['call_error_3'], $params['id']));
@ -178,7 +158,7 @@ trait AuthKeyHandler
if (hash('sha256', $params['g_a_or_b'], true) != $this->calls[$params['id']]->storage['g_a_hash']) {
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['invalid_g_a']);
}
$params['g_a_or_b'] = new \phpseclib\Math\BigInteger((string) $params['g_a_or_b'], 256);
$params['g_a_or_b'] = new \phpseclib\Math\BigInteger($params['g_a_or_b'], 256);
$this->check_G($params['g_a_or_b'], $dh_config['p']);
$key = str_pad($params['g_a_or_b']->powMod($this->calls[$params['id']]->storage['b'], $dh_config['p'])->toBytes(), 256, chr(0), \STR_PAD_LEFT);
if (substr(sha1($key, true), -8) != $params['key_fingerprint']) {
@ -204,11 +184,6 @@ trait AuthKeyHandler
if (!class_exists('\\danog\\MadelineProto\\VoIP')) {
throw new \danog\MadelineProto\Exception(['extension', 'libtgvoip']);
}
array_walk($this->calls, function ($controller, $id) {
if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
$controller->discard();
}
});
if (isset($this->calls[$id])) {
return $this->calls[$id]->getCallState();
}
@ -221,11 +196,6 @@ trait AuthKeyHandler
if (!class_exists('\\danog\\MadelineProto\\VoIP')) {
throw new \danog\MadelineProto\Exception(['extension', 'libtgvoip']);
}
array_walk($this->calls, function ($controller, $id) {
if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
$controller->discard();
}
});
return $this->calls[$call];
}
@ -262,6 +232,9 @@ trait AuthKeyHandler
in_array($this->settings['updates']['callback'], [['danog\\MadelineProto\\API', 'get_updates_update_handler'], 'get_updates_update_handler']) ? $this->get_updates_update_handler($update) : $this->settings['updates']['callback']($update);
}
unset($this->calls[$call['id']]);
}
public function checkCalls()
{
array_walk($this->calls, function ($controller, $id) {
if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
$controller->discard();

View File

@ -165,11 +165,6 @@ trait Loop
$callback = $this->loop_callback;
$callback();
}
array_walk($this->calls, function ($controller, $id) {
if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
$controller->discard();
}
});
yield $this->waitUpdate();
}
}

View File

@ -48,7 +48,6 @@ $settings = json_decode(getenv('MTPROTO_SETTINGS'), true) ?: [];
*/
echo 'Loading MadelineProto...'.PHP_EOL;
$MadelineProto = new \danog\MadelineProto\API(getcwd().'/testing.madeline', $settings);
$MadelineProto->fileGetContents('https://google.com');
$MadelineProto->start();