mirror of
https://github.com/danog/MadelineProto.git
synced 2024-11-27 01:14:39 +01:00
Fixes
This commit is contained in:
parent
0424539a1f
commit
1f608c0a4c
2
docs
2
docs
@ -1 +1 @@
|
|||||||
Subproject commit e83c3ea026fc2142b6558378d0c9636c8c29f248
|
Subproject commit 2afa14cd21754fbbcbc8bd25cecfeb3592662eca
|
@ -1 +1 @@
|
|||||||
Subproject commit 499f1d8ec8f7f2f554d0b347bd06c26404a2e402
|
Subproject commit 3bd78bce691319dc07cadc154056c7b68594eb55
|
2
schemas
2
schemas
@ -1 +1 @@
|
|||||||
Subproject commit 8fd40f0a4170769465e4943e4a5da37bd58f7e88
|
Subproject commit d0b2b612cbece1fd3dc971634326f7470dc0099b
|
@ -231,7 +231,10 @@ trait ResponseHandler
|
|||||||
$body = $request->getBodyOrEmpty();
|
$body = $request->getBodyOrEmpty();
|
||||||
$trimmed = [];
|
$trimmed = [];
|
||||||
if (isset($body['peer'])) {
|
if (isset($body['peer'])) {
|
||||||
$trimmed['peer'] = \is_string($body['peer']) ? $body['peer'] : $this->API->getId($body['peer']);
|
try {
|
||||||
|
$trimmed['peer'] = \is_string($body['peer']) ? $body['peer'] : $this->API->getId($body['peer']);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (isset($body['message'])) {
|
if (isset($body['message'])) {
|
||||||
$trimmed['message'] = (string) $body['message'];
|
$trimmed['message'] = (string) $body['message'];
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
namespace danog\MadelineProto\Stream\Ogg;
|
namespace danog\MadelineProto\Stream\Ogg;
|
||||||
|
|
||||||
use Amp\Emitter;
|
use Amp\Emitter;
|
||||||
|
use danog\MadelineProto\Exception;
|
||||||
use danog\MadelineProto\Logger;
|
use danog\MadelineProto\Logger;
|
||||||
use danog\MadelineProto\Stream\BufferedStreamInterface;
|
use danog\MadelineProto\Stream\BufferedStreamInterface;
|
||||||
use danog\MadelineProto\Stream\BufferInterface;
|
use danog\MadelineProto\Stream\BufferInterface;
|
||||||
@ -307,7 +308,6 @@ class Ogg
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->streamCount = $opus_head['channel_mapping']['stream_count'];
|
$this->streamCount = $opus_head['channel_mapping']['stream_count'];
|
||||||
\var_dump($opus_head);
|
|
||||||
$state = self::STATE_READ_COMMENT;
|
$state = self::STATE_READ_COMMENT;
|
||||||
} elseif ($state === self::STATE_READ_COMMENT) {
|
} elseif ($state === self::STATE_READ_COMMENT) {
|
||||||
$vendor_string_length = \unpack('V', \substr($content, 8, 4))[1];
|
$vendor_string_length = \unpack('V', \substr($content, 8, 4))[1];
|
||||||
|
@ -305,7 +305,7 @@ abstract class Tools extends StrTools
|
|||||||
$resolved = false;
|
$resolved = false;
|
||||||
do {
|
do {
|
||||||
try {
|
try {
|
||||||
Logger::log("Starting event loop...");
|
//Logger::log("Starting event loop...");
|
||||||
Loop::run(function () use (&$resolved, &$value, &$exception, $promise) {
|
Loop::run(function () use (&$resolved, &$value, &$exception, $promise) {
|
||||||
$promise->onResolve(function ($e, $v) use (&$resolved, &$value, &$exception) {
|
$promise->onResolve(function ($e, $v) use (&$resolved, &$value, &$exception) {
|
||||||
Loop::stop();
|
Loop::stop();
|
||||||
|
@ -13,6 +13,7 @@ If not, see <http://www.gnu.org/licenses/>.
|
|||||||
namespace danog\MadelineProto;
|
namespace danog\MadelineProto;
|
||||||
|
|
||||||
use Amp\Delayed;
|
use Amp\Delayed;
|
||||||
|
use Amp\Loop;
|
||||||
use danog\MadelineProto\MTProto\PermAuthKey;
|
use danog\MadelineProto\MTProto\PermAuthKey;
|
||||||
use danog\MadelineProto\Stream\Common\FileBufferedStream;
|
use danog\MadelineProto\Stream\Common\FileBufferedStream;
|
||||||
use danog\MadelineProto\Stream\ConnectionContext;
|
use danog\MadelineProto\Stream\ConnectionContext;
|
||||||
@ -113,7 +114,8 @@ class VoIP
|
|||||||
private $TLID_REFLECTOR_SELF_INFO;
|
private $TLID_REFLECTOR_SELF_INFO;
|
||||||
private $TLID_REFLECTOR_PEER_INFO;
|
private $TLID_REFLECTOR_PEER_INFO;
|
||||||
|
|
||||||
private $MadelineProto;
|
private MTProto $MadelineProto;
|
||||||
|
public MTProto $madeline;
|
||||||
public $received_timestamp_map = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
public $received_timestamp_map = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||||
public $remote_ack_timestamp_map = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
public $remote_ack_timestamp_map = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||||
public $session_out_seq_no = 0;
|
public $session_out_seq_no = 0;
|
||||||
@ -123,7 +125,7 @@ class VoIP
|
|||||||
public $storage = [];
|
public $storage = [];
|
||||||
public $internalStorage = [];
|
public $internalStorage = [];
|
||||||
private $signal = 0;
|
private $signal = 0;
|
||||||
private $callState;
|
private int $callState;
|
||||||
private $callID;
|
private $callID;
|
||||||
private $creatorID;
|
private $creatorID;
|
||||||
private $otherID;
|
private $otherID;
|
||||||
@ -139,69 +141,135 @@ class VoIP
|
|||||||
private PermAuthKey $authKey;
|
private PermAuthKey $authKey;
|
||||||
private int $peerVersion = 0;
|
private int $peerVersion = 0;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Endpoint[]
|
* @var Endpoint[]
|
||||||
*/
|
*/
|
||||||
private array $sockets = [];
|
private array $sockets = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timeout watcher.
|
||||||
|
*/
|
||||||
|
private string $timeoutWatcher;
|
||||||
|
|
||||||
private $connection_settings = [];
|
private $connection_settings = [];
|
||||||
private $dclist = [];
|
private $dclist = [];
|
||||||
|
|
||||||
private $datacenter;
|
private $socket;
|
||||||
|
|
||||||
public function __construct(bool $creator, int $otherID, MTProto $MadelineProto, $callState)
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param boolean $creator
|
||||||
|
* @param integer $otherID
|
||||||
|
* @param MTProto $MadelineProto
|
||||||
|
* @param integer $callState
|
||||||
|
*/
|
||||||
|
public function __construct(bool $creator, int $otherID, MTProto $MadelineProto, int $callState)
|
||||||
{
|
{
|
||||||
$this->creator = $creator;
|
$this->creator = $creator;
|
||||||
$this->otherID = $otherID;
|
$this->otherID = $otherID;
|
||||||
//$this->callID = $callID;
|
|
||||||
$this->madeline = $this->MadelineProto = $MadelineProto;
|
$this->madeline = $this->MadelineProto = $MadelineProto;
|
||||||
$this->callState = $callState;
|
$this->callState = $callState;
|
||||||
//$this->protocol = $protocol;
|
|
||||||
$this->TLID_REFLECTOR_SELF_INFO = \strrev(\hex2bin(self::TLID_REFLECTOR_SELF_INFO_HEX));
|
$this->TLID_REFLECTOR_SELF_INFO = \strrev(\hex2bin(self::TLID_REFLECTOR_SELF_INFO_HEX));
|
||||||
$this->TLID_REFLECTOR_PEER_INFO = \strrev(\hex2bin(self::TLID_REFLECTOR_PEER_INFO_HEX));
|
$this->TLID_REFLECTOR_PEER_INFO = \strrev(\hex2bin(self::TLID_REFLECTOR_PEER_INFO_HEX));
|
||||||
$this->TLID_DECRYPTED_AUDIO_BLOCK = \strrev(\hex2bin(self::TLID_DECRYPTED_AUDIO_BLOCK_HEX));
|
$this->TLID_DECRYPTED_AUDIO_BLOCK = \strrev(\hex2bin(self::TLID_DECRYPTED_AUDIO_BLOCK_HEX));
|
||||||
$this->TLID_SIMPLE_AUDIO_BLOCK = \strrev(\hex2bin(self::TLID_SIMPLE_AUDIO_BLOCK_HEX));
|
$this->TLID_SIMPLE_AUDIO_BLOCK = \strrev(\hex2bin(self::TLID_SIMPLE_AUDIO_BLOCK_HEX));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get max layer.
|
||||||
|
*
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
public static function getConnectionMaxLayer(): int
|
public static function getConnectionMaxLayer(): int
|
||||||
{
|
{
|
||||||
return 92;
|
return 92;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function deInitVoIPController()
|
/**
|
||||||
{
|
* Get debug string.
|
||||||
}
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function getDebugString(): string
|
public function getDebugString(): string
|
||||||
{
|
{
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setCall($callID)
|
/**
|
||||||
|
* Set call constructor.
|
||||||
|
*
|
||||||
|
* @param array $callID
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setCall(array $callID): void
|
||||||
{
|
{
|
||||||
$this->callID = $callID;
|
$this->protocol = $callID['protocol'];
|
||||||
|
$this->callID = [
|
||||||
|
'_' => 'inputPhoneCall',
|
||||||
|
'id' => $callID['id'],
|
||||||
|
'access_hash' => $callID['access_hash']
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setVisualization($visualization)
|
/**
|
||||||
|
* Set emojis.
|
||||||
|
*
|
||||||
|
* @param array $visualization
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setVisualization(array $visualization): void
|
||||||
{
|
{
|
||||||
$this->visualization = $visualization;
|
$this->visualization = $visualization;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVisualization()
|
/**
|
||||||
|
* Get emojis.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getVisualization(): array
|
||||||
{
|
{
|
||||||
return $this->visualization;
|
return $this->visualization;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Discard call.
|
||||||
|
*
|
||||||
|
* @param array $reason
|
||||||
|
* @param array $rating
|
||||||
|
* @param boolean $debug
|
||||||
|
* @return self|false
|
||||||
|
*/
|
||||||
public function discard($reason = ['_' => 'phoneCallDiscardReasonDisconnect'], $rating = [], $debug = false)
|
public function discard($reason = ['_' => 'phoneCallDiscardReasonDisconnect'], $rating = [], $debug = false)
|
||||||
{
|
{
|
||||||
if ($this->callState === self::CALL_STATE_ENDED || empty($this->configuration)) {
|
if ($this->callState === self::CALL_STATE_ENDED || empty($this->configuration)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$this->deinitVoIPController();
|
Logger::log("Now closing $this");
|
||||||
|
if (isset($this->timeoutWatcher)) {
|
||||||
|
Loop::cancel($this->timeoutWatcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger::log("Closing all sockets in $this");
|
||||||
|
foreach ($this->sockets as $socket) {
|
||||||
|
$socket->disconnect();
|
||||||
|
}
|
||||||
|
Logger::log("Closed all sockets, discarding $this");
|
||||||
|
|
||||||
return Tools::callFork($this->MadelineProto->discardCall($this->callID, $reason, $rating, $debug));
|
return Tools::callFork($this->MadelineProto->discardCall($this->callID, $reason, $rating, $debug));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function __destruct()
|
||||||
|
{
|
||||||
|
$this->discard(['_' => 'phoneCallDiscardReasonDisconnect']);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Accept call.
|
||||||
|
*
|
||||||
|
* @return self|false
|
||||||
|
*/
|
||||||
public function accept()
|
public function accept()
|
||||||
{
|
{
|
||||||
if ($this->callState !== self::CALL_STATE_INCOMING) {
|
if ($this->callState !== self::CALL_STATE_INCOMING) {
|
||||||
@ -218,13 +286,26 @@ class VoIP
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function close()
|
/**
|
||||||
{
|
* Last incoming timestamp.
|
||||||
$this->deinitVoIPController();
|
*
|
||||||
}
|
* @var float
|
||||||
|
*/
|
||||||
public function startTheMagic()
|
private $lastIncomingTimestamp = 0.0;
|
||||||
|
/**
|
||||||
|
* Start the actual call.
|
||||||
|
*/
|
||||||
|
public function startTheMagic(): self
|
||||||
{
|
{
|
||||||
|
if ($this->voip_state !== self::STATE_CREATED) {
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
$this->voip_state = self::STATE_WAIT_INIT;
|
||||||
|
$this->timeoutWatcher = Loop::repeat(10000, function () {
|
||||||
|
if (\microtime(true) - $this->lastIncomingTimestamp > 10) {
|
||||||
|
$this->discard(['_' => 'phoneCallDiscardReasonDisconnect']);
|
||||||
|
}
|
||||||
|
});
|
||||||
Tools::callFork((function () {
|
Tools::callFork((function () {
|
||||||
$this->authKey = new PermAuthKey();
|
$this->authKey = new PermAuthKey();
|
||||||
$this->authKey->setAuthKey($this->configuration['auth_key']);
|
$this->authKey->setAuthKey($this->configuration['auth_key']);
|
||||||
@ -237,160 +318,257 @@ class VoIP
|
|||||||
try {
|
try {
|
||||||
yield from $socket->connect();
|
yield from $socket->connect();
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
Logger::log($e);
|
|
||||||
unset($this->sockets[$k]);
|
unset($this->sockets[$k]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->init_all();
|
foreach ($this->sockets as $socket) {
|
||||||
Tools::callFork((function () use ($socket) {
|
$this->send_message(['_' => self::PKT_INIT, 'protocol' => self::PROTOCOL_VERSION, 'min_protocol' => self::MIN_PROTOCOL_VERSION, 'audio_streams' => [self::CODEC_OPUS], 'video_streams' => []], $socket);
|
||||||
while ($payload = yield from $this->recv_message($socket)) {
|
Tools::callFork((function () use ($socket) {
|
||||||
Tools::callFork($this->handlePacket($socket, $payload));
|
while ($payload = yield from $this->recv_message($socket)) {
|
||||||
}
|
$this->lastIncomingTimestamp = \microtime(true);
|
||||||
})());
|
Tools::callFork($this->handlePacket($socket, $payload));
|
||||||
|
}
|
||||||
|
Logger::log("Exiting VoIP read loop in $this!");
|
||||||
|
})());
|
||||||
|
}
|
||||||
})());
|
})());
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
public function handlePacket($datacenter, $packet)
|
/**
|
||||||
|
* Handle incoming packet.
|
||||||
|
*/
|
||||||
|
private function handlePacket(Endpoint $socket, array $packet): \Generator
|
||||||
{
|
{
|
||||||
//\var_dump($packet);
|
|
||||||
switch ($packet['_']) {
|
switch ($packet['_']) {
|
||||||
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]]], $socket);
|
||||||
|
|
||||||
if ($this->voip_state !== self::STATE_ESTABLISHED) {
|
yield from $this->startWriteLoop($socket);
|
||||||
$this->voip_state = self::STATE_ESTABLISHED;
|
|
||||||
|
|
||||||
$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, $datacenter) {
|
|
||||||
$timestamp = 0;
|
|
||||||
$frames = [];
|
|
||||||
while (yield $it->advance()) {
|
|
||||||
$frames []= $it->getCurrent();
|
|
||||||
}
|
|
||||||
foreach ($frames as $frame) {
|
|
||||||
$t = (\microtime(true) / 1000) + 60;
|
|
||||||
yield $this->send_message(['_' => self::PKT_STREAM_DATA, 'stream_id' => 0, 'data' => $frame, 'timestamp' => $timestamp], $datacenter);
|
|
||||||
|
|
||||||
yield new Delayed((int) ($t - (\microtime(true) / 1000)));
|
|
||||||
|
|
||||||
$timestamp += 60;
|
|
||||||
}
|
|
||||||
})());
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case self::PKT_INIT_ACK:
|
case self::PKT_INIT_ACK:
|
||||||
|
yield from $this->startWriteLoop($socket);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public $timestamp = 0;
|
/**
|
||||||
public function oggCallback($data)
|
* Start write loop.
|
||||||
|
*
|
||||||
|
* @param Endpoint $socket
|
||||||
|
* @return \Generator
|
||||||
|
*/
|
||||||
|
private function startWriteLoop(Endpoint $socket): \Generator
|
||||||
{
|
{
|
||||||
\var_dump(\strlen($data));
|
if ($this->voip_state !== self::STATE_ESTABLISHED) {
|
||||||
$this->send_message(['_' => self::PKT_STREAM_DATA, 'stream_id' => 0, 'data' => $data, 'timestamp' => $this->timestamp]);
|
$this->voip_state = self::STATE_ESTABLISHED;
|
||||||
$this->timestamp += 60;
|
|
||||||
|
$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, $socket) {
|
||||||
|
$timestamp = 0;
|
||||||
|
$frames = [];
|
||||||
|
while (yield $it->advance()) {
|
||||||
|
$frames []= $it->getCurrent();
|
||||||
|
}
|
||||||
|
foreach ($frames as $k => $frame) {
|
||||||
|
$t = (\microtime(true) / 1000) + 60;
|
||||||
|
if (!yield $this->send_message(['_' => self::PKT_STREAM_DATA, 'stream_id' => 0, 'data' => $frame, 'timestamp' => $timestamp], $socket)) {
|
||||||
|
Logger::log("Exiting VoIP write loop in $this!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Logger::log("Writing $k in $this!");
|
||||||
|
yield new Delayed((int) ($t - (\microtime(true) / 1000)));
|
||||||
|
|
||||||
|
$timestamp += 60;
|
||||||
|
}
|
||||||
|
})());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public function play($file)
|
/**
|
||||||
|
* Play file.
|
||||||
|
*
|
||||||
|
* @param string $file
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function play(string $file): self
|
||||||
{
|
{
|
||||||
$this->inputFiles[] = $file;
|
$this->inputFiles[] = $file;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function then($file)
|
/**
|
||||||
|
* Play file.
|
||||||
|
*
|
||||||
|
* @param string $file
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function then(string $file): self
|
||||||
{
|
{
|
||||||
$this->inputFiles[] = $file;
|
$this->inputFiles[] = $file;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function playOnHold($files)
|
/**
|
||||||
|
* Files to play on hold.
|
||||||
|
*
|
||||||
|
* @param array $files
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function playOnHold(array $files): self
|
||||||
{
|
{
|
||||||
$this->holdFiles = $files;
|
$this->holdFiles = $files;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setOutputFile($file)
|
/**
|
||||||
|
* Set output file.
|
||||||
|
*
|
||||||
|
* @param string $file
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function setOutputFile(string $file): self
|
||||||
{
|
{
|
||||||
$this->outputFile = $file;
|
$this->outputFile = $file;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function unsetOutputFile()
|
/**
|
||||||
|
* Unset output file.
|
||||||
|
*
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function unsetOutputFile(): self
|
||||||
{
|
{
|
||||||
$this->outputFile = null;
|
$this->outputFile = null;
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setMadeline($MadelineProto)
|
|
||||||
|
/**
|
||||||
|
* Set MadelineProto instance.
|
||||||
|
*
|
||||||
|
* @param MTProto $MadelineProto
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setMadeline(MTProto $MadelineProto): void
|
||||||
{
|
{
|
||||||
$this->MadelineProto = $MadelineProto;
|
$this->MadelineProto = $this->madeline = $MadelineProto;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getProtocol()
|
/**
|
||||||
|
* Get call protocol.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getProtocol(): array
|
||||||
{
|
{
|
||||||
return $this->protocol;
|
return $this->protocol;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getOtherID()
|
/**
|
||||||
|
* Get ID of other user.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getOtherID(): int
|
||||||
{
|
{
|
||||||
return $this->otherID;
|
return $this->otherID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get call ID.
|
||||||
|
*
|
||||||
|
* @return string|int
|
||||||
|
*/
|
||||||
public function getCallID()
|
public function getCallID()
|
||||||
{
|
{
|
||||||
return $this->callID;
|
return $this->callID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get creation date.
|
||||||
|
*
|
||||||
|
* @return int|bool
|
||||||
|
*/
|
||||||
public function whenCreated()
|
public function whenCreated()
|
||||||
{
|
{
|
||||||
return isset($this->internalStorage['created']) ? $this->internalStorage['created'] : false;
|
return isset($this->internalStorage['created']) ? $this->internalStorage['created'] : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function parseConfig()
|
/**
|
||||||
|
* Parse config.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function parseConfig(): void
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
private function init_all()
|
/**
|
||||||
{
|
* Get call state.
|
||||||
foreach ($this->sockets as $socket) {
|
*
|
||||||
$this->send_message(['_' => self::PKT_INIT, 'protocol' => self::PROTOCOL_VERSION, 'min_protocol' => self::MIN_PROTOCOL_VERSION, 'audio_streams' => [self::CODEC_OPUS], 'video_streams' => []], $socket);
|
* @return int
|
||||||
$this->voip_state = self::STATE_WAIT_INIT;
|
*/
|
||||||
}
|
public function getCallState(): int
|
||||||
}
|
|
||||||
|
|
||||||
public function getCallState()
|
|
||||||
{
|
{
|
||||||
return $this->callState;
|
return $this->callState;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVersion()
|
/**
|
||||||
|
* Get library version.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getVersion(): string
|
||||||
{
|
{
|
||||||
return 'libponyvoip-1.0';
|
return 'libponyvoip-1.0';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPreferredRelayID()
|
/**
|
||||||
|
* Get preferred relay ID.
|
||||||
|
*
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function getPreferredRelayID(): int
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLastError()
|
/**
|
||||||
|
* Get last error.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getLastError(): string
|
||||||
{
|
{
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDebugLog()
|
/**
|
||||||
|
* Get debug log.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDebugLog(): string
|
||||||
{
|
{
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSignalBarsCount()
|
/**
|
||||||
|
* Get signal bar count.
|
||||||
|
*/
|
||||||
|
public function getSignalBarsCount(): int
|
||||||
{
|
{
|
||||||
return $this->signal;
|
return $this->signal;
|
||||||
}
|
}
|
||||||
@ -424,4 +602,15 @@ class VoIP
|
|||||||
{
|
{
|
||||||
return $this->peerVersion;
|
return $this->peerVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get call representation.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
$id = $this->callID['id'];
|
||||||
|
return "call {$id} with {$this->otherID}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ namespace danog\MadelineProto\VoIP;
|
|||||||
|
|
||||||
use Amp\Promise;
|
use Amp\Promise;
|
||||||
use Amp\Socket\EncryptableSocket;
|
use Amp\Socket\EncryptableSocket;
|
||||||
|
use Amp\Success;
|
||||||
use danog\MadelineProto\MTProto\PermAuthKey;
|
use danog\MadelineProto\MTProto\PermAuthKey;
|
||||||
use danog\MadelineProto\MTProtoTools\Crypt;
|
use danog\MadelineProto\MTProtoTools\Crypt;
|
||||||
use danog\MadelineProto\VoIP;
|
use danog\MadelineProto\VoIP;
|
||||||
@ -37,7 +38,7 @@ class Endpoint
|
|||||||
/**
|
/**
|
||||||
* The socket.
|
* The socket.
|
||||||
*/
|
*/
|
||||||
private EncryptableSocket $socket;
|
private ?EncryptableSocket $socket = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether we're the creator.
|
* Whether we're the creator.
|
||||||
@ -78,6 +79,18 @@ class Endpoint
|
|||||||
$this->socket = yield connect("udp://{$this->ip}:{$this->port}");
|
$this->socket = yield connect("udp://{$this->ip}:{$this->port}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disconnect from endpoint.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function disconnect(): void
|
||||||
|
{
|
||||||
|
if ($this->socket !== null) {
|
||||||
|
$this->socket->close();
|
||||||
|
$this->socket = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Read packet.
|
* Read packet.
|
||||||
*
|
*
|
||||||
@ -139,6 +152,9 @@ class Endpoint
|
|||||||
*/
|
*/
|
||||||
public function write(string $payload): Promise
|
public function write(string $payload): Promise
|
||||||
{
|
{
|
||||||
|
if ($this->socket === null) {
|
||||||
|
return new Success(0);
|
||||||
|
}
|
||||||
$plaintext = \pack('v', \strlen($payload)).$payload;
|
$plaintext = \pack('v', \strlen($payload)).$payload;
|
||||||
$padding = 16 - (\strlen($plaintext) % 16);
|
$padding = 16 - (\strlen($plaintext) % 16);
|
||||||
if ($padding < 16) {
|
if ($padding < 16) {
|
||||||
|
@ -82,7 +82,7 @@ if (\class_exists(VoIPServerConfig::class)) {
|
|||||||
/**
|
/**
|
||||||
* Get final settings.
|
* Get final settings.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return array
|
||||||
*/
|
*/
|
||||||
public static function getFinal(): array
|
public static function getFinal(): array
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user