Refactoring

This commit is contained in:
Daniil Gentili 2020-10-26 23:13:05 +01:00
parent d0189b1ef2
commit 806f50bc2d
Signed by: danog
GPG Key ID: 8C1BE3B34B230CA7
4 changed files with 143 additions and 179 deletions

5
.gitignore vendored
View File

@ -125,9 +125,4 @@ tempConv
extracted.json
.phpunit.result.cache
src/danog/MadelineProto/VoIP.php
src/danog/MadelineProto/VoIP/AckHandler.php
src/danog/MadelineProto/VoIP/MessageHandler.php
src/danog/MadelineProto/OpusStream.php
ponyScripts

View File

@ -12,11 +12,20 @@ If not, see <http://www.gnu.org/licenses/>.
namespace danog\MadelineProto;
use Amp\Delayed;
use danog\MadelineProto\MTProto\PermAuthKey;
use danog\MadelineProto\Stream\Common\FileBufferedStream;
use danog\MadelineProto\Stream\ConnectionContext;
use danog\MadelineProto\Stream\Ogg\Ogg;
use danog\MadelineProto\VoIP\Endpoint;
use function Amp\File\open;
if (\extension_loaded('php-libtgvoip')) {
return;
}
class VoIP extends Tools
class VoIP
{
use \danog\MadelineProto\VoIP\MessageHandler;
use \danog\MadelineProto\VoIP\AckHandler;
@ -125,6 +134,16 @@ class VoIP extends Tools
private $outputFile;
private $isPlaying = false;
private bool $creator;
private PermAuthKey $authKey;
private int $peerVersion;
/**
* @var Endpoint[]
*/
private array $sockets = [];
private $connection_settings = [];
private $dclist = [];
@ -191,13 +210,12 @@ class VoIP extends Tools
public function startTheMagic()
{
while (true) {
$waiting = $this->datacenter->select();
foreach ($waiting as $dc) {
if ($packet = $this->recv_message($dc)) {
$this->handlePacket($dc, $packet);
foreach ($this->sockets as $socket) {
Tools::callFork(function () use ($socket) {
while ($payload = $this->recv_message($socket)) {
Tools::callFork($this->handlePacket($socket, $payload));
}
}
});
}
return $this;
}
@ -205,19 +223,36 @@ class VoIP extends Tools
{
\var_dump($packet);
switch ($packet['_']) {
case self::PKT_INIT:
$this->voip_state = self::STATE_WAIT_INIT_ACK;
$this->send_message(['_' => self::PKT_INIT_ACK, 'protocol' => self::PROTOCOL_VERSION, 'min_protocol' => self::MIN_PROTOCOL_VERSION, 'all_streams' => [['id' => 0, 'type' => self::STREAM_TYPE_AUDIO, 'codec' => self::CODEC_OPUS, 'frame_duration' => 60, 'enabled' => 1]]], $datacenter);
//$a = fopen('paloma.opus', 'rb');
//(new Ogg($a, [$this, 'oggCallback']))->run();
break;
case self::PKT_INIT_ACK:
case self::PKT_INIT:
$this->voip_state = self::STATE_WAIT_INIT_ACK;
$this->send_message(['_' => self::PKT_INIT_ACK, 'protocol' => self::PROTOCOL_VERSION, 'min_protocol' => self::MIN_PROTOCOL_VERSION, 'all_streams' => [['id' => 0, 'type' => self::STREAM_TYPE_AUDIO, 'codec' => self::CODEC_OPUS, 'frame_duration' => 60, 'enabled' => 1]]], $datacenter);
break;
case self::PKT_INIT_ACK:
if ($this->voip_state !== self::STATE_ESTABLISHED) {
$this->voip_state = self::STATE_ESTABLISHED;
$a = \fopen('paloma.opus', 'rb');
(new Ogg($a, [$this, 'oggCallback']))->run();
break;
}
$ctx = new ConnectionContext;
$ctx->addStream(FileBufferedStream::class, yield open('kda.opus', 'r'));
$stream = yield from $ctx->getStream();
$ogg = yield from Ogg::init($stream, 60000);
$it = $ogg->getEmitter()->iterate();
Tools::callFork($ogg->read());
Tools::callFork(function () use ($it) {
$timestamp = 0;
$t = microtime(true);
while (yield $it->advance()) {
$elapsed = microtime(true) - $t;
$t = microtime(true);
yield new Delayed((int) (60000 - $elapsed / 1000));
yield $this->send_message(['_' => self::PKT_STREAM_DATA, 'stream_id' => 0, 'data' => $it->getCurrent(), 'timestamp' => $this->timestamp], $datacenter);
$timestamp += 60;
}
});
}
break;
}
}
public $timestamp = 0;
public function oggCallback($data)
@ -279,11 +314,6 @@ class VoIP extends Tools
return $this->callID;
}
public function isCreator()
{
return $this->creator;
}
public function whenCreated()
{
return isset($this->internalStorage['created']) ? $this->internalStorage['created'] : false;
@ -291,36 +321,16 @@ class VoIP extends Tools
public function parseConfig()
{
$this->authKey = new PermAuthKey();
$this->authKey->setAuthKey($this->configuration['auth_key']);
if (\count($this->configuration['endpoints'])) {
$this->connection_settings['all'] = $this->MadelineProto->settings['connection_settings']['all'];
$this->connection_settings['all']['protocol'] = 'obfuscated2';
$this->connection_settings['all']['timeout'] = 1;
$this->connection_settings['all']['do_not_retry'] = true;
$test = $this->connection_settings['all']['test_mode'] ? 'test' : 'main';
foreach ($this->configuration['endpoints'] as $endpoint) {
$this->dclist[$test]['ipv6'][$endpoint['id']] = ['ip_address' => $endpoint['ipv6'], 'port' => $endpoint['port'], 'peer_tag' => $endpoint['peer_tag']];
$this->dclist[$test]['ipv4'][$endpoint['id']] = ['ip_address' => $endpoint['ip'], 'port' => $endpoint['port'], 'peer_tag' => $endpoint['peer_tag']];
$this->sockets['v6 '.$endpoint['id']] = new Endpoint($endpoint['ipv6'], $endpoint['port'], $endpoint['peer_tag'], true, $this);
$this->sockets['v4 '.$endpoint['id']] = new Endpoint($endpoint['ip'], $endpoint['port'], $endpoint['peer_tag'], true, $this);
}
if (!isset($this->datacenter)) {
$this->datacenter = new DataCenter($this->dclist, $this->connection_settings);
foreach ($this->sockets as $socket) {
yield from $socket->connect();
}
//$this->datacenter->__construct($this->dclist, $this->connection_settings);
foreach ($this->datacenter->get_dcs() as $new_dc) {
try {
$this->datacenter->dc_connect($new_dc);
} catch (\danog\MadelineProto\Exception $e) {
}
}
$this->init_all();
foreach ($this->datacenter->get_dcs(false) as $new_dc) {
try {
$this->datacenter->dc_connect($new_dc);
} catch (\danog\MadelineProto\Exception $e) {
}
}
$this->init_all();
}
}
@ -328,29 +338,8 @@ class VoIP extends Tools
{
$test = $this->connection_settings['all']['test_mode'] ? 'test' : 'main';
foreach ($this->datacenter->sockets as $dc_id => $socket) {
if ($socket->auth_key === null) {
$socket->auth_key = ['id' => $this->configuration['auth_key_id'], 'auth_key' => $this->configuration['auth_key'], 'connection_inited' => false];
}
if ($socket->type === Connection::API_ENDPOINT) {
$socket->type = Connection::VOIP_TCP_REFLECTOR_ENDPOINT;
}
if ($socket->peer_tag === null) {
switch ($socket->type) {
case Connection::VOIP_TCP_REFLECTOR_ENDPOINT:
case Connection::VOIP_UDP_REFLECTOR_ENDPOINT:
$socket->peer_tag = $this->dclist[$test]['ipv4'][$dc_id]['peer_tag'];
break;
default:
$socket->peer_tag = $this->configuration['call_id'];
}
}
//if ($this->voip_state === self::STATE_CREATED) {
$this->send_message(['_' => self::PKT_INIT, 'protocol' => self::PROTOCOL_VERSION, 'min_protocol' => self::MIN_PROTOCOL_VERSION, 'audio_streams' => [self::CODEC_OPUS], 'video_streams' => []], $dc_id);
$this->send_message(['_' => self::PKT_INIT, 'protocol' => self::PROTOCOL_VERSION, 'min_protocol' => self::MIN_PROTOCOL_VERSION, 'audio_streams' => [self::CODEC_OPUS], 'video_streams' => []], $socket);
$this->voip_state = self::STATE_WAIT_INIT;
//}
if (isset($this->datacenter->sockets[$dc_id])) {
$this->send_message(['_' => self::PKT_PING], $dc_id);
}
}
}
@ -383,4 +372,34 @@ class VoIP extends Tools
{
return $this->signal;
}
/**
* Get the value of creator.
*
* @return bool
*/
public function isCreator(): bool
{
return $this->creator;
}
/**
* Get the value of authKey.
*
* @return PermAuthKey
*/
public function getAuthKey(): PermAuthKey
{
return $this->authKey;
}
/**
* Get the value of peerVersion.
*
* @return int
*/
public function getPeerVersion(): int
{
return $this->peerVersion;
}
}

View File

@ -19,7 +19,7 @@ trait AckHandler
{
return $s1 > $s2;
}
public function received_packet($datacenter, $last_ack_id, $packet_seq_no, $ack_mask)
public function received_packet($last_ack_id, $packet_seq_no, $ack_mask)
{
if ($this->seqgt($packet_seq_no, $this->session_in_seq_no)) {
$diff = $packet_seq_no - $this->session_in_seq_no;

View File

@ -13,6 +13,9 @@ If not, see <http://www.gnu.org/licenses/>.
namespace danog\MadelineProto\VoIP;
use danog\MadelineProto\TL\Exception;
use danog\MadelineProto\Tools;
/**
* Manages packing and unpacking of messages, and the list of sent and received messages.
*/
@ -28,7 +31,7 @@ trait MessageHandler
$concat .= \pack('@'.$this->posmod(-$l - 1, 4));
} else {
$concat .= \chr(254);
$concat .= \substr($this->pack_signed_int($l), 0, 3);
$concat .= \substr(Tools::packSignedInt($l), 0, 3);
$concat .= $object;
$concat .= \pack('@'.$this->posmod(-$l, 4));
}
@ -60,7 +63,7 @@ trait MessageHandler
public function send_message($args, $datacenter = null)
{
if ($datacenter === null) {
return $this->send_message($args, \key($this->datacenter->sockets));
return $this->send_message($args, \reset($this->sockets));
}
$message = '';
switch ($args['_']) {
@ -68,11 +71,11 @@ trait MessageHandler
//
// packetInit#1 protocol:int min_protocol:int flags:# data_saving_enabled:flags.0?true audio_streams:byteVector<streamTypeSimple> video_streams:byteVector<streamTypeSimple> = Packet;
case \danog\MadelineProto\VoIP::PKT_INIT:
$message .= $this->pack_signed_int($args['protocol']);
$message .= $this->pack_signed_int($args['min_protocol']);
$message .= Tools::packSignedInt($args['protocol']);
$message .= Tools::packSignedInt($args['min_protocol']);
$flags = 0;
$flags = isset($args['data_saving_enabled']) && $args['data_saving_enabled'] ? $flags | 1 : $flags & ~1;
$message .= $this->pack_unsigned_int($flags);
$message .= Tools::packUnsignedInt($flags);
$message .= \chr(\count($args['audio_streams']));
foreach ($args['audio_streams'] as $codec) {
$message .= \chr($codec);
@ -86,8 +89,8 @@ trait MessageHandler
//
// packetInitAck#2 protocol:int min_protocol:int all_streams:byteVector<streamType> = Packet;
case \danog\MadelineProto\VoIP::PKT_INIT_ACK:
$message .= $this->pack_signed_int($args['protocol']);
$message .= $this->pack_signed_int($args['min_protocol']);
$message .= Tools::packSignedInt($args['protocol']);
$message .= Tools::packSignedInt($args['min_protocol']);
$message .= \chr(\count($args['all_streams']));
foreach ($args['all_streams'] as $stream) {
$message .= \chr($stream['id']);
@ -114,7 +117,7 @@ trait MessageHandler
$flags = $flags | $args['stream_id'];
$message .= \chr($flags);
$message .= $length > 255 ? \pack('v', $length) : \chr($length);
$message .= $this->pack_unsigned_int($args['timestamp']);
$message .= Tools::packUnsignedInt($args['timestamp']);
$message .= $args['data'];
break;
/*case \danog\MadelineProto\VoIP::PKT_UPDATE_STREAMS:
@ -122,7 +125,7 @@ trait MessageHandler
case \danog\MadelineProto\VoIP::PKT_PING:
break;*/
case \danog\MadelineProto\VoIP::PKT_PONG:
$message .= $this->pack_unsigned_int($args['out_seq_no']);
$message .= Tools::packUnsignedInt($args['out_seq_no']);
break;
case \danog\MadelineProto\VoIP::PKT_STREAM_DATA_X2:
for ($x = 0; $x < 2; $x++) {
@ -134,7 +137,7 @@ trait MessageHandler
$flags = $flags | $args[$x]['stream_id'];
$message .= \chr($flags);
$message .= $length > 255 ? \pack('v', $length) : \chr($length);
$message .= $this->pack_unsigned_int($args[$x]['timestamp']);
$message .= Tools::packUnsignedInt($args[$x]['timestamp']);
$message .= $args[$x]['data'];
}
break;
@ -148,22 +151,22 @@ trait MessageHandler
$flags = $flags | $args[$x]['stream_id'];
$message .= \chr($flags);
$message .= $length > 255 ? \pack('v', $length) : \chr($length);
$message .= $this->pack_unsigned_int($args[$x]['timestamp']);
$message .= Tools::packUnsignedInt($args[$x]['timestamp']);
$message .= $args[$x]['data'];
}
break;
// packetLanEndpoint#A address:int port:int = Packet;
case \danog\MadelineProto\VoIP::PKT_LAN_ENDPOINT:
$message .= $this->pack_signed_int($args['address']);
$message .= $this->pack_signed_int($args['port']);
$message .= Tools::packSignedInt($args['address']);
$message .= Tools::packSignedInt($args['port']);
break;
// packetNetworkChanged#B flags:# data_saving_enabled:flags.0?true = Packet;
case \danog\MadelineProto\VoIP::PKT_NETWORK_CHANGED:
$message .= $this->pack_signed_int(isset($args['data_saving_enabled']) && $args['data_saving_enabled'] ? 1 : 0);
$message .= Tools::packSignedInt(isset($args['data_saving_enabled']) && $args['data_saving_enabled'] ? 1 : 0);
break;
// packetSwitchPreferredRelay#C relay_id:long = Packet;
case \danog\MadelineProto\VoIP::PKT_SWITCH_PREF_RELAY:
$message .= $this->pack_signed_long($args['relay_d']);
$message .= Tools::packSignedLong($args['relay_d']);
break;
/*case \danog\MadelineProto\VoIP::PKT_SWITCH_TO_P2P:
break;
@ -194,11 +197,11 @@ trait MessageHandler
$flags = isset($args['extra']) ? $flags | 2 : $flags & ~2; // extra
$flags = \strlen($message) ? $flags | 1 : $flags & ~1; // raw_data
$flags = $flags | ($args['_'] << 24);
$payload .= $this->pack_unsigned_int($flags);
$payload .= Tools::packUnsignedInt($flags);
$payload .= $this->configuration['call_id'];
$payload .= $this->pack_unsigned_int($this->session_in_seq_no);
$payload .= $this->pack_unsigned_int($this->session_out_seq_no);
$payload .= $this->pack_unsigned_int($ack_mask);
$payload .= Tools::packUnsignedInt($this->session_in_seq_no);
$payload .= Tools::packUnsignedInt($this->session_out_seq_no);
$payload .= Tools::packUnsignedInt($ack_mask);
$payload .= \danog\MadelineProto\VoIP::PROTO_ID;
if ($flags & 2) {
$payload .= $this->pack_string($args['extra']);
@ -211,76 +214,23 @@ trait MessageHandler
$payload .= $this->random(8);
$payload .= \chr(7);
$payload .= $this->random(7);
$message = \chr($args['_']).$this->pack_unsigned_int($this->session_in_seq_no).$this->pack_unsigned_int($this->session_out_seq_no).$this->pack_unsigned_int($ack_mask).$message;
$message = \chr($args['_']).Tools::packUnsignedInt($this->session_in_seq_no).Tools::packUnsignedInt($this->session_out_seq_no).Tools::packUnsignedInt($ack_mask).$message;
$payload .= $this->pack_string($message);
}
$this->session_out_seq_no++;
$payload = $this->pack_unsigned_int(\strlen($payload)).$payload;
$payload_key = \substr(\sha1($payload, true), -16);
list($aes_key, $aes_iv) = $this->old_aes_calculate($payload_key, $this->datacenter->sockets[$datacenter]->auth_key['auth_key'], $this->creator);
$payload .= $this->random($this->posmod(-\strlen($payload), 16));
$payload = $this->datacenter->sockets[$datacenter]->peer_tag.$this->datacenter->sockets[$datacenter]->auth_key['id'].$payload_key.$this->ige_encrypt($payload, $aes_key, $aes_iv);
try {
$this->datacenter->sockets[$datacenter]->send_message($payload);
} catch (\danog\MadelineProto\Exception $e) {
unset($this->datacenter->sockets[$datacenter]);
}
return $datacenter->write($payload);
}
/**
* Reading connection and receiving message from server.
*/
public function recv_message($datacenter)
public function recv_message(Endpoint $endpoint)
{
$payload = \fopen('php://memory', 'rw+b');
\fwrite($payload, $this->datacenter->sockets[$datacenter]->read_message());
\fseek($payload, 0);
if (\stream_get_contents($payload, 16) !== $this->datacenter->sockets[$datacenter]->peer_tag) {
\danog\MadelineProto\Logger::log("Received packet has wrong peer tag", \danog\MadelineProto\Logger::ERROR);
return false;
if (!$payload = yield from $endpoint->read()) {
return null;
}
if (\stream_get_contents($payload, 12) === "\0\0\0\0\0\0\0\0\0\0\0\0") {
$payload = \stream_get_contents($payload);
} else {
\fseek($payload, 16);
if (\stream_get_contents($payload, 8) !== $this->datacenter->sockets[$datacenter]->auth_key['id']) {
\danog\MadelineProto\Logger::log('Wrong auth key ID', \danog\MadelineProto\Logger::ERROR);
return false;
}
$message_key = \stream_get_contents($payload, 16);
list($aes_key, $aes_iv) = $this->old_aes_calculate($message_key, $this->datacenter->sockets[$datacenter]->auth_key['auth_key'], !$this->creator);
$encrypted_data = \stream_get_contents($payload);
if (\strlen($encrypted_data) % 16 != 0) {
\danog\MadelineProto\Logger::log(\danog\MadelineProto\Lang::$current_lang['length_not_divisible_16'], \danog\MadelineProto\Logger::ERROR);
}
$decrypted_data = $this->ige_decrypt($encrypted_data, $aes_key, $aes_iv);
$message_data_length = \unpack('V', \substr($decrypted_data, 0, 4))[1];
$payload = \substr($decrypted_data, 4, $message_data_length);
if ($message_data_length > \strlen($decrypted_data)) {
\danog\MadelineProto\Logger::log(\danog\MadelineProto\Lang::$current_lang['msg_data_length_too_big'], \danog\MadelineProto\Logger::ERROR);
return false;
}
if ($message_key != \substr(\sha1(\substr($decrypted_data, 0, 4 + $message_data_length), true), -16)) {
\danog\MadelineProto\Logger::log(\danog\MadelineProto\Lang::$current_lang['msg_key_mismatch'], \danog\MadelineProto\Logger::ERROR);
return false;
}
if (\strlen($decrypted_data) - 4 - $message_data_length > 15) {
\danog\MadelineProto\Logger::log('difference between message_data_length and the length of the remaining decrypted buffer is too big', \danog\MadelineProto\Logger::ERROR);
}
if (\strlen($decrypted_data) % 16 != 0) {
\danog\MadelineProto\Logger::log(\danog\MadelineProto\Lang::$current_lang['length_not_divisible_16'], \danog\MadelineProto\Logger::ERROR);
}
}
$stream = \fopen('php://memory', 'rw+b');
\fwrite($stream, $payload);
$payload = $stream;
\fseek($payload, 0);
$result = [];
switch ($crc = \stream_get_contents($payload, 4)) {
@ -296,25 +246,25 @@ trait MessageHandler
}
}
if ($flags & 16) {
$in_seq_no = \unpack('V', \stream_get_contents($stream, 4))[1];
$out_seq_no = \unpack('V', \stream_get_contents($stream, 4))[1];
$in_seq_no = \unpack('V', \stream_get_contents($payload, 4))[1];
$out_seq_no = \unpack('V', \stream_get_contents($payload, 4))[1];
}
if ($flags & 32) {
$ack_mask = \unpack('V', \stream_get_contents($stream, 4))[1];
$ack_mask = \unpack('V', \stream_get_contents($payload, 4))[1];
}
if ($flags & 8) {
if (\stream_get_contents($stream, 4) !== \danog\MadelineProto\VoIP::PROTO_ID) {
if (\stream_get_contents($payload, 4) !== \danog\MadelineProto\VoIP::PROTO_ID) {
\danog\MadelineProto\Logger::log('Protocol mismatch', \danog\MadelineProto\Logger::ERROR);
return false;
}
}
if ($flags & 2) {
$result['extra'] = $this->unpack_string($stream);
$result['extra'] = $this->unpack_string($payload);
}
$message = \fopen('php://memory', 'rw+b');
if ($flags & 1) {
\fwrite($message, $this->unpack_string($stream));
\fwrite($message, $this->unpack_string($payload));
\fseek($message, 0);
}
break;
@ -324,7 +274,7 @@ trait MessageHandler
$flags = \unpack('V', \stream_get_contents($payload, 4))[1];
$message = \fopen('php://memory', 'rw+b');
\fwrite($message, $this->unpack_string($stream));
\fwrite($message, $this->unpack_string($payload));
\fseek($message, 0);
$result['_'] = \ord(\stream_get_contents($message, 1));
$in_seq_no = \unpack('V', \stream_get_contents($message, 4))[1];
@ -333,22 +283,22 @@ trait MessageHandler
break;
case $this->TLID_REFLECTOR_SELF_INFO:
$result['date'] = $this->unpack_signed_int(\stream_get_contents($payload, 4));
$result['query_id'] = $this->unpack_signed_long(\stream_get_contents($payload, 8));
$result['date'] = Tools::unpackSignedInt(\stream_get_contents($payload, 4));
$result['query_id'] = Tools::unpackSignedLong(\stream_get_contents($payload, 8));
$result['my_ip'] = \stream_get_contents($payload, 16);
$result['my_port'] = $this->unpack_signed_int(\stream_get_contents($payload, 4));
$result['my_port'] = Tools::unpackSignedInt(\stream_get_contents($payload, 4));
return $result;
case $this->TLID_REFLECTOR_PEER_INFO:
$result['my_address'] = $this->unpack_signed_int(\stream_get_contents($payload, 4));
$result['my_port'] = $this->unpack_signed_int(\stream_get_contents($payload, 4));
$result['peer_address'] = $this->unpack_signed_int(\stream_get_contents($payload, 4));
$result['peer_port'] = $this->unpack_signed_int(\stream_get_contents($payload, 4));
$result['my_address'] = Tools::unpackSignedInt(\stream_get_contents($payload, 4));
$result['my_port'] = Tools::unpackSignedInt(\stream_get_contents($payload, 4));
$result['peer_address'] = Tools::unpackSignedInt(\stream_get_contents($payload, 4));
$result['peer_port'] = Tools::unpackSignedInt(\stream_get_contents($payload, 4));
return $result;
default:
\danog\MadelineProto\Logger::log('Unknown packet received: '.\bin2hex($crc), \danog\MadelineProto\Logger::ERROR);
return false;
}
if (!$this->received_packet($datacenter, $in_seq_no, $out_seq_no, $ack_mask)) {
if (!$this->received_packet($in_seq_no, $out_seq_no, $ack_mask)) {
return false;
}
switch ($result['_']) {
@ -356,8 +306,8 @@ trait MessageHandler
//
// packetInit#1 protocol:int min_protocol:int flags:# data_saving_enabled:flags.0?true audio_streams:byteVector<streamTypeSimple> video_streams:byteVector<streamTypeSimple> = Packet;
case \danog\MadelineProto\VoIP::PKT_INIT:
$result['protocol'] = $this->unpack_signed_int(\stream_get_contents($message, 4));
$result['min_protocol'] = $this->unpack_signed_int(\stream_get_contents($message, 4));
$result['protocol'] = Tools::unpackSignedInt(\stream_get_contents($message, 4));
$result['min_protocol'] = Tools::unpackSignedInt(\stream_get_contents($message, 4));
$flags = \unpack('V', \stream_get_contents($message, 4))[1];
$result['data_saving_enabled'] = (bool) ($flags & 1);
$result['audio_streams'] = [];
@ -375,8 +325,8 @@ trait MessageHandler
//
// packetInitAck#2 protocol:int min_protocol:int all_streams:byteVector<streamType> = Packet;
case \danog\MadelineProto\VoIP::PKT_INIT_ACK:
$result['protocol'] = $this->unpack_signed_int(\stream_get_contents($message, 4));
$result['min_protocol'] = $this->unpack_signed_int(\stream_get_contents($message, 4));
$result['protocol'] = Tools::unpackSignedInt(\stream_get_contents($message, 4));
$result['min_protocol'] = Tools::unpackSignedInt(\stream_get_contents($message, 4));
$result['all_streams'] = [];
$length = \ord(\stream_get_contents($message, 1));
for ($x = 0; $x < $length; $x++) {
@ -410,8 +360,8 @@ trait MessageHandler
case \danog\MadelineProto\VoIP::PKT_PING:
break;*/
case \danog\MadelineProto\VoIP::PKT_PONG:
if (\fstat($stream)['size'] - \ftell($stream)) {
$result['out_seq_no'] = \unpack('V', \stream_get_contents($stream, 4))[1];
if (\fstat($payload)['size'] - \ftell($payload)) {
$result['out_seq_no'] = \unpack('V', \stream_get_contents($payload, 4))[1];
}
break;
case \danog\MadelineProto\VoIP::PKT_STREAM_DATA_X2:
@ -438,16 +388,16 @@ trait MessageHandler
break;
// packetLanEndpoint#A address:int port:int = Packet;
case \danog\MadelineProto\VoIP::PKT_LAN_ENDPOINT:
$result['address'] = \unpack('V', \stream_get_contents($stream, 4))[1];
$result['port'] = \unpack('V', \stream_get_contents($stream, 4))[1];
$result['address'] = \unpack('V', \stream_get_contents($payload, 4))[1];
$result['port'] = \unpack('V', \stream_get_contents($payload, 4))[1];
break;
// packetNetworkChanged#B flags:# data_saving_enabled:flags.0?true = Packet;
case \danog\MadelineProto\VoIP::PKT_NETWORK_CHANGED:
$result['data_saving_enabled'] = (bool) (\unpack('V', \stream_get_contents($stream, 4))[1] & 1);
$result['data_saving_enabled'] = (bool) (\unpack('V', \stream_get_contents($payload, 4))[1] & 1);
break;
// packetSwitchPreferredRelay#C relay_id:long = Packet;
case \danog\MadelineProto\VoIP::PKT_SWITCH_PREF_RELAY:
$result['relay_id'] = $this->unpack_signed_long(\stream_get_contents($stream, 8));
$result['relay_id'] = Tools::unpackSignedLong(\stream_get_contents($payload, 8));
break;
/*case \danog\MadelineProto\VoIP::PKT_SWITCH_TO_P2P:
break;