2022-12-30 21:54:44 +01:00
< ? php
declare ( strict_types = 1 );
2018-02-24 17:54:13 +01:00
Merge alpha into master (async, huge bugfixes and more) (#546)
* Implement async and lots of bugfixes
* Implement more async
* Implement async, implement bugfixes for the connection module, for the datacenter module, huge bugfixes, huge perfomance improvements, media DCs for https, advanced selecting, custom var_dump, totally rewritten IOLoop and response mechanism, promises, improvements to the TL parser, custom mb_substr
* Apply fixes from StyleCI
* Bugfixes
* Apply fixes from StyleCI
* Bugfixes, implement combined promises
* Apply fixes from StyleCI
* Support passing method arguments as callable
* Starting to write async upload logic
* Apply fixes from StyleCI
* Start implementing async file upload
* Apply fixes from StyleCI
* bugfix
* Apply fixes from StyleCI
* Start rewriting connection module
* Add PHP file docblocks for all classes
* Start working on new async stream API
* Finish writing stream API
* More stream API fixes
* Apply fixes from StyleCI
* Rewrite DataCenter and Connection modules
* Clean up stream API documentation
* Fixes
* Apply fixes from StyleCI
* Add referenced parameter to get length of buffer to read in getReadBuffer API
* Moved all MessageHandler code in the Connection module, added a PHP version warning in the phar
* Start fixing reads
* Fix all protocol stream wrappers
* Apply fixes from StyleCI
* Implement disconnection, and remove end function
* Working async RPC
* Implement async file upload
* Bugfix
* Method recall bugfixes
* Bugfixes
* Trait bugfixes
* Fix FIFO buffer
* Bugfixes and speedtests
* Async logging
* Implement websocket streams
* Implement loop API, signal API, clean closing and start changing layer
* Small magna, websocket and HTTP fixes
* Clean up loop API
* Improved stack traces, 2FA and async
* Login fixes
* Added instructions for manual verification
* Small fixes
* More app info improvements
* More app info improvements
* TL and 2FA fixes
* Update to layer 89
* More bugfixes
* Implement broken media reporting
* Remove debug comments
* PHP 7.2 backwards compatibility
* Bugfixes
* Async key generation
* Some simplifications
* Transport fixes
* Cleanup
* async API
* Performance fixes
* Fixes to async API
* Bugfixes
* Implement one-time async loop
* Authorization and logging fixes
* Update to layer 91
* 7to5 fix
* Null coalesce conversion
* Implement socks5 proxy
* Implement HTTP proxy
* Fixes to HTTP proxy
* MTProxy and socks5 fixes
* Disable PHP 5 conversion
* Proxies have higher priority
* Avoid error handling in vendor
* Override composer dependencies
* Fix travis build
* Final composer fixes
* Proxy logic fixes
* Fix get_updates update handling
* Do not use parallel file driver if not supported
* Refactor loader and implement HTTP fixes
* Suppress errors in loader
* HTTP and authorization fixes
* HTTP fixes
* Improved peer management
* Use HTTP protocol on altervista
* Small bugfixes
* Minor fixes
* Docufix
* Docufix
* Legacy fixes
* Fix message queue
* Avoid updating if using MTProxy
* Improve logs and examples
* Trim final newlines while converting parse mode
* Reimplement noResponse flag
* Async combined event handler and APIFactory fixes
* Actually return config
* Case-insensitive methods
* Bugfix
* Apply fixes from StyleCI (#545)
* MTProxy fixes
* PHP 5 warning
* Improved PHP 5 warning
* Use <br> along with newlines in web logs
* Update docs
2018-12-26 20:51:14 +01:00
/**
* Serialization module .
*
* This file is part of MadelineProto .
* MadelineProto is free software : you can redistribute it and / or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation , either version 3 of the License , or ( at your option ) any later version .
* MadelineProto is distributed in the hope that it will be useful , but WITHOUT ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
* See the GNU Affero General Public License for more details .
* You should have received a copy of the GNU General Public License along with MadelineProto .
* If not , see < http :// www . gnu . org / licenses />.
*
* @ author Daniil Gentili < daniil @ daniil . it >
2023-01-04 12:43:01 +01:00
* @ copyright 2016 - 2023 Daniil Gentili < daniil @ daniil . it >
Merge alpha into master (async, huge bugfixes and more) (#546)
* Implement async and lots of bugfixes
* Implement more async
* Implement async, implement bugfixes for the connection module, for the datacenter module, huge bugfixes, huge perfomance improvements, media DCs for https, advanced selecting, custom var_dump, totally rewritten IOLoop and response mechanism, promises, improvements to the TL parser, custom mb_substr
* Apply fixes from StyleCI
* Bugfixes
* Apply fixes from StyleCI
* Bugfixes, implement combined promises
* Apply fixes from StyleCI
* Support passing method arguments as callable
* Starting to write async upload logic
* Apply fixes from StyleCI
* Start implementing async file upload
* Apply fixes from StyleCI
* bugfix
* Apply fixes from StyleCI
* Start rewriting connection module
* Add PHP file docblocks for all classes
* Start working on new async stream API
* Finish writing stream API
* More stream API fixes
* Apply fixes from StyleCI
* Rewrite DataCenter and Connection modules
* Clean up stream API documentation
* Fixes
* Apply fixes from StyleCI
* Add referenced parameter to get length of buffer to read in getReadBuffer API
* Moved all MessageHandler code in the Connection module, added a PHP version warning in the phar
* Start fixing reads
* Fix all protocol stream wrappers
* Apply fixes from StyleCI
* Implement disconnection, and remove end function
* Working async RPC
* Implement async file upload
* Bugfix
* Method recall bugfixes
* Bugfixes
* Trait bugfixes
* Fix FIFO buffer
* Bugfixes and speedtests
* Async logging
* Implement websocket streams
* Implement loop API, signal API, clean closing and start changing layer
* Small magna, websocket and HTTP fixes
* Clean up loop API
* Improved stack traces, 2FA and async
* Login fixes
* Added instructions for manual verification
* Small fixes
* More app info improvements
* More app info improvements
* TL and 2FA fixes
* Update to layer 89
* More bugfixes
* Implement broken media reporting
* Remove debug comments
* PHP 7.2 backwards compatibility
* Bugfixes
* Async key generation
* Some simplifications
* Transport fixes
* Cleanup
* async API
* Performance fixes
* Fixes to async API
* Bugfixes
* Implement one-time async loop
* Authorization and logging fixes
* Update to layer 91
* 7to5 fix
* Null coalesce conversion
* Implement socks5 proxy
* Implement HTTP proxy
* Fixes to HTTP proxy
* MTProxy and socks5 fixes
* Disable PHP 5 conversion
* Proxies have higher priority
* Avoid error handling in vendor
* Override composer dependencies
* Fix travis build
* Final composer fixes
* Proxy logic fixes
* Fix get_updates update handling
* Do not use parallel file driver if not supported
* Refactor loader and implement HTTP fixes
* Suppress errors in loader
* HTTP and authorization fixes
* HTTP fixes
* Improved peer management
* Use HTTP protocol on altervista
* Small bugfixes
* Minor fixes
* Docufix
* Docufix
* Legacy fixes
* Fix message queue
* Avoid updating if using MTProxy
* Improve logs and examples
* Trim final newlines while converting parse mode
* Reimplement noResponse flag
* Async combined event handler and APIFactory fixes
* Actually return config
* Case-insensitive methods
* Bugfix
* Apply fixes from StyleCI (#545)
* MTProxy fixes
* PHP 5 warning
* Improved PHP 5 warning
* Use <br> along with newlines in web logs
* Update docs
2018-12-26 20:51:14 +01:00
* @ license https :// opensource . org / licenses / AGPL - 3.0 AGPLv3
2019-10-31 15:07:35 +01:00
* @ link https :// docs . madelineproto . xyz MadelineProto documentation
Merge alpha into master (async, huge bugfixes and more) (#546)
* Implement async and lots of bugfixes
* Implement more async
* Implement async, implement bugfixes for the connection module, for the datacenter module, huge bugfixes, huge perfomance improvements, media DCs for https, advanced selecting, custom var_dump, totally rewritten IOLoop and response mechanism, promises, improvements to the TL parser, custom mb_substr
* Apply fixes from StyleCI
* Bugfixes
* Apply fixes from StyleCI
* Bugfixes, implement combined promises
* Apply fixes from StyleCI
* Support passing method arguments as callable
* Starting to write async upload logic
* Apply fixes from StyleCI
* Start implementing async file upload
* Apply fixes from StyleCI
* bugfix
* Apply fixes from StyleCI
* Start rewriting connection module
* Add PHP file docblocks for all classes
* Start working on new async stream API
* Finish writing stream API
* More stream API fixes
* Apply fixes from StyleCI
* Rewrite DataCenter and Connection modules
* Clean up stream API documentation
* Fixes
* Apply fixes from StyleCI
* Add referenced parameter to get length of buffer to read in getReadBuffer API
* Moved all MessageHandler code in the Connection module, added a PHP version warning in the phar
* Start fixing reads
* Fix all protocol stream wrappers
* Apply fixes from StyleCI
* Implement disconnection, and remove end function
* Working async RPC
* Implement async file upload
* Bugfix
* Method recall bugfixes
* Bugfixes
* Trait bugfixes
* Fix FIFO buffer
* Bugfixes and speedtests
* Async logging
* Implement websocket streams
* Implement loop API, signal API, clean closing and start changing layer
* Small magna, websocket and HTTP fixes
* Clean up loop API
* Improved stack traces, 2FA and async
* Login fixes
* Added instructions for manual verification
* Small fixes
* More app info improvements
* More app info improvements
* TL and 2FA fixes
* Update to layer 89
* More bugfixes
* Implement broken media reporting
* Remove debug comments
* PHP 7.2 backwards compatibility
* Bugfixes
* Async key generation
* Some simplifications
* Transport fixes
* Cleanup
* async API
* Performance fixes
* Fixes to async API
* Bugfixes
* Implement one-time async loop
* Authorization and logging fixes
* Update to layer 91
* 7to5 fix
* Null coalesce conversion
* Implement socks5 proxy
* Implement HTTP proxy
* Fixes to HTTP proxy
* MTProxy and socks5 fixes
* Disable PHP 5 conversion
* Proxies have higher priority
* Avoid error handling in vendor
* Override composer dependencies
* Fix travis build
* Final composer fixes
* Proxy logic fixes
* Fix get_updates update handling
* Do not use parallel file driver if not supported
* Refactor loader and implement HTTP fixes
* Suppress errors in loader
* HTTP and authorization fixes
* HTTP fixes
* Improved peer management
* Use HTTP protocol on altervista
* Small bugfixes
* Minor fixes
* Docufix
* Docufix
* Legacy fixes
* Fix message queue
* Avoid updating if using MTProxy
* Improve logs and examples
* Trim final newlines while converting parse mode
* Reimplement noResponse flag
* Async combined event handler and APIFactory fixes
* Actually return config
* Case-insensitive methods
* Bugfix
* Apply fixes from StyleCI (#545)
* MTProxy fixes
* PHP 5 warning
* Improved PHP 5 warning
* Use <br> along with newlines in web logs
* Update docs
2018-12-26 20:51:14 +01:00
*/
2018-02-25 17:50:03 +01:00
2016-12-26 18:23:46 +01:00
namespace danog\MadelineProto ;
2023-01-11 18:47:27 +01:00
use Amp\CancelledException ;
use Amp\DeferredCancellation ;
2022-12-30 20:24:13 +01:00
use Amp\DeferredFuture ;
2023-01-04 12:37:12 +01:00
use Amp\Future ;
2020-10-04 14:55:05 +02:00
use Amp\Ipc\Sync\ChannelledSocket ;
2023-01-11 18:47:27 +01:00
use Amp\TimeoutException ;
2023-07-25 14:27:16 +02:00
use AssertionError ;
2024-04-06 13:08:41 +02:00
use danog\AsyncOrm\DbArrayBuilder ;
2024-04-01 19:08:32 +02:00
use danog\AsyncOrm\Driver\DriverArray ;
2024-04-06 13:08:41 +02:00
use danog\AsyncOrm\KeyType ;
use danog\AsyncOrm\ValueType ;
2020-09-22 23:10:56 +02:00
use danog\MadelineProto\Ipc\Server ;
2023-11-19 16:41:47 +01:00
use danog\MadelineProto\Settings\Database\DriverDatabaseAbstract ;
2022-12-30 20:24:13 +01:00
use Revolt\EventLoop ;
2022-12-30 19:21:36 +01:00
use Throwable ;
2020-07-09 21:42:06 +02:00
2022-12-30 19:21:36 +01:00
use const LOCK_EX ;
2023-07-25 18:44:30 +02:00
2020-02-25 18:02:32 +01:00
use function Amp\File\exists ;
2020-09-22 23:10:56 +02:00
use function Amp\Ipc\connect ;
2020-02-25 18:02:32 +01:00
2016-12-26 18:23:46 +01:00
/**
2016-12-26 20:24:24 +01:00
* Manages serialization of the MadelineProto instance .
2023-02-16 18:38:47 +01:00
*
* @ internal
2016-12-26 18:23:46 +01:00
*/
2020-09-22 23:10:56 +02:00
abstract class Serialization
2016-12-26 20:24:24 +01:00
{
2020-09-22 23:10:56 +02:00
/**
* Unserialize session .
*
* Logic for deserialization is as follows .
* - If the session is unlocked
* - Try starting IPC server :
* - Fetch light state
* - If don ' t need event handler
* - Unlock
* - Fork
* - Lock ( fork )
* - Deserialize full ( fork )
* - Start IPC server ( fork )
* - Store IPC state ( fork )
* - If need event handler
* - If have event handler class
* - Deserialize full
* - Start IPC server
* - Store IPC state
* - Else Fallthrough
* - Wait for a new IPC state for a maximum of 30 seconds , then throw
* - Execute original request via IPC
*
* - If the session is locked
* - In parallel ( concurrent ) :
* - The IPC server should be running , connect
* - Try starting full session
* - Fetch light state
* - If don ' t need event handler
* - Wait lock
* - Unlock
* - Fork
* - Lock ( fork )
* - Deserialize full ( fork )
* - Start IPC server ( fork )
* - Store IPC state ( fork )
* - If need event handler and have event handler class
* - Wait lock
* - Deserialize full
* - Start IPC server
* - Store IPC state
* - Wait for a new IPC session for a maximum of 30 seconds , then throw
* - Execute original request via IPC
*
*
*
* - If receiving a startAndLoop or setEventHandler request on an IPC session :
* - Shutdown remote IPC server
* - Deserialize full
* - Start IPC server
* - Store IPC state
2020-02-25 18:02:32 +01:00
*
2020-10-07 16:48:34 +02:00
* @ param SessionPaths $session Session name
* @ param SettingsAbstract $settings Settings
* @ param bool $forceFull Whether to force full session deserialization
2020-02-25 18:02:32 +01:00
* @ internal
2022-12-30 20:24:13 +01:00
* @ return array { 0 : ( ChannelledSocket | APIWrapper | Throwable | null | 0 ), 1 : ( callable | null )}
2020-02-25 18:02:32 +01:00
*/
2022-12-30 20:24:13 +01:00
public static function unserialize ( SessionPaths $session , SettingsAbstract $settings , bool $forceFull = false ) : array
2020-02-25 18:02:32 +01:00
{
2020-09-23 00:57:49 +02:00
//Logger::log('Waiting for exclusive session lock...');
2022-12-30 20:24:13 +01:00
$warningId = EventLoop :: delay ( 1 , static function () use ( & $warningId ) : void {
2023-07-18 15:46:27 +02:00
if ( isset ( $_GET [ 'MadelineSelfRestart' ])) {
Logger :: log ( " MadelineProto self-restarted successfully! " );
} else {
Logger :: log ( 'It seems like the session is busy.' );
Logger :: log ( 'Telegram does not support starting multiple instances of the same session, make sure no other instance of the session is running.' );
2023-11-11 16:55:29 +01:00
$warningId = EventLoop :: repeat ( 5 , static fn () => Logger :: log ( 'Still waiting for exclusive session lock...' ));
2023-07-18 15:46:27 +02:00
EventLoop :: unreference ( $warningId );
}
2020-09-22 23:10:56 +02:00
});
2022-12-30 20:24:13 +01:00
EventLoop :: unreference ( $warningId );
2020-09-22 23:10:56 +02:00
$lightState = null ;
2023-01-11 18:47:27 +01:00
$cancelFlock = new DeferredCancellation ;
2022-12-30 20:24:13 +01:00
$cancelIpc = new DeferredFuture ;
2020-09-22 23:10:56 +02:00
$canContinue = true ;
$ipcSocket = null ;
2023-01-15 20:13:47 +01:00
$unlock = Tools :: flock ( $session -> getLockPath (), LOCK_EX , 1 , $cancelFlock -> getCancellation (), $forceFull ? null : static function () use ( $session , & $cancelFlock , $cancelIpc , & $canContinue , & $ipcSocket , & $lightState ) : void {
2021-12-07 15:16:15 +01:00
$cancelFull = static function () use ( & $cancelFlock ) : void {
if ( $cancelFlock !== null ) {
$copy = $cancelFlock ;
$cancelFlock = null ;
2023-01-11 18:47:27 +01:00
$copy -> cancel ();
2021-12-07 15:16:15 +01:00
}
};
2023-11-11 16:55:29 +01:00
EventLoop :: queue ( static function () use ( $session , $cancelFull , & $canContinue , & $lightState ) : void {
2023-01-04 12:37:12 +01:00
try {
$lightState = $session -> getLightState ();
if ( ! $lightState -> canStartIpc ()) {
2020-09-22 23:10:56 +02:00
$canContinue = false ;
2021-12-07 15:16:15 +01:00
$cancelFull ();
2020-09-22 23:10:56 +02:00
}
2023-01-04 12:37:12 +01:00
} catch ( Throwable ) {
2020-09-23 00:57:49 +02:00
$lightState = false ;
2020-07-12 01:12:20 +02:00
}
2020-07-09 21:42:06 +02:00
});
2023-01-15 19:39:01 +01:00
$ipcSocket = self :: tryConnect ( $session -> getIpcPath (), $cancelIpc -> getFuture (), $cancelFull );
2020-09-22 23:10:56 +02:00
});
2022-12-30 21:43:58 +01:00
EventLoop :: cancel ( $warningId );
2020-09-22 23:10:56 +02:00
if ( ! $unlock ) { // Canceled, don't have lock
2020-09-23 00:57:49 +02:00
return $ipcSocket ;
2020-09-22 23:10:56 +02:00
}
2020-09-23 00:57:49 +02:00
if ( ! $canContinue ) { // Have lock, can't use it
2020-09-24 11:45:20 +02:00
Logger :: log ( " Session has event handler, but it's not started. " , Logger :: ERROR );
Logger :: log ( " We don't have access to the event handler class, so we can't start it. " , Logger :: ERROR );
2023-01-04 15:13:55 +01:00
Logger :: log ( 'Please start the event handler or unset it to use the IPC server.' , Logger :: ERROR );
2020-09-22 23:10:56 +02:00
$unlock ();
2020-09-23 00:57:49 +02:00
return $ipcSocket ;
2020-09-22 23:10:56 +02:00
}
try {
2022-12-30 20:24:13 +01:00
$lightState ? ? = $session -> getLightState ();
2023-01-15 20:13:47 +01:00
} catch ( Throwable ) {
2020-09-22 23:10:56 +02:00
}
2023-11-19 18:40:20 +01:00
\assert ( $lightState === null || $lightState instanceof LightState );
$exists = exists ( $session -> getSessionPath ());
2020-09-24 11:45:20 +02:00
if ( $lightState && ! $forceFull ) {
2020-09-22 23:10:56 +02:00
if ( ! $class = $lightState -> getEventHandler ()) {
// Unlock and fork
2020-09-22 17:30:07 +02:00
$unlock ();
2023-01-11 18:47:27 +01:00
$monitor = Server :: startMe ( $session );
2023-11-11 16:55:29 +01:00
EventLoop :: queue ( static function () use ( $cancelIpc , $monitor ) : void {
2023-01-11 18:47:27 +01:00
try {
$cancelIpc -> complete ( $monitor -> await ());
} catch ( \Throwable $e ) {
$cancelIpc -> error ( $e );
}
});
2022-12-30 20:24:13 +01:00
return $ipcSocket ? ? self :: tryConnect ( $session -> getIpcPath (), $cancelIpc -> getFuture ());
2023-10-01 20:05:04 +02:00
} elseif ( ! class_exists ( $class )) {
2020-09-24 11:45:20 +02:00
// Have lock, can't use it
$unlock ();
2023-07-25 14:27:16 +02:00
Logger :: log ( " Session has event handler (class $class ), but it's not started. " , Logger :: ERROR );
2020-09-24 11:45:20 +02:00
Logger :: log ( " We don't have access to the event handler class, so we can't start it. " , Logger :: ERROR );
2023-01-04 15:13:55 +01:00
Logger :: log ( 'Please start the event handler or unset it to use the IPC server.' , Logger :: ERROR );
2023-07-27 13:20:30 +02:00
return $ipcSocket ? ? self :: tryConnect ( $session -> getIpcPath (), $cancelIpc -> getFuture (), customE : new AssertionError ( " Please make sure the $class class is in scope, or that the event handler is running (in a separate process or in the current process). " ));
2023-10-01 20:05:04 +02:00
} elseif ( is_subclass_of ( $class , EventHandler :: class )) {
2023-07-21 20:02:01 +02:00
EventHandler :: cachePlugins ( $class );
2020-09-22 23:10:56 +02:00
}
2023-11-19 18:40:20 +01:00
} elseif ( $lightState ) {
2023-07-25 14:27:16 +02:00
$class = $lightState -> getEventHandler ();
2023-10-01 20:05:04 +02:00
if ( $class && ! class_exists ( $class )) {
2023-07-25 14:27:16 +02:00
// Have lock, can't use it
$unlock ();
Logger :: log ( " Session has event handler, but it's not started. " , Logger :: ERROR );
Logger :: log ( " We don't have access to the event handler class, so we can't start it. " , Logger :: ERROR );
Logger :: log ( 'Please start the event handler or unset it to use the IPC server.' , Logger :: ERROR );
2023-07-27 13:20:30 +02:00
throw new AssertionError ( " Please make sure the $class class is in scope, or that the event handler is running (in a separate process or in the current process). " );
2023-10-01 20:05:04 +02:00
} elseif ( $class && is_subclass_of ( $class , EventHandler :: class )) {
2023-07-25 14:27:16 +02:00
EventHandler :: cachePlugins ( $class );
}
2023-11-19 18:40:20 +01:00
} elseif ( $exists ) {
throw new AssertionError ( " Could not read the lightstate file, check logs! " );
2020-09-22 23:10:56 +02:00
}
2020-07-09 21:42:06 +02:00
2022-12-08 20:16:40 +01:00
$tempId = Shutdown :: addCallback ( $unlock = static function () use ( $unlock ) : void {
2023-01-04 15:13:55 +01:00
Logger :: log ( 'Unlocking exclusive session lock!' );
2020-09-22 23:10:56 +02:00
$unlock ();
2023-01-04 15:13:55 +01:00
Logger :: log ( 'Unlocked exclusive session lock!' );
2020-09-22 23:10:56 +02:00
});
2023-01-04 15:13:55 +01:00
Logger :: log ( 'Got exclusive session lock!' );
2020-09-22 17:30:07 +02:00
2023-11-19 18:40:20 +01:00
if ( $exists ) {
$unserialized = $session -> unserialize ();
} else {
$unserialized = null ;
}
2024-04-06 13:08:41 +02:00
if ( $unserialized instanceof DriverArray || \is_string ( $unserialized ) || ! $exists ) {
2023-01-19 15:48:56 +01:00
if ( $settings instanceof Settings ) {
$settings = $settings -> getDb ();
}
2024-04-06 13:08:41 +02:00
if ( $settings instanceof DriverDatabaseAbstract
&& $prefix = $settings -> getEphemeralFilesystemPrefix ()
) {
$tableName = " { $prefix } _MTProto_session " ;
} elseif ( $unserialized instanceof DriverArray ) {
$tableName = (( array ) $unserialized )[ " \0 * \0 table " ];
} else {
$tableName = $unserialized ;
}
$unserialized = null ;
if ( $tableName !== null && $settings instanceof DriverDatabaseAbstract ) {
Logger :: log ( 'Extracting session from database...' );
$unserialized = ( new DbArrayBuilder (
$tableName ,
$settings -> getOrmSettings (),
KeyType :: STRING ,
ValueType :: SCALAR ,
)) -> build () -> get ( 'data' );
}
if ( ! $unserialized && $exists ) {
throw new Exception ( 'Could not extract session from database!' );
2023-01-19 15:48:56 +01:00
}
2020-09-22 23:10:56 +02:00
}
2023-11-19 18:40:20 +01:00
\assert ( $unserialized instanceof APIWrapper || $unserialized === null );
2020-09-22 23:10:56 +02:00
Shutdown :: removeCallback ( $tempId );
return [ $unserialized , $unlock ];
}
/**
* Try connecting to IPC socket .
*
2023-09-06 21:12:19 +02:00
* @ param string $ipcPath IPC path
* @ param Future < ( Throwable | null ) > $cancelConnect Cancelation token ( triggers cancellation of connection )
* @ param null | callable () : void $cancelFull Cancelation token source ( can trigger cancellation of full unserialization )
2023-01-04 12:37:12 +01:00
* @ return array { 0 : ( ChannelledSocket | Throwable | 0 ), 1 : null }
2020-09-22 23:10:56 +02:00
*/
2023-07-27 13:20:30 +02:00
public static function tryConnect ( string $ipcPath , Future $cancelConnect , ? callable $cancelFull = null , ? Throwable $customE = null ) : array
2020-09-22 23:10:56 +02:00
{
2023-07-27 13:20:30 +02:00
for ( $x = 0 ; $x < 25 ; $x ++ ) {
2023-01-04 15:13:55 +01:00
Logger :: log ( 'MadelineProto is starting, please wait...' );
2023-04-27 15:55:10 +02:00
if ( \PHP_OS_FAMILY === 'Windows' ) {
2023-08-14 16:46:01 +02:00
Logger :: log ( Lang :: $current_lang [ 'windows_warning' ]);
2023-04-27 15:55:10 +02:00
}
2020-02-25 18:02:32 +01:00
try {
2023-10-01 20:05:04 +02:00
clearstatcache ( true , $ipcPath );
2022-12-30 20:24:13 +01:00
$socket = connect ( $ipcPath );
2023-01-04 15:13:55 +01:00
Logger :: log ( 'Connected to IPC socket!' );
2020-09-24 11:45:20 +02:00
if ( $cancelFull ) {
2021-12-07 15:16:15 +01:00
$cancelFull ();
2020-02-25 18:02:32 +01:00
}
2020-09-23 00:57:49 +02:00
return [ $socket , null ];
2022-12-30 19:21:36 +01:00
} catch ( Throwable $e ) {
2020-09-22 23:10:56 +02:00
$e = $e -> getMessage ();
2021-06-10 15:54:15 +02:00
if ( $e !== 'The endpoint does not exist!' ) {
Logger :: log ( " $e while connecting to IPC socket " );
}
2020-09-22 23:10:56 +02:00
}
2023-01-11 18:47:27 +01:00
try {
2023-07-25 14:05:51 +02:00
if ( $res = $cancelConnect -> await ( Tools :: getTimeoutCancellation ( 1.0 ))) {
2023-01-11 18:47:27 +01:00
if ( $res instanceof Throwable ) {
return [ $res , null ];
}
$cancelConnect = ( new DeferredFuture ) -> getFuture ();
}
} catch ( CancelledException $e ) {
if ( ! $e -> getPrevious () instanceof TimeoutException ) {
throw $e ;
2020-09-24 11:45:20 +02:00
}
}
2020-09-22 23:10:56 +02:00
}
2023-07-27 13:20:30 +02:00
return [ $customE ? ? 0 , null ];
2020-09-22 23:10:56 +02:00
}
2018-02-25 17:50:03 +01:00
}