diff --git a/README.md b/README.md
index 7a6dc902..0e57efd9 100644
--- a/README.md
+++ b/README.md
@@ -31,6 +31,7 @@ src/danog/MadelineProto/
TLMethod - Represents a TL method
API - Wrapper class that istantiates the MTProto class, sets the error handler, and provides a wrapper for calling mtproto methods directly as class submethods
Connection - Handles tcp/udp/http connections and wrapping payloads generated by MTProtoTools/MessageHandler into the right message according to the protocol
+ DataCenter - Handles mtproto datacenters
DebugTools - Various debugging tools
Exception - Handles exceptions in the main namespace
MTProto - Extends MTProtoTools, handles initial connection, generation of authorization keys, istantiation of classes
diff --git a/src/danog/MadelineProto/API.php b/src/danog/MadelineProto/API.php
index 9219b712..d128164a 100644
--- a/src/danog/MadelineProto/API.php
+++ b/src/danog/MadelineProto/API.php
@@ -12,7 +12,7 @@ If not, see .
namespace danog\MadelineProto;
-class API
+class API extends Tools
{
public $session;
diff --git a/src/danog/MadelineProto/DataCenter.php b/src/danog/MadelineProto/DataCenter.php
new file mode 100644
index 00000000..a589fbce
--- /dev/null
+++ b/src/danog/MadelineProto/DataCenter.php
@@ -0,0 +1,71 @@
+.
+*/
+
+namespace danog\MadelineProto;
+
+/**
+ * Manages all of the mtproto stuff.
+ */
+class DataCenter extends Tools
+{
+ public function __construct($dclist, $settings) {
+ $this->dclist = $dclist;
+ $this->settings = $settings;
+ if (isset($this->settings["all"])) {
+ foreach ($this->range(1, 6) as $n) {
+ $this->settings[$n] = $this->settings["all"];
+ }
+ unset($this->settings["all"]);
+ }
+ foreach ($this->range(1, 6) as $n) {
+ if (!isset($this->settings[$n])) {
+ $this->settings[$n] = [
+ 'protocol' => 'tcp_full',
+ 'port' => '443',
+ 'test_mode' => true
+ ];
+ }
+ }
+ $this->connect(2);
+ }
+ public function connnect($dc_number, $settings = []) {
+ if ($settings == []) {
+ $settings = $this->settings[$dc_number];
+ }
+ $address = $settings["test_mode"] ? $this->dclist["test"][$dc_number] : $this->dclist["main"][$dc_number];
+ if ($settings["protocol"] == "https") {
+ $subdomain = $this->dclist["ssl_subdomains"][$dc_number] . ($settings["upload"] ? '-1' : '');
+ $path = $settings["test_mode"] ? 'apiw_test1' : 'apiw1';
+ $address = 'https://' . $subdomain . '.web.telegram.org/' . $path;
+ }
+ $this->sockets[$dc_number] = new Connection($address, $settings["port"], $settings["protocol"]);
+ $this->curdc = $dc_number;
+ }
+ public function send_message($message, $dc_number = -1) {
+ if ($dc_number == -1) {
+ $dc_number = $this->curdc;
+ }
+ return $this->sockets[$dc_number]->send_message($message);
+ }
+ public function read_message($dc_number = -1) {
+ if ($dc_number == -1) {
+ $dc_number = $this->curdc;
+ }
+ return $this->sockets[$dc_number]->read_message();
+ }
+
+ public function __destroy() {
+ foreach ($this->sockets as $n => $socket) {
+ unset($this->sockets[$n]);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/danog/MadelineProto/MTProto.php b/src/danog/MadelineProto/MTProto.php
index db39481c..9703e120 100644
--- a/src/danog/MadelineProto/MTProto.php
+++ b/src/danog/MadelineProto/MTProto.php
@@ -38,12 +38,30 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
-----END RSA PUBLIC KEY-----',
],
'connection' => [
- 'dc_list' => [
- 2 => [
- 'ip_address' => '149.154.167.50',
- 'port' => '443',
- 'protocol' => 'tcp_full',
- ],
+ 'ssl_subdomains' => [
+ 1 => 'pluto',
+ 2 => 'venus',
+ 3 => 'aurora',
+ 4 => 'vesta',
+ 5 => 'flora'
+ ],
+ 'test' => [
+ 1 => '149.154.175.10',
+ 2 => '149.154.167.40',
+ 3 => '149.154.175.117'
+ ],
+ 'main' => [
+ 1 => '149.154.175.50',
+ 2 => '149.154.167.51',
+ 3 => '149.154.175.100',
+ 4 => '149.154.167.91',
+ 5 => '149.154.171.5'
+ ]
+ ],
+ 'connection_settings' => [
+ 'all' => [
+ 'protocol' => 'tcp_full',
+ 'test_mode' => true
],
],
'app_info' => [
@@ -85,7 +103,8 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
$this->settings = $settings;
// Connect to servers
- $this->sock = new Connection($this->settings['connection']['ip_address'], $this->settings['connection']['port'], $this->settings['connection']['protocol']);
+ $this->connection = new DataCenter($this->settings['connection'], $this->settings['connection_settings']);
+ var_dump($this->connection);
// Load rsa key
$this->key = new RSA($settings['authorization']['rsa_key']);
diff --git a/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php b/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php
index b9848513..ad803db7 100644
--- a/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php
+++ b/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php
@@ -22,7 +22,7 @@ class AuthKeyHandler extends AckHandler
{
public function create_auth_key($expires_in = -1)
{
- foreach (\danog\MadelineProto\Tools::range(0, $this->settings['max_tries']['authorization']) as $retry_id_total) {
+ foreach ($this->range(0, $this->settings['max_tries']['authorization']) as $retry_id_total) {
$this->log->log('Handshake: Requesting pq');
/**
@@ -51,7 +51,7 @@ class AuthKeyHandler extends AckHandler
/*
* ***********************************************************************
- * Compare the equal of nonce client and nonce server
+ * Check if the client's nonce and the server's nonce are the same
*/
if ($ResPQ['nonce'] !== $nonce) {
throw new Exception('Handshake: wrong nonce');
@@ -94,7 +94,7 @@ class AuthKeyHandler extends AckHandler
throw new Exception("Handshake: couldn't compute p and q.");
}
- $this->log->log(sprintf('Factorization %s = %s * %s', $pq, $p, $q));
+ $this->log->log('Handshake: Factorization '.$pq.' = '.$p.' * '.$q);
/*
* ***********************************************************************
@@ -138,7 +138,7 @@ class AuthKeyHandler extends AckHandler
$to_encrypt = $sha_digest.$data.$random_bytes;
$encrypted_data = $this->key->encrypt($to_encrypt);
- $this->log->log('Starting Diffie Hellman key exchange');
+ $this->log->log('Handshake: Starting Diffie Hellman key exchange');
/*
* ***********************************************************************
* Starting Diffie Hellman key exchange, Server authentication
@@ -172,7 +172,7 @@ class AuthKeyHandler extends AckHandler
/*
* ***********************************************************************
- * Compare the equal of nonce client and nonce server
+ * Check if the client's nonce and the server's nonce are the same
*/
if ($nonce != $server_dh_params['nonce']) {
throw new Exception('Handshake: wrong nonce.');
@@ -180,7 +180,7 @@ class AuthKeyHandler extends AckHandler
/*
* ***********************************************************************
- * Compare the equal of server_nonce and new server_nonce
+ * Check if server_nonce and new server_nonce are the same
*/
if ($server_nonce != $server_dh_params['server_nonce']) {
throw new Exception('Handshake: wrong server nonce.');
@@ -224,13 +224,13 @@ class AuthKeyHandler extends AckHandler
* int $server_time
* ]
*/
- $server_DH_inner_data = $this->tl->deserialize(\danog\MadelineProto\Tools::fopen_and_write('php://memory', 'rw+b', $answer));
+ $server_DH_inner_data = $this->tl->deserialize($this->fopen_and_write('php://memory', 'rw+b', $answer));
/*
* ***********************************************************************
* Do some checks
*/
- $server_DH_inner_data_length = $this->tl->get_length(\danog\MadelineProto\Tools::fopen_and_write('php://memory', 'rw+b', $answer));
+ $server_DH_inner_data_length = $this->tl->get_length($this->fopen_and_write('php://memory', 'rw+b', $answer));
if (sha1(substr($answer, 0, $server_DH_inner_data_length), true) != $answer_hash) {
throw new Exception('Handshake: answer_hash mismatch.');
}
@@ -252,9 +252,9 @@ class AuthKeyHandler extends AckHandler
* Time delta
*/
$server_time = $server_DH_inner_data['server_time'];
- $this->timedelta = ($server_time - time());
+ $this->timedelta = $server_time - time();
- $this->log->log(sprintf('Server-client time delta = %.1f s', $this->timedelta));
+ $this->log->log(sprintf('Handshake: Server-client time delta = %.1f s', $this->timedelta));
/*
@@ -310,7 +310,7 @@ class AuthKeyHandler extends AckHandler
throw new Exception('Handshake: g_a is invalid (1 < g_a < dh_prime - 1 is false).');
}
- foreach (\danog\MadelineProto\Tools::range(0, $this->settings['max_tries']['authorization']) as $retry_id) {
+ foreach ($this->range(0, $this->settings['max_tries']['authorization']) as $retry_id) {
$b = new \phpseclib\Math\BigInteger(\phpseclib\Crypt\Random::string(256), 256);
$g_b = $g->powMod($b, $dh_prime);
@@ -352,7 +352,7 @@ class AuthKeyHandler extends AckHandler
* encrypt client_DH_inner_data
*/
$data_with_sha = sha1($data, true).$data;
- $data_with_sha_padded = $data_with_sha.\phpseclib\Crypt\Random::string(\danog\MadelineProto\Tools::posmod(-strlen($data_with_sha), 16));
+ $data_with_sha_padded = $data_with_sha.\phpseclib\Crypt\Random::string($this->posmod(-strlen($data_with_sha), 16));
$encrypted_data = $this->ige_encrypt($data_with_sha_padded, $tmp_aes_key, $tmp_aes_iv);
/*
@@ -395,7 +395,7 @@ class AuthKeyHandler extends AckHandler
/*
* ***********************************************************************
- * Compare the equal of nonce client and nonce server
+ * Check if the client's nonce and the server's nonce are the same
*/
if ($Set_client_DH_params_answer['nonce'] != $nonce) {
throw new Exception('Handshake: wrong nonce.');
@@ -403,7 +403,7 @@ class AuthKeyHandler extends AckHandler
/*
* ***********************************************************************
- * Compare the equal of server_nonce and new server_nonce
+ * Check if server_nonce and new server_nonce are the same
*/
if ($Set_client_DH_params_answer['server_nonce'] != $server_nonce) {
throw new Exception('Handshake: wrong server nonce');
@@ -413,41 +413,43 @@ class AuthKeyHandler extends AckHandler
* ***********************************************************************
* Check Set_client_DH_params_answer type
*/
- if ($Set_client_DH_params_answer['_'] == 'dh_gen_ok') {
- if ($Set_client_DH_params_answer['new_nonce_hash1'] != $new_nonce_hash1) {
- throw new Exception('Handshake: wrong new_nonce_hash1');
- }
+ switch ($Set_client_DH_params_answer['_']) {
+ case 'dh_gen_ok':
+ if ($Set_client_DH_params_answer['new_nonce_hash1'] != $new_nonce_hash1) {
+ throw new Exception('Handshake: wrong new_nonce_hash1');
+ }
- $this->log->log('Diffie Hellman key exchange processed successfully');
+ $this->log->log('Diffie Hellman key exchange processed successfully');
- $res_authorization['server_salt'] = $this->struct->unpack('struct->unpack('log->log('Auth key generated');
- $this->timedelta = 0;
+ $this->log->log('Auth key generated');
+ $this->timedelta = 0;
+ return $res_authorization;
+ case 'dh_gen_retry':
+ if ($Set_client_DH_params_answer['new_nonce_hash2'] != $new_nonce_hash2) {
+ throw new Exception('Handshake: wrong new_nonce_hash_2');
+ }
- return $res_authorization;
- } elseif ($Set_client_DH_params_answer['_'] == 'dh_gen_retry') {
- if ($Set_client_DH_params_answer['new_nonce_hash2'] != $new_nonce_hash2) {
- throw new Exception('Handshake: wrong new_nonce_hash_2');
- }
+ //repeat foreach
+ $this->log->log('Handshake: Retrying Auth');
+ break;
+ case 'dh_gen_fail':
+ if ($Set_client_DH_params_answer['new_nonce_hash3'] != $new_nonce_hash3) {
+ throw new Exception('Handshake: wrong new_nonce_hash_3');
+ }
- //repeat foreach
- $this->log->log('Retrying Auth');
- } elseif ($Set_client_DH_params_answer['_'] == 'dh_gen_fail') {
- if ($Set_client_DH_params_answer['new_nonce_hash3'] != $new_nonce_hash3) {
- throw new Exception('Handshake: wrong new_nonce_hash_3');
- }
-
- $this->log->log('Auth Failed');
- break;
- } else {
- throw new Exception('Response Error');
+ $this->log->log('Handshake: Auth Failed');
+ break 2;
+ default:
+ throw new Exception('Response Error');
+ break;
}
}
}
diff --git a/src/danog/MadelineProto/MTProtoTools/CallHandler.php b/src/danog/MadelineProto/MTProtoTools/CallHandler.php
index 9708a388..43e04ea5 100644
--- a/src/danog/MadelineProto/MTProtoTools/CallHandler.php
+++ b/src/danog/MadelineProto/MTProtoTools/CallHandler.php
@@ -52,8 +52,8 @@ class CallHandler extends AuthKeyHandler
$server_answer = $this->wait_for_response($int_message_id);
} catch (Exception $e) {
$this->log->log('An error occurred while calling method '.$method.': '.$e->getMessage().' in '.$e->getFile().':'.$e->getLine().$e->getTraceAsString().'. Recreating connection and retrying to call method...');
- unset($this->sock);
- $this->sock = new \danog\MadelineProto\Connection($this->settings['connection']['ip_address'], $this->settings['connection']['port'], $this->settings['connection']['protocol']);
+ unset($this->connection);
+ $this->connection = new DataCenter($this->settings['connection'], $this->settings['connection_settings']);
continue;
}
if ($server_answer == null) {
@@ -73,9 +73,9 @@ class CallHandler extends AuthKeyHandler
$this->outgoing_messages[$int_message_id]['content'] = ['object' => $object, 'args' => $args];
// $server_answer = $this->wait_for_response($int_message_id);
} catch (Exception $e) {
- $this->log->log('An error occurred while calling object '.$object.': '.$e->getMessage().' in '.$e->getFile().':'.$e->getLine().'. Recreating connection and retrying to call object...');
- unset($this->sock);
- $this->sock = new \danog\MadelineProto\Connection($this->settings['connection']['ip_address'], $this->settings['connection']['port'], $this->settings['connection']['protocol']);
+ $this->log->log('An error occurred while calling object '.$object.': '.$e->getMessage().' in '.$e->getFile().':'.$e->getLine().'. Recreating connection and retrying to call object...');
+ unset($this->connection);
+ $this->connection = new DataCenter($this->settings['connection'], $this->settings['connection_settings']);
continue;
}
diff --git a/src/danog/MadelineProto/MTProtoTools/MessageHandler.php b/src/danog/MadelineProto/MTProtoTools/MessageHandler.php
index f8c5d434..47990dcc 100644
--- a/src/danog/MadelineProto/MTProtoTools/MessageHandler.php
+++ b/src/danog/MadelineProto/MTProtoTools/MessageHandler.php
@@ -38,17 +38,17 @@ class MessageHandler extends Crypt
$message = $this->settings['authorization']['temp_auth_key']['id'].$message_key.$this->ige_encrypt($encrypted_data.$padding, $aes_key, $aes_iv);
$this->outgoing_messages[$int_message_id]['seq_no'] = $seq_no;
}
- $this->sock->send_message($message);
+ $this->connection->send_message($message);
return $int_message_id;
}
/**
- * Reading socket and receiving message from server. Check the CRC32.
+ * Reading connectionet and receiving message from server. Check the CRC32.
*/
public function recv_message()
{
- $payload = $this->sock->read_message();
+ $payload = $this->connection->read_message();
if (fstat($payload)['size'] == 4) {
throw new Exception('Server response error: '.abs($this->struct->unpack('