diff --git a/lua/madeline.php b/lua/madeline.php
index a95a1bf9..b4ea2da8 100755
--- a/lua/madeline.php
+++ b/lua/madeline.php
@@ -55,7 +55,7 @@ if (!is_object($Lua)) {
}
$offset = 0;
while (true) {
- $updates = $Lua->MadelineProto->API->get_updates(['offset' => $offset, 'limit' => 50, 'timeout' => 0]); // Just like in the bot API, you can specify an offset, a limit and a timeout
+ $updates = $Lua->MadelineProto->get_updates(['offset' => $offset, 'limit' => 50, 'timeout' => 0]); // Just like in the bot API, you can specify an offset, a limit and a timeout
foreach ($updates as $update) {
$offset = $update['update_id'] + 1; // Just like in the bot API, the offset must be set to the last update_id
$Lua->madeline_update_callback($update['update']);
diff --git a/lua/td.php b/lua/td.php
index 7b2244ed..95c53259 100755
--- a/lua/td.php
+++ b/lua/td.php
@@ -56,7 +56,7 @@ if (!is_object($Lua)) {
$offset = 0;
while (true) {
- $updates = $Lua->MadelineProto->API->get_updates(['offset' => $offset, 'limit' => 50, 'timeout' => 0]); // Just like in the bot API, you can specify an offset, a limit and a timeout
+ $updates = $Lua->MadelineProto->get_updates(['offset' => $offset, 'limit' => 50, 'timeout' => 0]); // Just like in the bot API, you can specify an offset, a limit and a timeout
foreach ($updates as $update) {
$offset = $update['update_id'] + 1; // Just like in the bot API, the offset must be set to the last update_id
$Lua->tdcli_update_callback($update['update']);
diff --git a/phartesting.php b/phartesting.php
index 3557397c..c3a81009 100755
--- a/phartesting.php
+++ b/phartesting.php
@@ -107,7 +107,7 @@ if (stripos(readline('Do you want to handle incoming calls? (y/n): '), 'y') !==
$howmany = readline('How many calls would you like me to handle? ');
$offset = 0;
while ($howmany > 0) {
- $updates = $MadelineProto->API->get_updates(['offset' => $offset, 'limit' => 50, 'timeout' => 0]); // Just like in the bot API, you can specify an offset, a limit and a timeout
+ $updates = $MadelineProto->get_updates(['offset' => $offset, 'limit' => 50, 'timeout' => 0]); // Just like in the bot API, you can specify an offset, a limit and a timeout
foreach ($updates as $update) {
\danog\MadelineProto\Logger::log($update);
$offset = $update['update_id'] + 1; // Just like in the bot API, the offset must be set to the last update_id
@@ -135,7 +135,7 @@ if (stripos(readline('Do you want to make the secret chat tests? (y/n): '), 'y')
\danog\MadelineProto\Logger::log($sentMessage, \danog\MadelineProto\Logger::NOTICE);
/*
while (true) {
- $updates = $MadelineProto->API->get_updates(['offset' => $offset, 'limit' => 50, 'timeout' => 0]); // Just like in the bot API, you can specify an offset, a limit and a timeout
+ $updates = $MadelineProto->get_updates(['offset' => $offset, 'limit' => 50, 'timeout' => 0]); // Just like in the bot API, you can specify an offset, a limit and a timeout
//\danog\MadelineProto\Logger::log($updates);
foreach ($updates as $update) {
$offset = $update['update_id'] + 1; // Just like in the bot API, the offset must be set to the last update_id
diff --git a/socket.php b/socket.php
index fd349ea2..d79ba168 100644
--- a/socket.php
+++ b/socket.php
@@ -1,3 +1,6 @@
AF_INET, 'protocol' => 0, 'address' => 'localhost', 'port' => 8005]);
+$handler->start();
diff --git a/src/Socket.php b/src/Socket.php
index e72cf3a7..2e4603cd 100644
--- a/src/Socket.php
+++ b/src/Socket.php
@@ -120,13 +120,13 @@ If not, see .
if (!extension_loaded('pthreads')) {
if (extension_loaded('sockets')) {
- class Socket
+ class SocketBase
{
private $sock;
- public function __construct(int $domain, int $type, int $protocol)
+ public function __construct($sock)
{
- $this->sock = socket_create($domain, $type, $protocol);
+ $this->sock = $sock;
}
public function __destruct()
@@ -170,7 +170,11 @@ if (!extension_loaded('pthreads')) {
public function accept()
{
- return socket_accept($this->sock);
+ if ($socket = socket_accept($this->sock)) {
+ return new SocketBase($socket);
+ } else {
+ return $socket;
+ }
}
public function connect(string $address, int $port = 0)
@@ -222,6 +226,13 @@ if (!extension_loaded('pthreads')) {
return $port ? ['host' => $address, 'port' => $port] : ['host' => $address];
}
}
+ class Socket extends SocketBase
+ {
+ public function __construct(int $domain, int $type, int $protocol)
+ {
+ parent::__construct(socket_create($domain, $type, $protocol));
+ }
+ }
} else {
define('AF_INET', 0);
define('AF_INET6', 1);
diff --git a/src/danog/MadelineProto/API.php b/src/danog/MadelineProto/API.php
index b23dffda..4010b290 100644
--- a/src/danog/MadelineProto/API.php
+++ b/src/danog/MadelineProto/API.php
@@ -22,7 +22,6 @@ class API extends APIFactory
public function __magic_construct($params = [])
{
set_error_handler(['\\danog\\MadelineProto\\Exception', 'ExceptionErrorHandler']);
- set_exception_handler(['\\danog\\MadelineProto\\Serialization', 'serialize_all']);
if (is_string($params)) {
$realpaths = Serialization::realpaths($params);
if (file_exists($realpaths['file'])) {
diff --git a/src/danog/MadelineProto/Connection.php b/src/danog/MadelineProto/Connection.php
index d66456e0..faf9b6a3 100644
--- a/src/danog/MadelineProto/Connection.php
+++ b/src/danog/MadelineProto/Connection.php
@@ -236,13 +236,10 @@ class Connection
}
return $wrote;
- break;
case 'udp':
throw new Exception(\danog\MadelineProto\Lang::$current_lang['protocol_not_implemented']);
- break;
default:
throw new Exception(\danog\MadelineProto\Lang::$current_lang['protocol_invalid']);
- break;
}
}
diff --git a/src/danog/MadelineProto/Server.php b/src/danog/MadelineProto/Server.php
index 97241aae..19fd8d0c 100644
--- a/src/danog/MadelineProto/Server.php
+++ b/src/danog/MadelineProto/Server.php
@@ -23,7 +23,9 @@ class Server
public function __construct($settings)
{
+ set_error_handler(['\\danog\\MadelineProto\\Exception', 'ExceptionErrorHandler']);
$this->settings = $settings;
+ $this->main = getmypid();
}
public function start()
@@ -32,15 +34,24 @@ class Server
pcntl_signal(SIGINT, [$this, 'sig_handler']);
pcntl_signal(SIGCHLD, [$this, 'sig_handler']);
- $this->sock = new Socket($this->settings['type'], SOCK_STREAM, $this->settings['protocol']);
+ $this->sock = new \Socket($this->settings['type'], SOCK_STREAM, $this->settings['protocol']);
$this->sock->bind($this->settings['address'], $this->settings['port']);
$this->sock->listen();
$this->sock->setBlocking(true);
+
+ $timeout = 2;
+ $this->sock->setOption(\SOL_SOCKET, \SO_RCVTIMEO, $timeout);
+ $this->sock->setOption(\SOL_SOCKET, \SO_SNDTIMEO, $timeout);
while (true) {
- $this->handle($this->sock->accept());
+ pcntl_signal_dispatch();
+ try {
+ if ($sock = $this->sock->accept()) {
+ $this->handle($sock);
+ }
+ } catch (\danog\MadelineProto\Exception $e) {
+ }
}
}
-
private function handle($socket)
{
$pid = pcntl_fork();
@@ -49,16 +60,21 @@ class Server
} elseif ($pid) {
return $this->pids[] = $pid;
}
- $handler = new \danog\MadelineProto\Server\Handler($socket);
+ $handler = new \danog\MadelineProto\Server\Handler($socket, 'tcp_abridged', null, null, null, null, null);
$handler->loop();
die;
}
public function __destruct()
{
- foreach ($this->pid as $pid) {
- pcntl_wait($pid);
+ if (!\danog\MadelineProto\Logger::$is_fork) {
+ \danog\MadelineProto\Logger::log('Shutting main process down');
+ foreach ($this->pids as $pid) {
+ pcntl_wait($pid);
+ }
+ return;
}
+ \danog\MadelineProto\Logger::log('Shutting fork '.getmypid().' down');
}
public function sig_handler($sig)
@@ -66,6 +82,7 @@ class Server
switch ($sig) {
case SIGTERM:
case SIGINT:
+ Logger::log('Got SIGTERM/SIGINT in '.getmypid());
exit();
case SIGCHLD:
diff --git a/src/danog/MadelineProto/Server/Handler.php b/src/danog/MadelineProto/Server/Handler.php
index 49dc20a7..9500641a 100644
--- a/src/danog/MadelineProto/Server/Handler.php
+++ b/src/danog/MadelineProto/Server/Handler.php
@@ -16,24 +16,123 @@ namespace danog\MadelineProto\Server;
/*
* Socket handler for server
*/
-class Handler
+class Handler extends \danog\MadelineProto\Connection
{
- private $socket;
+ use \danog\MadelineProto\TL\TL;
+ use \danog\MadelineProto\Tools;
+ private $madeline;
- public function __construct($socket)
+ public function __magic_construct($socket, $extra, $ip, $port, $protocol, $timeout, $ipv6)
{
- $this->socket = $socket;
+ $this->sock = $socket;
+ $this->sock->setBlocking(true);
+ $this->protocol = $protocol;
+ $this->construct_TL(['socket' => __DIR__.'/../TL_socket.tl']);
+ }
+ public function __destruct() {
+ unset($this->sock);
+ $this->destruct_madeline();
+ exit();
+ }
+ public function destruct_madeline() {
+ if ($this->madeline !== null) {
+ $this->madeline->settings['logger'] = ['logger' => 0];
+ $this->madeline->serialize();
+ unset($this->madeline);
+ return true;
+ }
+ return false;
}
-
public function loop()
{
- }
+ while (true) {
+ $request_id = 0;
+ try {
+ $message = $this->read_message();
+ } catch (\danog\MadelineProto\NothingInTheSocketException $e) {
+ continue;
+ }
+ if ($message === null) {
+ continue;
+ }
+ try {
+ $message = $this->deserialize($message, ['type' => '', 'datacenter' => '']);
+ if ($message['_'] !== 'socketMessageRequest') {
+ throw new \danog\MadelineProto\Exception('Invalid object received');
+ }
+ $request_id = $message['request_id'];
+ $this->send_response($request_id, $this->on_request($request_id, $message['method'], $message['args']));
+ } catch (\danog\MadelineProto\TL\Exception $e) {
+ $this->send_exception($request_id, $e);
+ continue;
+ } catch (\danog\MadelineProto\Exception $e) {
+ $this->send_exception($request_id, $e);
+ continue;
+ } catch (\danog\MadelineProto\RPCErrorException $e) {
+ $this->send_exception($request_id, $e);
+ continue;
+ } catch (\DOMException $e) {
+ $this->send_exception($request_id, $e);
+ continue;
+ }
- public function read_payload()
- {
+ }
}
+ public function on_request($method, $args) {
+ if (count($method) === 0 || count($method) > 2) {
+ throw new \danog\MadelineProto\Exception('Invalid method called');
+ }
+ if ($method[0] === '__construct') {
+ if (count($args) === 1 && is_array($args[0])) {
+ $args[0]['logger'] = ['logger' => 4, 'logger_param' => [$this, 'logger']];
+ $args[0]['updates']['callback'] = [$this, 'update_handler'];
+ } else if (count($args) === 2 && is_array($args[1])) {
+ $args[1]['logger'] = ['logger' => 4, 'logger_param' => [$this, 'logger']];
+ $args[1]['updates']['callback'] = [$this, 'update_handler'];
+ }
+ $this->madeline = new \danog\MadelineProto\API(...$args);
+ return true;
+ }
+ if ($method[0] === '__destruct') {
+ return $this->destruct_madeline();
+ }
+ if ($this->madeline === null) {
+ throw new \danog\MadelineProto\Exception('__construct was not called');
+ }
+ foreach ($args as &$arg) {
+ if (is_array($arg) && isset($arg['_'])){
+ if ($arg['_'] === 'callback' && isset($arg['callback']) && !method_exists($this, $arg['callback'])) {
+ $arg = [$this, $arg['callback']];
+ }
+ if ($arg['_'] === 'stream' && isset($arg['stream_id'])) {
+ $arg = fopen('madelineSocket://', 'r+b', false, Handler::getContext($this, $arg['stream_id']));
+ }
+ }
+ }
+ if (count($method) === 1) {
+ return $this->madeline->{$method[0]}(...$args);
+ }
+ if (count($method) === 2) {
+ return $this->madeline->{$method[0]}->{$method[1]}(...$args);
+ }
+ }
+ public function send_exception($request_id, $e) {
+ echo $e;
+ //$this->send_message($this->serialize_object(['type' => 'socketMessageException'], ['request_id' => $request_id, 'exception' => $e]));
+ }
+ public function send_response($request_id, $response) {
+ $this->send_message($this->serialize_object(['type' => 'socketMessageResponse'], ['request_id' => $request_id, 'data' => $response]));
+ }
+ public function send_data($stream_id, $data) {
+ $this->send_message($this->serialize_object(['type' => 'socketMessageRawData'], ['stream_id' => $stream_id, 'data' => $data]));
+ }
+ public function logger($message, $level) {
- public function write_payload($payload)
- {
+ }
+ public function update_handler($update) {
+ $this->send_message($this->serialize_object(['type' => 'socketMessageUpdate'], ['data' => $update]));
+ }
+ public function __call($method, $args) {
+ $this->send_message($this->serialize_object(['type' => 'socketMessageRequest'], ['request_id' => 0, 'method' => $method, 'args' => $args]));
}
}
diff --git a/src/danog/MadelineProto/Server/Stream.php b/src/danog/MadelineProto/Server/Stream.php
new file mode 100644
index 00000000..a9baca3d
--- /dev/null
+++ b/src/danog/MadelineProto/Server/Stream.php
@@ -0,0 +1,57 @@
+.
+*/
+
+namespace danog\MadelineProto\Server;
+
+
+class Stream
+{
+ const WRAPPER_NAME = 'madelineSocket';
+
+ public $context;
+ private $_handler;
+ private $_stream_id;
+
+ private static $_isRegistered = false;
+
+ public static function getContext($handler, $stream_id)
+ {
+ if (!self::$_isRegistered) {
+ stream_wrapper_register(self::WRAPPER_NAME, get_class());
+ self::$_isRegistered = true;
+ }
+ return stream_context_create(array(self::WRAPPER_NAME => ['handler' => $handler, $stream_id]));
+ }
+
+ public function stream_open($path, $mode, $options, &$opened_path)
+ {
+ $opt = stream_context_get_options($this->context);
+ if (!is_array($opt[self::WRAPPER_NAME]) ||
+ !isset($opt[self::WRAPPER_NAME]['handler']) ||
+ !($opt[self::WRAPPER_NAME]['handler'] instanceof Handler)
+ !isset($opt[self::WRAPPER_NAME]['stream_id']) ||
+ !is_integer($opt[self::WRAPPER_NAME]['stream_id'])) return false;
+ $this->_handler = $opt[self::WRAPPER_NAME]['handler'];
+ $this->_stream_id = $opt[self::WRAPPER_NAME]['stream_id'];
+ return true;
+ }
+
+ public function stream_write($data)
+ {
+ $this->handler->send_data($this->_stream_id, $data);
+ }
+
+ public function stream_lock($mode) {
+
+ }
+}
\ No newline at end of file
diff --git a/src/danog/MadelineProto/TL_socket.tl b/src/danog/MadelineProto/TL_socket.tl
new file mode 100644
index 00000000..ad975cd4
--- /dev/null
+++ b/src/danog/MadelineProto/TL_socket.tl
@@ -0,0 +1,18 @@
+
+dataJSON#7d748d04 data:string = DataJSON;
+
+socketMessageRequest request_id:int method:vector args:vector<%DataJSON> = SocketMessage;
+socketMessageResponse request_id:int data:%DataJSON = SocketMessage;
+socketMessageException request_id:int exception:SocketException = SocketMessage;
+socketMessageUpdate data:%DataJSON = SocketMessage;
+socketMessageLog flags:# thread:flags.0?true process:flags.1?true additional:flags.2?string file:flags.3?string level:int data:string = SocketMessage;
+socketMessageRawData stream_id:int data:bytes = SocketMessage;
+
+socketException message:string code:int trace:%SocketTLTrace = SocketException;
+socketRPCErrorException flags:# rpc_message:flags.0?string message:flags.1?string code:int trace:%SocketTLTrace = SocketException;
+socketTLException message:string code:int trace:%SocketTLTrace = SocketException;
+socketDOMException message:string code:int trace:%SocketTLTrace = SocketException;
+
+socketTLTrace frames:vector<%SocketTLFrame> = SocketTLTrace;
+
+socketTLFrame flags:# file:flags.0?string line:flags.1?string function:flags.2?string args:flags.3?string tl_param:flags.4?string = SocketTLFrame;
\ No newline at end of file
diff --git a/tests/testing.php b/tests/testing.php
index d9db6b8c..e8cc11ba 100755
--- a/tests/testing.php
+++ b/tests/testing.php
@@ -113,7 +113,7 @@ if (stripos(readline('Do you want to handle incoming calls? (y/n): '), 'y') !==
$howmany = readline('How many calls would you like me to handle? ');
$offset = 0;
while ($howmany > 0) {
- $updates = $MadelineProto->API->get_updates(['offset' => $offset, 'limit' => 50, 'timeout' => 0]); // Just like in the bot API, you can specify an offset, a limit and a timeout
+ $updates = $MadelineProto->get_updates(['offset' => $offset, 'limit' => 50, 'timeout' => 0]); // Just like in the bot API, you can specify an offset, a limit and a timeout
foreach ($updates as $update) {
\danog\MadelineProto\Logger::log($update);
$offset = $update['update_id'] + 1; // Just like in the bot API, the offset must be set to the last update_id
@@ -141,7 +141,7 @@ if (stripos(readline('Do you want to make the secret chat tests? (y/n): '), 'y')
\danog\MadelineProto\Logger::log($sentMessage, \danog\MadelineProto\Logger::NOTICE);
/*
while (true) {
- $updates = $MadelineProto->API->get_updates(['offset' => $offset, 'limit' => 50, 'timeout' => 0]); // Just like in the bot API, you can specify an offset, a limit and a timeout
+ $updates = $MadelineProto->get_updates(['offset' => $offset, 'limit' => 50, 'timeout' => 0]); // Just like in the bot API, you can specify an offset, a limit and a timeout
//\danog\MadelineProto\Logger::log($updates);
foreach ($updates as $update) {
$offset = $update['update_id'] + 1; // Just like in the bot API, the offset must be set to the last update_id
diff --git a/userbots/MadelineProto_bot.php b/userbots/MadelineProto_bot.php
index fd36fe10..de502c02 100755
--- a/userbots/MadelineProto_bot.php
+++ b/userbots/MadelineProto_bot.php
@@ -64,7 +64,7 @@ Created by [Daniil Gentili](mention:@danogentili) (@daniilgentili) using the [Ma
echo 'Bot started.'.PHP_EOL;
while (true) {
- $updates = $MadelineProto->API->get_updates(['offset' => $offset, 'limit' => 50, 'timeout' => 0]); // Just like in the bot API, you can specify an offset, a limit and a timeout
+ $updates = $MadelineProto->get_updates(['offset' => $offset, 'limit' => 50, 'timeout' => 0]); // Just like in the bot API, you can specify an offset, a limit and a timeout
foreach ($updates as $update) {
$offset = $update['update_id'] + 1; // Just like in the bot API, the offset must be set to the last update_id
switch ($update['update']['_']) {
diff --git a/userbots/pipesbot.php b/userbots/pipesbot.php
index 393d3ab8..b4e2e451 100755
--- a/userbots/pipesbot.php
+++ b/userbots/pipesbot.php
@@ -107,7 +107,7 @@ Note that the query must be terminated by a \$
Created by @danogentili (@daniilgentili) using the daniil.it/MadelineProto PHP MTProto client.";
while (true) {
- $updates = $MadelineProto->API->get_updates(['offset' => $offset, 'limit' => 50, 'timeout' => 0]); // Just like in the bot API, you can specify an offset, a limit and a timeout
+ $updates = $MadelineProto->get_updates(['offset' => $offset, 'limit' => 50, 'timeout' => 0]); // Just like in the bot API, you can specify an offset, a limit and a timeout
foreach ($updates as $update) {
$offset = $update['update_id'] + 1; // Just like in the bot API, the offset must be set to the last update_id
try {
diff --git a/userbots/pwrtelegram_debug_bot.php b/userbots/pwrtelegram_debug_bot.php
index c8eb4f03..a16e34a9 100755
--- a/userbots/pwrtelegram_debug_bot.php
+++ b/userbots/pwrtelegram_debug_bot.php
@@ -109,7 +109,7 @@ function recurse($array, $prefix = '')
}
$offset = 0;
while (true) {
- $updates = $MadelineProto->API->get_updates(['offset' => $offset, 'limit' => 50, 'timeout' => 0]); // Just like in the bot API, you can specify an offset, a limit and a timeout
+ $updates = $MadelineProto->get_updates(['offset' => $offset, 'limit' => 50, 'timeout' => 0]); // Just like in the bot API, you can specify an offset, a limit and a timeout
foreach ($updates as $update) {
$offset = $update['update_id'] + 1; // Just like in the bot API, the offset must be set to the last update_id
switch ($update['update']['_']) {