Refactoring
This commit is contained in:
parent
d0189b1ef2
commit
806f50bc2d
5
.gitignore
vendored
5
.gitignore
vendored
@ -125,9 +125,4 @@ tempConv
|
|||||||
extracted.json
|
extracted.json
|
||||||
.phpunit.result.cache
|
.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
|
ponyScripts
|
||||||
|
@ -12,11 +12,20 @@ If not, see <http://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
namespace danog\MadelineProto;
|
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')) {
|
if (\extension_loaded('php-libtgvoip')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
class VoIP extends Tools
|
class VoIP
|
||||||
{
|
{
|
||||||
use \danog\MadelineProto\VoIP\MessageHandler;
|
use \danog\MadelineProto\VoIP\MessageHandler;
|
||||||
use \danog\MadelineProto\VoIP\AckHandler;
|
use \danog\MadelineProto\VoIP\AckHandler;
|
||||||
@ -125,6 +134,16 @@ class VoIP extends Tools
|
|||||||
private $outputFile;
|
private $outputFile;
|
||||||
private $isPlaying = false;
|
private $isPlaying = false;
|
||||||
|
|
||||||
|
private bool $creator;
|
||||||
|
|
||||||
|
private PermAuthKey $authKey;
|
||||||
|
private int $peerVersion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Endpoint[]
|
||||||
|
*/
|
||||||
|
private array $sockets = [];
|
||||||
|
|
||||||
private $connection_settings = [];
|
private $connection_settings = [];
|
||||||
private $dclist = [];
|
private $dclist = [];
|
||||||
|
|
||||||
@ -191,13 +210,12 @@ class VoIP extends Tools
|
|||||||
|
|
||||||
public function startTheMagic()
|
public function startTheMagic()
|
||||||
{
|
{
|
||||||
while (true) {
|
foreach ($this->sockets as $socket) {
|
||||||
$waiting = $this->datacenter->select();
|
Tools::callFork(function () use ($socket) {
|
||||||
foreach ($waiting as $dc) {
|
while ($payload = $this->recv_message($socket)) {
|
||||||
if ($packet = $this->recv_message($dc)) {
|
Tools::callFork($this->handlePacket($socket, $payload));
|
||||||
$this->handlePacket($dc, $packet);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -208,14 +226,31 @@ class VoIP extends Tools
|
|||||||
case self::PKT_INIT:
|
case self::PKT_INIT:
|
||||||
$this->voip_state = self::STATE_WAIT_INIT_ACK;
|
$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);
|
$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;
|
break;
|
||||||
case self::PKT_INIT_ACK:
|
case self::PKT_INIT_ACK:
|
||||||
|
if ($this->voip_state !== self::STATE_ESTABLISHED) {
|
||||||
$this->voip_state = self::STATE_ESTABLISHED;
|
$this->voip_state = self::STATE_ESTABLISHED;
|
||||||
$a = \fopen('paloma.opus', 'rb');
|
|
||||||
(new Ogg($a, [$this, 'oggCallback']))->run();
|
|
||||||
|
|
||||||
|
$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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -279,11 +314,6 @@ class VoIP extends Tools
|
|||||||
return $this->callID;
|
return $this->callID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isCreator()
|
|
||||||
{
|
|
||||||
return $this->creator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function whenCreated()
|
public function whenCreated()
|
||||||
{
|
{
|
||||||
return isset($this->internalStorage['created']) ? $this->internalStorage['created'] : false;
|
return isset($this->internalStorage['created']) ? $this->internalStorage['created'] : false;
|
||||||
@ -291,36 +321,16 @@ class VoIP extends Tools
|
|||||||
|
|
||||||
public function parseConfig()
|
public function parseConfig()
|
||||||
{
|
{
|
||||||
|
$this->authKey = new PermAuthKey();
|
||||||
|
$this->authKey->setAuthKey($this->configuration['auth_key']);
|
||||||
if (\count($this->configuration['endpoints'])) {
|
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) {
|
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->sockets['v6 '.$endpoint['id']] = new Endpoint($endpoint['ipv6'], $endpoint['port'], $endpoint['peer_tag'], true, $this);
|
||||||
$this->dclist[$test]['ipv4'][$endpoint['id']] = ['ip_address' => $endpoint['ip'], 'port' => $endpoint['port'], 'peer_tag' => $endpoint['peer_tag']];
|
$this->sockets['v4 '.$endpoint['id']] = new Endpoint($endpoint['ip'], $endpoint['port'], $endpoint['peer_tag'], true, $this);
|
||||||
}
|
}
|
||||||
if (!isset($this->datacenter)) {
|
foreach ($this->sockets as $socket) {
|
||||||
$this->datacenter = new DataCenter($this->dclist, $this->connection_settings);
|
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';
|
$test = $this->connection_settings['all']['test_mode'] ? 'test' : 'main';
|
||||||
foreach ($this->datacenter->sockets as $dc_id => $socket) {
|
foreach ($this->datacenter->sockets as $dc_id => $socket) {
|
||||||
if ($socket->auth_key === null) {
|
$this->send_message(['_' => self::PKT_INIT, 'protocol' => self::PROTOCOL_VERSION, 'min_protocol' => self::MIN_PROTOCOL_VERSION, 'audio_streams' => [self::CODEC_OPUS], 'video_streams' => []], $socket);
|
||||||
$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->voip_state = self::STATE_WAIT_INIT;
|
$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;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ trait AckHandler
|
|||||||
{
|
{
|
||||||
return $s1 > $s2;
|
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)) {
|
if ($this->seqgt($packet_seq_no, $this->session_in_seq_no)) {
|
||||||
$diff = $packet_seq_no - $this->session_in_seq_no;
|
$diff = $packet_seq_no - $this->session_in_seq_no;
|
||||||
|
@ -13,6 +13,9 @@ If not, see <http://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
namespace danog\MadelineProto\VoIP;
|
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.
|
* 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));
|
$concat .= \pack('@'.$this->posmod(-$l - 1, 4));
|
||||||
} else {
|
} else {
|
||||||
$concat .= \chr(254);
|
$concat .= \chr(254);
|
||||||
$concat .= \substr($this->pack_signed_int($l), 0, 3);
|
$concat .= \substr(Tools::packSignedInt($l), 0, 3);
|
||||||
$concat .= $object;
|
$concat .= $object;
|
||||||
$concat .= \pack('@'.$this->posmod(-$l, 4));
|
$concat .= \pack('@'.$this->posmod(-$l, 4));
|
||||||
}
|
}
|
||||||
@ -60,7 +63,7 @@ trait MessageHandler
|
|||||||
public function send_message($args, $datacenter = null)
|
public function send_message($args, $datacenter = null)
|
||||||
{
|
{
|
||||||
if ($datacenter === null) {
|
if ($datacenter === null) {
|
||||||
return $this->send_message($args, \key($this->datacenter->sockets));
|
return $this->send_message($args, \reset($this->sockets));
|
||||||
}
|
}
|
||||||
$message = '';
|
$message = '';
|
||||||
switch ($args['_']) {
|
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;
|
// 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:
|
case \danog\MadelineProto\VoIP::PKT_INIT:
|
||||||
$message .= $this->pack_signed_int($args['protocol']);
|
$message .= Tools::packSignedInt($args['protocol']);
|
||||||
$message .= $this->pack_signed_int($args['min_protocol']);
|
$message .= Tools::packSignedInt($args['min_protocol']);
|
||||||
$flags = 0;
|
$flags = 0;
|
||||||
$flags = isset($args['data_saving_enabled']) && $args['data_saving_enabled'] ? $flags | 1 : $flags & ~1;
|
$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']));
|
$message .= \chr(\count($args['audio_streams']));
|
||||||
foreach ($args['audio_streams'] as $codec) {
|
foreach ($args['audio_streams'] as $codec) {
|
||||||
$message .= \chr($codec);
|
$message .= \chr($codec);
|
||||||
@ -86,8 +89,8 @@ trait MessageHandler
|
|||||||
//
|
//
|
||||||
// packetInitAck#2 protocol:int min_protocol:int all_streams:byteVector<streamType> = Packet;
|
// packetInitAck#2 protocol:int min_protocol:int all_streams:byteVector<streamType> = Packet;
|
||||||
case \danog\MadelineProto\VoIP::PKT_INIT_ACK:
|
case \danog\MadelineProto\VoIP::PKT_INIT_ACK:
|
||||||
$message .= $this->pack_signed_int($args['protocol']);
|
$message .= Tools::packSignedInt($args['protocol']);
|
||||||
$message .= $this->pack_signed_int($args['min_protocol']);
|
$message .= Tools::packSignedInt($args['min_protocol']);
|
||||||
$message .= \chr(\count($args['all_streams']));
|
$message .= \chr(\count($args['all_streams']));
|
||||||
foreach ($args['all_streams'] as $stream) {
|
foreach ($args['all_streams'] as $stream) {
|
||||||
$message .= \chr($stream['id']);
|
$message .= \chr($stream['id']);
|
||||||
@ -114,7 +117,7 @@ trait MessageHandler
|
|||||||
$flags = $flags | $args['stream_id'];
|
$flags = $flags | $args['stream_id'];
|
||||||
$message .= \chr($flags);
|
$message .= \chr($flags);
|
||||||
$message .= $length > 255 ? \pack('v', $length) : \chr($length);
|
$message .= $length > 255 ? \pack('v', $length) : \chr($length);
|
||||||
$message .= $this->pack_unsigned_int($args['timestamp']);
|
$message .= Tools::packUnsignedInt($args['timestamp']);
|
||||||
$message .= $args['data'];
|
$message .= $args['data'];
|
||||||
break;
|
break;
|
||||||
/*case \danog\MadelineProto\VoIP::PKT_UPDATE_STREAMS:
|
/*case \danog\MadelineProto\VoIP::PKT_UPDATE_STREAMS:
|
||||||
@ -122,7 +125,7 @@ trait MessageHandler
|
|||||||
case \danog\MadelineProto\VoIP::PKT_PING:
|
case \danog\MadelineProto\VoIP::PKT_PING:
|
||||||
break;*/
|
break;*/
|
||||||
case \danog\MadelineProto\VoIP::PKT_PONG:
|
case \danog\MadelineProto\VoIP::PKT_PONG:
|
||||||
$message .= $this->pack_unsigned_int($args['out_seq_no']);
|
$message .= Tools::packUnsignedInt($args['out_seq_no']);
|
||||||
break;
|
break;
|
||||||
case \danog\MadelineProto\VoIP::PKT_STREAM_DATA_X2:
|
case \danog\MadelineProto\VoIP::PKT_STREAM_DATA_X2:
|
||||||
for ($x = 0; $x < 2; $x++) {
|
for ($x = 0; $x < 2; $x++) {
|
||||||
@ -134,7 +137,7 @@ trait MessageHandler
|
|||||||
$flags = $flags | $args[$x]['stream_id'];
|
$flags = $flags | $args[$x]['stream_id'];
|
||||||
$message .= \chr($flags);
|
$message .= \chr($flags);
|
||||||
$message .= $length > 255 ? \pack('v', $length) : \chr($length);
|
$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'];
|
$message .= $args[$x]['data'];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -148,22 +151,22 @@ trait MessageHandler
|
|||||||
$flags = $flags | $args[$x]['stream_id'];
|
$flags = $flags | $args[$x]['stream_id'];
|
||||||
$message .= \chr($flags);
|
$message .= \chr($flags);
|
||||||
$message .= $length > 255 ? \pack('v', $length) : \chr($length);
|
$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'];
|
$message .= $args[$x]['data'];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
// packetLanEndpoint#A address:int port:int = Packet;
|
// packetLanEndpoint#A address:int port:int = Packet;
|
||||||
case \danog\MadelineProto\VoIP::PKT_LAN_ENDPOINT:
|
case \danog\MadelineProto\VoIP::PKT_LAN_ENDPOINT:
|
||||||
$message .= $this->pack_signed_int($args['address']);
|
$message .= Tools::packSignedInt($args['address']);
|
||||||
$message .= $this->pack_signed_int($args['port']);
|
$message .= Tools::packSignedInt($args['port']);
|
||||||
break;
|
break;
|
||||||
// packetNetworkChanged#B flags:# data_saving_enabled:flags.0?true = Packet;
|
// packetNetworkChanged#B flags:# data_saving_enabled:flags.0?true = Packet;
|
||||||
case \danog\MadelineProto\VoIP::PKT_NETWORK_CHANGED:
|
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;
|
break;
|
||||||
// packetSwitchPreferredRelay#C relay_id:long = Packet;
|
// packetSwitchPreferredRelay#C relay_id:long = Packet;
|
||||||
case \danog\MadelineProto\VoIP::PKT_SWITCH_PREF_RELAY:
|
case \danog\MadelineProto\VoIP::PKT_SWITCH_PREF_RELAY:
|
||||||
$message .= $this->pack_signed_long($args['relay_d']);
|
$message .= Tools::packSignedLong($args['relay_d']);
|
||||||
break;
|
break;
|
||||||
/*case \danog\MadelineProto\VoIP::PKT_SWITCH_TO_P2P:
|
/*case \danog\MadelineProto\VoIP::PKT_SWITCH_TO_P2P:
|
||||||
break;
|
break;
|
||||||
@ -194,11 +197,11 @@ trait MessageHandler
|
|||||||
$flags = isset($args['extra']) ? $flags | 2 : $flags & ~2; // extra
|
$flags = isset($args['extra']) ? $flags | 2 : $flags & ~2; // extra
|
||||||
$flags = \strlen($message) ? $flags | 1 : $flags & ~1; // raw_data
|
$flags = \strlen($message) ? $flags | 1 : $flags & ~1; // raw_data
|
||||||
$flags = $flags | ($args['_'] << 24);
|
$flags = $flags | ($args['_'] << 24);
|
||||||
$payload .= $this->pack_unsigned_int($flags);
|
$payload .= Tools::packUnsignedInt($flags);
|
||||||
$payload .= $this->configuration['call_id'];
|
$payload .= $this->configuration['call_id'];
|
||||||
$payload .= $this->pack_unsigned_int($this->session_in_seq_no);
|
$payload .= Tools::packUnsignedInt($this->session_in_seq_no);
|
||||||
$payload .= $this->pack_unsigned_int($this->session_out_seq_no);
|
$payload .= Tools::packUnsignedInt($this->session_out_seq_no);
|
||||||
$payload .= $this->pack_unsigned_int($ack_mask);
|
$payload .= Tools::packUnsignedInt($ack_mask);
|
||||||
$payload .= \danog\MadelineProto\VoIP::PROTO_ID;
|
$payload .= \danog\MadelineProto\VoIP::PROTO_ID;
|
||||||
if ($flags & 2) {
|
if ($flags & 2) {
|
||||||
$payload .= $this->pack_string($args['extra']);
|
$payload .= $this->pack_string($args['extra']);
|
||||||
@ -211,76 +214,23 @@ trait MessageHandler
|
|||||||
$payload .= $this->random(8);
|
$payload .= $this->random(8);
|
||||||
$payload .= \chr(7);
|
$payload .= \chr(7);
|
||||||
$payload .= $this->random(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);
|
$payload .= $this->pack_string($message);
|
||||||
}
|
}
|
||||||
$this->session_out_seq_no++;
|
$this->session_out_seq_no++;
|
||||||
|
|
||||||
$payload = $this->pack_unsigned_int(\strlen($payload)).$payload;
|
return $datacenter->write($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]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reading connection and receiving message from server.
|
* Reading connection and receiving message from server.
|
||||||
*/
|
*/
|
||||||
public function recv_message($datacenter)
|
public function recv_message(Endpoint $endpoint)
|
||||||
{
|
{
|
||||||
$payload = \fopen('php://memory', 'rw+b');
|
if (!$payload = yield from $endpoint->read()) {
|
||||||
\fwrite($payload, $this->datacenter->sockets[$datacenter]->read_message());
|
return null;
|
||||||
\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 (\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 = [];
|
$result = [];
|
||||||
switch ($crc = \stream_get_contents($payload, 4)) {
|
switch ($crc = \stream_get_contents($payload, 4)) {
|
||||||
@ -296,25 +246,25 @@ trait MessageHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($flags & 16) {
|
if ($flags & 16) {
|
||||||
$in_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($stream, 4))[1];
|
$out_seq_no = \unpack('V', \stream_get_contents($payload, 4))[1];
|
||||||
}
|
}
|
||||||
if ($flags & 32) {
|
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 ($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);
|
\danog\MadelineProto\Logger::log('Protocol mismatch', \danog\MadelineProto\Logger::ERROR);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($flags & 2) {
|
if ($flags & 2) {
|
||||||
$result['extra'] = $this->unpack_string($stream);
|
$result['extra'] = $this->unpack_string($payload);
|
||||||
}
|
}
|
||||||
$message = \fopen('php://memory', 'rw+b');
|
$message = \fopen('php://memory', 'rw+b');
|
||||||
|
|
||||||
if ($flags & 1) {
|
if ($flags & 1) {
|
||||||
\fwrite($message, $this->unpack_string($stream));
|
\fwrite($message, $this->unpack_string($payload));
|
||||||
\fseek($message, 0);
|
\fseek($message, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -324,7 +274,7 @@ trait MessageHandler
|
|||||||
$flags = \unpack('V', \stream_get_contents($payload, 4))[1];
|
$flags = \unpack('V', \stream_get_contents($payload, 4))[1];
|
||||||
|
|
||||||
$message = \fopen('php://memory', 'rw+b');
|
$message = \fopen('php://memory', 'rw+b');
|
||||||
\fwrite($message, $this->unpack_string($stream));
|
\fwrite($message, $this->unpack_string($payload));
|
||||||
\fseek($message, 0);
|
\fseek($message, 0);
|
||||||
$result['_'] = \ord(\stream_get_contents($message, 1));
|
$result['_'] = \ord(\stream_get_contents($message, 1));
|
||||||
$in_seq_no = \unpack('V', \stream_get_contents($message, 4))[1];
|
$in_seq_no = \unpack('V', \stream_get_contents($message, 4))[1];
|
||||||
@ -333,22 +283,22 @@ trait MessageHandler
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case $this->TLID_REFLECTOR_SELF_INFO:
|
case $this->TLID_REFLECTOR_SELF_INFO:
|
||||||
$result['date'] = $this->unpack_signed_int(\stream_get_contents($payload, 4));
|
$result['date'] = Tools::unpackSignedInt(\stream_get_contents($payload, 4));
|
||||||
$result['query_id'] = $this->unpack_signed_long(\stream_get_contents($payload, 8));
|
$result['query_id'] = Tools::unpackSignedLong(\stream_get_contents($payload, 8));
|
||||||
$result['my_ip'] = \stream_get_contents($payload, 16);
|
$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;
|
return $result;
|
||||||
case $this->TLID_REFLECTOR_PEER_INFO:
|
case $this->TLID_REFLECTOR_PEER_INFO:
|
||||||
$result['my_address'] = $this->unpack_signed_int(\stream_get_contents($payload, 4));
|
$result['my_address'] = Tools::unpackSignedInt(\stream_get_contents($payload, 4));
|
||||||
$result['my_port'] = $this->unpack_signed_int(\stream_get_contents($payload, 4));
|
$result['my_port'] = Tools::unpackSignedInt(\stream_get_contents($payload, 4));
|
||||||
$result['peer_address'] = $this->unpack_signed_int(\stream_get_contents($payload, 4));
|
$result['peer_address'] = Tools::unpackSignedInt(\stream_get_contents($payload, 4));
|
||||||
$result['peer_port'] = $this->unpack_signed_int(\stream_get_contents($payload, 4));
|
$result['peer_port'] = Tools::unpackSignedInt(\stream_get_contents($payload, 4));
|
||||||
return $result;
|
return $result;
|
||||||
default:
|
default:
|
||||||
\danog\MadelineProto\Logger::log('Unknown packet received: '.\bin2hex($crc), \danog\MadelineProto\Logger::ERROR);
|
\danog\MadelineProto\Logger::log('Unknown packet received: '.\bin2hex($crc), \danog\MadelineProto\Logger::ERROR);
|
||||||
return false;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
switch ($result['_']) {
|
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;
|
// 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:
|
case \danog\MadelineProto\VoIP::PKT_INIT:
|
||||||
$result['protocol'] = $this->unpack_signed_int(\stream_get_contents($message, 4));
|
$result['protocol'] = Tools::unpackSignedInt(\stream_get_contents($message, 4));
|
||||||
$result['min_protocol'] = $this->unpack_signed_int(\stream_get_contents($message, 4));
|
$result['min_protocol'] = Tools::unpackSignedInt(\stream_get_contents($message, 4));
|
||||||
$flags = \unpack('V', \stream_get_contents($message, 4))[1];
|
$flags = \unpack('V', \stream_get_contents($message, 4))[1];
|
||||||
$result['data_saving_enabled'] = (bool) ($flags & 1);
|
$result['data_saving_enabled'] = (bool) ($flags & 1);
|
||||||
$result['audio_streams'] = [];
|
$result['audio_streams'] = [];
|
||||||
@ -375,8 +325,8 @@ trait MessageHandler
|
|||||||
//
|
//
|
||||||
// packetInitAck#2 protocol:int min_protocol:int all_streams:byteVector<streamType> = Packet;
|
// packetInitAck#2 protocol:int min_protocol:int all_streams:byteVector<streamType> = Packet;
|
||||||
case \danog\MadelineProto\VoIP::PKT_INIT_ACK:
|
case \danog\MadelineProto\VoIP::PKT_INIT_ACK:
|
||||||
$result['protocol'] = $this->unpack_signed_int(\stream_get_contents($message, 4));
|
$result['protocol'] = Tools::unpackSignedInt(\stream_get_contents($message, 4));
|
||||||
$result['min_protocol'] = $this->unpack_signed_int(\stream_get_contents($message, 4));
|
$result['min_protocol'] = Tools::unpackSignedInt(\stream_get_contents($message, 4));
|
||||||
$result['all_streams'] = [];
|
$result['all_streams'] = [];
|
||||||
$length = \ord(\stream_get_contents($message, 1));
|
$length = \ord(\stream_get_contents($message, 1));
|
||||||
for ($x = 0; $x < $length; $x++) {
|
for ($x = 0; $x < $length; $x++) {
|
||||||
@ -410,8 +360,8 @@ trait MessageHandler
|
|||||||
case \danog\MadelineProto\VoIP::PKT_PING:
|
case \danog\MadelineProto\VoIP::PKT_PING:
|
||||||
break;*/
|
break;*/
|
||||||
case \danog\MadelineProto\VoIP::PKT_PONG:
|
case \danog\MadelineProto\VoIP::PKT_PONG:
|
||||||
if (\fstat($stream)['size'] - \ftell($stream)) {
|
if (\fstat($payload)['size'] - \ftell($payload)) {
|
||||||
$result['out_seq_no'] = \unpack('V', \stream_get_contents($stream, 4))[1];
|
$result['out_seq_no'] = \unpack('V', \stream_get_contents($payload, 4))[1];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case \danog\MadelineProto\VoIP::PKT_STREAM_DATA_X2:
|
case \danog\MadelineProto\VoIP::PKT_STREAM_DATA_X2:
|
||||||
@ -438,16 +388,16 @@ trait MessageHandler
|
|||||||
break;
|
break;
|
||||||
// packetLanEndpoint#A address:int port:int = Packet;
|
// packetLanEndpoint#A address:int port:int = Packet;
|
||||||
case \danog\MadelineProto\VoIP::PKT_LAN_ENDPOINT:
|
case \danog\MadelineProto\VoIP::PKT_LAN_ENDPOINT:
|
||||||
$result['address'] = \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($stream, 4))[1];
|
$result['port'] = \unpack('V', \stream_get_contents($payload, 4))[1];
|
||||||
break;
|
break;
|
||||||
// packetNetworkChanged#B flags:# data_saving_enabled:flags.0?true = Packet;
|
// packetNetworkChanged#B flags:# data_saving_enabled:flags.0?true = Packet;
|
||||||
case \danog\MadelineProto\VoIP::PKT_NETWORK_CHANGED:
|
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;
|
break;
|
||||||
// packetSwitchPreferredRelay#C relay_id:long = Packet;
|
// packetSwitchPreferredRelay#C relay_id:long = Packet;
|
||||||
case \danog\MadelineProto\VoIP::PKT_SWITCH_PREF_RELAY:
|
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;
|
break;
|
||||||
/*case \danog\MadelineProto\VoIP::PKT_SWITCH_TO_P2P:
|
/*case \danog\MadelineProto\VoIP::PKT_SWITCH_TO_P2P:
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user