diff --git a/.gitignore b/.gitignore index 81e9d403..a05cbbae 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/src/danog/MadelineProto/VoIP.php b/src/danog/MadelineProto/VoIP.php index ad21a430..40a045af 100644 --- a/src/danog/MadelineProto/VoIP.php +++ b/src/danog/MadelineProto/VoIP.php @@ -12,11 +12,20 @@ If not, see . 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; + } } diff --git a/src/danog/MadelineProto/VoIP/AckHandler.php b/src/danog/MadelineProto/VoIP/AckHandler.php index a37ba1c9..d602ee1c 100644 --- a/src/danog/MadelineProto/VoIP/AckHandler.php +++ b/src/danog/MadelineProto/VoIP/AckHandler.php @@ -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; diff --git a/src/danog/MadelineProto/VoIP/MessageHandler.php b/src/danog/MadelineProto/VoIP/MessageHandler.php index 8d830cf3..72e44fc6 100644 --- a/src/danog/MadelineProto/VoIP/MessageHandler.php +++ b/src/danog/MadelineProto/VoIP/MessageHandler.php @@ -13,6 +13,9 @@ If not, see . 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 video_streams:byteVector = 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 = 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 video_streams:byteVector = 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 = 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;