{language}
  • Examples
  • FAQ
  • Documentation
  • Issues
  • Team
  • Contribute
  • Publications
  • Introduction

    Achtung! Documentation is under active construction! Consider making a contribution.

    PHPDaemon — asynchronous framework You can built very fast applications, web-services and more on top of it. Out-of-box it provides a wide range of network servers such as FastCGI, HTTP, CGI, FlashPolicy, Telnet, WebSocket; clients like MySQL, Redis, MongoDB, PostgreSQL, Memcached, IRC, XMPP, and others. Network programming became very simple. Middle developer can implement, e.g., full-featured IRC-bot in a hour.

    Usage of this documentation Introduction

    As you may see, whole documentation is placed on one page, so feel free to use standard search within the page (hotkey is Ctrl + F or Cmd + F)

    Installation

    Requirements Installation

    It's recommended to install these non-mandatory modules:

    Source code Installation

    You may clone the repository $ git clone https://github.com/kakserpom/phpdaemon.git

    Or download current version as an archive $ wget https://github.com/kakserpom/phpdaemon/archive/master.zip

    Then install mandatory PHP modules $ pecl install event eio inotify

    Composer Installation

    Add a section into yours composer.json

    "require" : {
        "kakserpom/phpdaemon" : "dev-master"
    }

    Futhermore information about the package is located at packagist.org.

    CentOS/RedHat Installation

    First of all you should install related utilities. $ sudo yum install -y git gcc openssl-devel libevent

    To install latest PHP. you should add the Remi and the Epel repositories, because standard package may contain outdated version.

    For RHEL/CentOS 6.4-6.0 32 Bit.

    sudo rpm -Uvh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm
    sudo rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm

    For RHEL/CentOS 6.4-6.0 64 Bit.

    sudo rpm -Uvh http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
    sudo rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
    #Installing PHP.
    sudo yum --enablerepo=remi,remi-test install -y php-cli php-devel php-pear php-process
    
    #Then installing PHP modules.
    sudo -i
    pecl install event eio
    
    #Modules `event` and `eio` require module `sockets`.
    #In RedHat/CentOS, configuration files load up in alphabetic order, so name them `z-event.ini` and `z-eio.ini` accordingly.  
    echo "extension=event.so" > /etc/php.d/z-event.ini
    echo "extension=eio.so" > /etc/php.d/z-eio.ini
    
    exit #out of sudo

    Define date.timezone in /etc/php.ini.

    #Prepare a folder for PHPDaemon.
    sudo mkdir /opt/phpdaemon
    sudo chown [your user]:[your group] /opt/phpdaemon
    cd /opt/phpdaemon
    
    #Installing PHPDaemon.  
    cd /opt/phpdaemon
    git clone https://github.com/kakserpom/phpdaemon.git ./
    
    #Copying configuration file from sample:
    cp /opt/phpdaemon/conf/phpd.conf.example /opt/phpdaemon/conf/phpd.conf
    
    #Creating a link for phpd
    ln -s /opt/phpdaemon/bin/phpd /usr/bin/phpd

    Then run the thing:
    sudo phpd start --verbose-tty=1

    Option --verbose-tty=1 turns on logging into STDOUT

    If you see something like this:

    [PHPD] Loaded config file: '/opt/phpdaemon/conf/phpd.conf'
    [PHPD] Loaded config file: 'conf/conf.d/ExampleJabberBot.conf'
    [PHPD] Loaded config file: 'conf/conf.d/FastCGI.conf'
    [PHPD] Loaded config file: 'conf/conf.d/FlashpolicyServer.conf'
    [PHPD] Loaded config file: 'conf/conf.d/HTTPServer.conf'
    [PHPD] Loaded config file: 'conf/conf.d/IdentServer.conf'
    [PHPD] Loaded config file: 'conf/conf.d/SSL-sample.conf'
    [PHPD] Loaded config file: 'conf/conf.d/WebSocketServer.conf'

    Congratulatious! PHPDaemon is working!

    Ubuntu Installation

    #First of all you should install related utilities.
    sudo -i  
    apt-get install gcc make libcurl4-openssl-dev libevent-dev git libevent
    
    #Installing PHP 5.5.  
    apt-get install php5-cli php5-dev php-pear
    
    #Then install PHP modules.
    pecl install event eio  
    echo "extension=event.so" > /etc/php5/mods-available/event.ini  
    echo "extension=eio.so" > /etc/php5/mods-available/eio.ini
    
    #Creating links
    ln -s /etc/php5/mods-available/event.ini /etc/php5/cli/conf.d/event.ini 
    ln -s /etc/php5/mods-available/eio.ini /etc/php5/cli/conf.d/eio.ini
    
    #Prepare a folder for PHPDaemon.  
    mkdir /opt/phpdaemon
    chown [your user]:[your group] /opt/phpdaemon
    exit #exiting root user
    
    #Installing PHPDaemon.  
    cd /opt/phpdaemon
    git clone https://github.com/kakserpom/phpdaemon.git ./
    
    #Creating configuration file from sample.
    cp /opt/phpdaemon/conf/phpd.conf.example /opt/phpdaemon/conf/phpd.conf
    
    #Let's create an alias of `phpd` for convenience.  
    alias phpd='/opt/phpdaemon/bin/phpd'
    
    #Local alias of sudo:  
    alias sudo='sudo '

    Then run the thing:
    sudo phpd start --verbose-tty=1

    Option --verbose-tty=1 turns on logging into STDOUT

    If you see something like this:

    [PHPD] Loaded config file: '/opt/phpdaemon/conf/phpd.conf'
    [PHPD] Loaded config file: 'conf/conf.d/ExampleJabberBot.conf'
    [PHPD] Loaded config file: 'conf/conf.d/FastCGI.conf'
    [PHPD] Loaded config file: 'conf/conf.d/FlashpolicyServer.conf'
    [PHPD] Loaded config file: 'conf/conf.d/HTTPServer.conf'
    [PHPD] Loaded config file: 'conf/conf.d/IdentServer.conf'
    [PHPD] Loaded config file: 'conf/conf.d/SSL-sample.conf'
    [PHPD] Loaded config file: 'conf/conf.d/WebSocketServer.conf'

    Congratulatious! PHPDaemon is working!

    Let's make the aliases permanent:

    echo "alias phpd='/opt/phpdaemon/bin/phpd'" >> ~/.bashrc
    echo "alias sudo='sudo /opt/phpdaemon/bin/phpd'" >> ~/.bashrc

    Gentoo Installation

    You may install PHPDaemon with layman overlay.

    Add this reference into the overlays section in layman.cfg file: https://github.com/lexa-uw/layman-phpdaemon/blob/master/layman.xml

    It should like that:

    overlays  : http://www.gentoo.org/proj/en/overlays/repositories.xml
                https://github.com/lexa-uw/layman-phpdaemon/blob/master/layman.xml

    Execute the following commands:

    sudo layman -L
    sudo layman -a phpdaemon
    sudo emerge www-servers/phpdaemon

    For example, below command install phpdaemon by version 0.4.1, 1.0_beta2 and weekly release.

    $ sudo emerge "=www-servers/phpdaemon-0.4.1" "=www-servers/phpdaemon-1.0_beta2" "www-servers/phpdaemon"
    These are the packages that would be merged, in order:
    
    Calculating dependencies... done!
    [ebuild   R   ~] www-servers/phpdaemon-0.4.1:0.4::phpdaemon  USE="libevent -examples -runkit" 0 kB
    [ebuild   R   ~] www-servers/phpdaemon-1.0_beta2:1.0::phpdaemon  USE="eio event -runkit" 0 kB
    [ebuild   R   ~] www-servers/phpdaemon-20130907:weekly::phpdaemon  USE="eio event -runkit" 0 kB
    ...

    After installation you can use "eselect phpdaemon set" tool for set up symlink for /usr/bin/phpd

    $ sudo eselect phpdaemon list
    Available phpdaemon targets:
      [1]   phpd0.4
      [2]   phpd1.0
      [3]   phpdweekly
    $ sudo eselect phpdaemon set 3
    $ sudo eselect phpdaemon show
    Current phpdaemon:
      weekly

    Add phpdaemon to autoload:

    $ rc-update add phpd default
     * service phpd added to runlevel default

    Add sepatare init.d scripts for different versions:

    $ ln -s /etc/init.d/phpd /etc/init.d/phpd-0.4
    $ ln -s /etc/init.d/phpd /etc/init.d/phpd-1.0
    $ ln -s /etc/init.d/phpd /etc/init.d/phpd-weekly

    And add phpd-1.0 to autoload:

    $ rc-update add phpd-1.0 default
     * service phpd added to runlevel default

    Basics

    PHPDaemon represents one master process with multiple workflows.

    Application, depending on the load, is initialized to one or more workflows. In the second case, the request will be given one free workflow.

    Mechanism of interaction between rebochimi processes is not provided, so for synchronization applications in different processes, you can use third-party software, such as Redis. It is also possible to specify the application option limit-instances N; to limit the number of copies of the application in all operating processes.

    The executable file is located in dirktor ./bin/phpd. You can create your own executable file, as shown in the example ./bin/sampleapp. Before starting the daemon checks for a variable $configFile, using it to load the configuration.

    Псевдотипы Basics

    Псевдотип url @TODO

    Control

    $ phpd start Запуск демона
    $ phpd stop Остановка демона
    SYSCTL: SIGTERM, SIGQUIT
    $ phpd hardstop Принудительная остановка демона
    SYSCTL: SIGINT, SIGKILL
    $ phpd update Обновление конфигурации
    SYSCTL: SIGHUP
    $ phpd reload Плавный перезапуск всех рабочих процессов
    SYSCTL: SIGUSR2
    $ phpd reopenlog Переоткрытие журналов
    SYSCTL: SIGUSR1
    $ phpd restart Плавный перезапуск демона
    $ phpd hardrestart Принудительный перезапуск демона
    $ phpd status Вывод статуса демона
    $ phpd fullstatus Вывод подробной информации работы демона
    $ phpd configtest Вывод глобальных опций. В скобках будет указано значение по-умочанию.
    $ phpd log [-n K] Вывод журнала в реальном времени с помощью команды tail -f. C параметром -n K выводится K последних строк. Или используйте -n +K для вывода строк, начиная с K.
    $ phpd runworker Запуск рабочего процесса без мастер-процесса. Используется для отладки.

    Examples

    Examples

    App resolver

    Получая запросы демон первым делом должен определить какому приложению он должен передать обработку. Для этого служит метод getRequestRoute в классе AppResolver.

    Вы можете определить свой обработчик, пример которого лежит в ./conf/AppResolver.php [https://github.com/kakserpom/phpdaemon/blob/master/conf/AppResolver.php].

    Метод getRequestRoute принимает два параметра:

    Результатом работы может быть:

    Не забудьте указать в конфиге путь до вашего AppResolver, например path './conf/AppResolver.php';.

    В настройках сервера, принимающего запросы, с помощью опции responder можно указать имя приложения по-умолчанию, которому будет передан запрос, если getRequestRoute вернул null.

    Configuration

    Типы данных Configuration

    Большинство опций phpdaemon описывается своими типами данных, позволяющие указывать значения расширенным форматом.

    Предназначен для записи объема информации. Можно записать в виде целого числа или целого числа с постфиксом.

    Формат записи: integer [bBkKmMgG]?

    Постфикс Множитель Пример Значение
    b, B 1 1b 1
    k 1000 1k 1000
    K 1024 1K 1024
    m 1000 * 1000 1m 1000000
    M 1024 * 1024 1M 1048576
    g 1000 * 1000 * 1000 1g 1000000000
    G 1024 * 1024 * 1024 1G 1073741824

    Предназначен для записи количества секунд. Число может быть с плавающей точкой с использованием только символа ".".

    Формат записи: float [smhd]? или (float [smhd])+

    Постфикс Множитель Пример Значение
    s 1 1s 1
    m 60 1m 60
    h 60 * 60 2h 12s 7212
    d 60 * 60 * 24 1d 15m 32s 87332

    Предназначен для записи чисел.

    Формат записи: integer [kKmMgG]?

    Постфикс Множитель Пример Значение
    k, K 1000 1k 1000
    m, M 1000 * 1000 1M 1000000
    g, G 1000 * 1000 * 1000 1g 1000000000

    Глобальные опции Configuration

    Два способа установки опций:

    1. Конфигурационный файл ./conf/phpd.conf;
    2. Параметры командной строки, например --max-workers=1.

    Параметры командной строки имеют больший приоритет.

    Конфигурационный файл Глобальные опции Configuration

    Формат записи опций следующий:
    название-опции; или название-опции значение;

    название-опции не чувствительно к регистру и использованию знака дефиса "-". Следующие варианты написания равнозначны:

    Значение может отсутствовать, что приравнивется к bool(true), либо может быть записано следующими способами:

    Для записи массива используется разделитель пробел " " или запятая ",". В одном значении можно использовать оба разделителя одновременно.

    Пример опции Вывод var_dump
    var-name; bool(true)
    var-name null; NULL
    var-name true; bool(true)
    var-name false; bool(false)
    var-name 0; int(0)
    var-name 1; int(1)
    var-name 3.14; float(3.14)
    var-name "3.14"; string(4) "3.14"
    var-name "пример. длинной строки,второй пример"; string(67) "пример. длинной строки,второй пример"
    var-name пример. длинной строки,второй пример; array(5) {
        [0]=>
        string(13) "пример."
        [1]=>
        string(14) "длинной"
        [2]=>
        string(12) "строки"
        [3]=>
        string(12) "второй"
        [4]=>
        string(12) "пример"
    }
    var-name 1, 'a' null 3.14 'пару слов'; array(5) {
        [0]=>
        int(1)
        [1]=>
        string(1) "a"
        [2]=>
        NULL
        [3]=>
        float(3.14)
        [4]=>
        string(17) "пару слов"
    }

    Ниже будут перечислены глобальные опции демона в формате:
    название-опции (тип-данных = значение-по-умолчанию);

    Плавный перезапуск рабочих процессов Глобальные опции Configuration

    Основные пути Глобальные опции Configuration

    Связанные с мастер-процессом Глобальные опции Configuration

    Рабочие процессы Глобальные опции Configuration

    Журналирование и отладка Глобальные опции Configuration

    Подсистема ввода-вывода POSIX Глобальные опции Configuration

    Applications Configuration

    Development

    Application Development

    Appendix B is a subclass phpDaemon AppInstance, to create a new application, you must create a file applications / [name] .php and call it class Example extends AppInstance. Then, the kernel will call methods in response to which the application must perform the required operations:

    init() - initialize the application. The application needs to maintain the required dependencies and prepare for the launch. onReady() - it means that the working process in which the application is ready to run processing. onShutdown() - the completion of the application. beginRequest(Request $ req, AppInstance $ upstream) - sought a new request object to the application. The method can return false, this means that the application is refused (or not able) to handle requests. After calling this method, the request object enters the queue and invoked iteratively. The class is declared as class ExampleRequest extends Request. Methods:

    init() - is invoked only once when creating the request object. run() - called the dispatcher queue to ter long as it will be returned code 1 or terminate method is called (). terminate() - it should not be rebooted. Method interrupts and terminates the request. sleep($seconds) - the time in seconds after which you want to return to the query. wakeup() - interrupt sleep. onAbort() - request a reset event is called if the client fell off. header($header) - set the HTTP-response header. out($str) - to write to the output stream line. combinedOut($str) - write a string to the output stream containing both headers and body. stdin($str) - processor input stream of the request. finish($status) - 0 - normal, -1 - abort, -2 - termination chunked() - set Transfer-Encoding: chunked.

    Processing Query Development

    Servers and clients Development

    Debug Development

    Servers

    Серверы предназначены для приема запросов и передачи их приложениям.

    Каждый сервер представляет собой класс наследуемый от Сеть\Сервер, который в свой очередь наследуется от Сеть\Пул. Сервер можно инициировать прямо в пользовательском приложении, например:

    /* ... */
    $this->pool = \PHPDaemon\Servers\FlashPolicy::getInstance([
        'listen' => 'tcp://0.0.0.0:843'
    ]);
    $this->pool->onReady();
    /* ... */

    Но не забывайте, что в таком случае следует отправлять ему onReady(), onShutdown() и onConfigUpdated() события.

    В большинстве случаев сервер запускается одноименнным приложением Pool.

    # контекст для ssl соединения (опционально)
    TransportContext:myContext {
        tls;
        certFile "/path/to/cert.pem";
        pkFile "/path/to/privkey.pem";
        passphrase "";
        verifyPeer true;
        allowSelfSigned true;
    }
    
    # слушаем 80 и 443 порт
    Pool:HTTPServer {
        listen "tcp://0.0.0.0:80", "tcp://0.0.0.0:443##myContext";
        port 80;
        privileged;
        maxconcurrency 1;
    }

    Опции серверов Servers

    В данном разделе перечислены опции, используемые всеми серверами.

    HTTP Servers

    The server uses the namespace HTTPRequest.

    This vehicle application provides HTTP server for phpDaemon. Incoming connections will be transferred Websocket WebsocketServer application.

    HTTP is trying to determine the application through AppResolver, be sure to configure it.

    Connection HTTP Servers

    namespace PHPDaemon\Servers\HTTP;
    class Connection extends \PHPDaemon\Network\Connection;
    Constants Connection HTTP Servers
    Methods Connection HTTP Servers

    Pool HTTP Servers

    namespace PHPDaemon\Servers\HTTP;
    class Pool extends \PHPDaemon\Network\Server;
    Options Pool HTTP Servers
    Properties Pool HTTP Servers
    Methods Pool HTTP Servers

    FastCGI Servers

    The server uses the namespace HTTPRequest.

    This vehicle is an application server for FastCGI phpDaemon.

    After configuring phpDaemon you should also use a Web server that supports FastCGI. If you have not made a choice in favor of one of them, we recommend to NGINX.

    The web server can transmit the FastCGI-server option APPNAME, which contains the name of the application that should handle the request. If not passed, FastCGI-server will try to determine this through AppResolver.

    Configuration example NGINX:

    location /Example/ {
        fastcgi_pass unix:/tmp/phpdaemon.fcgi.sock;
        fastcgi_param APPNAME Example;
        include fastcgi_params;
    }

    Connection FastCGI Servers

    namespace PHPDaemon\Servers\FastCGI;
    class Connection extends \PHPDaemon\Network\Connection;
    Constants Connection FastCGI Servers
    Properties Connection FastCGI Servers
    Methods Connection FastCGI Servers

    Pool FastCGI Servers

    namespace PHPDaemon\Servers\FastCGI;
    class Pool extends \PHPDaemon\Network\Server;
    Options Pool FastCGI Servers
    Properties Pool FastCGI Servers
    Methods Pool FastCGI Servers

    DebugConsole Servers

    This vehicle application provides interactive debugging console phpDaemon.

    # telnet 127.0.0.1 8818
    Trying 127.0.0.1...
    Connected to 127.0.0.1.
    Escape character is '^]'.
    Welcome! DebugConsole for phpDaemon.
    
    login secret
    OK.
    eval echo 123;
    123

    Connection DebugConsole Servers

    namespace PHPDaemon\Servers\DebugConsole;
    class Connection extends \PHPDaemon\Network\Connection;
    Properties Connection DebugConsole Servers
    Methods Connection DebugConsole Servers

    Pool DebugConsole Servers

    namespace PHPDaemon\Servers\DebugConsole;
    class Pool extends \PHPDaemon\Network\Server;
    Options Pool DebugConsole Servers

    FlashPolicy Servers

    This simple application provides Flashpolicy server phpDaemon.

    This application should be included in case you want to connect to a server via Flash.

    Connection FlashPolicy Servers

    namespace PHPDaemon\Servers\FlashPolicy;
    class Connection extends \PHPDaemon\Network\Connection;
    Methods Connection FlashPolicy Servers

    Pool FlashPolicy Servers

    namespace PHPDaemon\Servers\FlashPolicy;
    class Pool extends \PHPDaemon\Network\Server;
    Options Pool FlashPolicy Servers
    Properties Pool FlashPolicy Servers
    Methods Pool FlashPolicy Servers

    Ident Servers

    Connection Ident Servers

    namespace PHPDaemon\Servers\Ident;
    class Connection extends \PHPDaemon\Network\Connection;

    Pool Ident Servers

    namespace PHPDaemon\Servers\Ident;
    class Pool extends \PHPDaemon\Network\Server;
    Options Pool Ident Servers
    Methods Pool Ident Servers

    IRCBouncer Servers

    Connection IRCBouncer Servers

    namespace PHPDaemon\Servers\IRCBouncer;
    class Connection extends \PHPDaemon\Network\Connection;
    Properties Connection IRCBouncer Servers
    Methods Connection IRCBouncer Servers

    Pool IRCBouncer Servers

    namespace PHPDaemon\Servers\IRCBouncer;
    class Pool extends \PHPDaemon\Network\Server;
    Options Pool IRCBouncer Servers
    Properties Pool IRCBouncer Servers
    Methods Pool IRCBouncer Servers

    Lock Servers

    It requires refactoring

    Connection Lock Servers

    namespace PHPDaemon\Servers\Lock;
    class Connection extends \PHPDaemon\Network\Connection;
    Properties Connection Lock Servers
    Methods Connection Lock Servers

    Pool Lock Servers

    namespace PHPDaemon\Servers\Lock;
    class Pool extends \PHPDaemon\Network\Server;
    Options Pool Lock Servers
    Properties Pool Lock Servers

    Socks Servers

    Connection Socks Servers

    namespace PHPDaemon\Servers\Socks;
    class Connection extends \PHPDaemon\Network\Connection;
    Constants Connection Socks Servers
    Methods Connection Socks Servers

    SlaveConnection Socks Servers

    namespace PHPDaemon\Servers\Socks;
    class SlaveConnection extends \PHPDaemon\Servers\Socks\Connection;
    Methods SlaveConnection Socks Servers

    Pool Socks Servers

    namespace PHPDaemon\Servers\Socks;
    class Pool extends \PHPDaemon\Network\Server;
    Options Pool Socks Servers

    WebSocket Servers

    The server uses the namespace HTTPRequest.

    This vehicle is an application WebSocket server phpDaemon.

    Your application must obtain a reference to an instance and call WebSocketServer addRoute() to add their own ways. Callback-way function must return a new instance of your class that inherits from WebSocketRoute determines onFrame method. Inside the method onFrame we can contact $this->client->sendFrame() to send packets to the client.

    Connection WebSocket Servers

    namespace PHPDaemon\Servers\WebSocket;
    class Connection extends \PHPDaemon\Network\Connection;
    Constants Connection WebSocket Servers
    Properties Connection WebSocket Servers
    Methods Connection WebSocket Servers

    Pool WebSocket Servers

    namespace PHPDaemon\Servers\WebSocket;
    class Pool extends \PHPDaemon\Network\Server;
    Options Pool WebSocket Servers
    Constants Pool WebSocket Servers
    Properties Pool WebSocket Servers
    Methods Pool WebSocket Servers

    Clients

    At the heart of all customers is the namespace the Network, the study of which will give a greater understanding of customer opportunities and networking daemon as a whole.

    Basics Clients

    Clients options Basics Clients

    Asterisk Clients

    namespace PHPDaemon\Clients\Asterisk;

    Раздел устарел!

    Asterisk - это АТС с открытым исходным кодом. AMI - программный интерфейс (API) Asterisk для управления системой, который позволяет разработчикам отправлять команды на сервер, считывать результаты их выполнения, а так же получать уведомления о происходящих событиях в реальном времени. Клиент Asterisk обеспечивает высокоуровневый интерфейс к AMI, позволяющий разработчикам контролировать сервер Asterisk из приложений.

    В основе документирования клиента лежит материал книги Asterisk: будущее телефонии.

    Использование Asterisk Clients

    @TODO это из вики, проверить

    Перед тем как посылать команды и получать события с сервера, нужно получить сессию(сессии) соединения(соединений) в вашем приложении. В вашем приложении вы получаете объект AsteriskDriver посредством:

    $this->pbxDriver = Daemon::$appResolver->getInstanceByAppName('AsteriskDriver');
    Соединение Использование Asterisk Clients

    Далее получаете объект AsteriskDriverSession посредством:

    $session = $this->pbxDriver->getConnection();
    // или
    foreach($this->pbxConnections as $addr => $conn) {
        $session = $this->pbxDriver->getConnection($addr);
        // что-нибудь делаем...
    }

    Добавляете (композиция) в него текущий контекст соединения посредством:

    $session->context = $this;

    При соединении:

    $session->onConnected(function(SocketSession $session, $status) {
        // ваш код, в зависимости от соединения
    });

    При разрыве:

    $session->onFinish(function(SocketSession $session) {
        // возможно запустить интервал реконнекта...
    });

    Предположим у вас несколько серверов Asterisk с которых вы хотите получать события(events) и на которые вы хотите отправлять команды(actions). Так же вы хотите отслеживать падение соединения(connection failed), и осуществлять реконнект. Смотрите пример реконнекта ниже.

    Немного о формате ввода-вывода Использование Asterisk Clients

    Хотя протокол AMI является строковым, драйвер при вводе-выводе работает с ассоциативными массивами. При получении ответа на действие или события все заголовки и их значения приводятся к нижнему регистру, если значение не содержит информацию, для которой важен регистр - например имя пира.

    Отправка команд и получение ответа Использование Asterisk Clients

    Для отправки команды и получения ответа вы можете воспользоваться либо методом-помощником, который снабжен подробным комментарием из документации Asterisk, либо универсальным методом Connection::action.

    В любом случае для каждой команды вы определяете функцию обратного вызова, в которую будет передан объект сессии соединения и ассоциативный массив пар заголовок-значение ответа.

    Клиент корректно обрабатывает, что порядок следования пакетов ответа не определен, корректно собирает составные пакеты ответа.

    $session->getSipPeers(function(SocketSession $session, array $packet) {
        // $session->addr содержит адрес соединения
        // $session->context содержит контекст вызова (если был установлен)
        // $packet - это массив пар заголовок-значение ответа
        // что-нибудь делаем
    })
    // или
    $session->getConfig('chan_dahdi.conf', array($this, 'doSomething'));
    public function doSomething(SocketSession $session, array $packet) {
    
    }
    // или
    $session->action('Ping', function(SocketSession $session, array $packet) {
        if($packet['response'] == 'success' && $packet['ping'] == 'pong') {
            // успешно сыграли в пинг-понг
        }    
    });
    // или
    // $channel содержит канал из события
    $session->redirect(array(
        'Channel' => $channel,
        'Context' => 'internal',
        'Exten' => '116',
        'Priority' => 1
    ), function(SocketSession $session, array $packet) {
      // узнаем успешно или нет из ответа сервера содержащегося в ассоциативном массиве $packet
    });
    Получение событий сервера Использование Asterisk Clients

    Функция обратного вызова при наступлении события в данном соединении определяется один раз и передается методу onEvent().

    $session->onEvent(array($this, 'onPbxEvent'));

    Когда запущено несколько воркеров, чтобы не получилось, что события канала(характеризуются наличием уникального идентификатора(uniqueid) канала) кратны количеству воркеров(workers) можно воспользоваться таблицей блокировки. Вот пример, когда в качестве таблицы блокировки используется MongoDB коллекция(collection), которая позволяет ставить уникальный индекс на документ:

    $session->onEvent(array($this, 'onPbxEvent'));
    // db.events.ensureIndex({"event": 1, "addr": 1}, {unique: true});
    public function onPbxEvent(SocketSession $session, array $event) {
        if(method_exists('Foo_PbxEventDispatcher', "{$event['event']}Handler")) {
            $handler = "{$event['event']}Handler";
            if(isset($event['uniqueid']) || isset($event['uniqueid1'])) {
                $appInstance = $this;
                $this->db->events->insert(
                    array(
                            'ts' => microtime(true),
                            'event' => $event,
                            'addr' => $session->addr
                    ),
                    function($result) use ($appInstance, $session, $event) {
                        if($result['err'] === null) {
                            $handler = "{$event['event']}Handler";
                            Foo_PbxEventDispatcher::$handler($appInstance, $session, $event);
                        }
                    }
                );
            }
            else {
                Foo_PbxEventDispatcher::$handler($this, $session, $event);
            }
        }
    }

    Пример реконнекта Asterisk Clients

    class Foo extends AppInstance {
        // ...
        public function onInit() {
            // pbxConnections - array of connections
            foreach($this->pbxConnections as $addr => $conn) {
                $pbx_driver_session = $this->pbxDriver->getConnection($addr);
                if($pbx_driver_session instanceof SocketSession) {
                    $pbx_driver_session->context = $this;
                    //$pbx_driver_session->onError(array($this, 'onPbxError'));
                    $pbx_driver_session->onConnected(array($this, 'onPbxConnected'));
                    $pbx_driver_session->onEvent(array($this, 'onPbxEvent'));
                    $pbx_driver_session->onFinish(array($this, 'onPbxFinish'));
                }
                else {
                    $this->runPbxReconnectInterval($pbx_driver_session);
                }
            }
        }
        // ...
        public function onPbxConnected(SocketSession $session, $status) {
            if($status) {
                if($session->context instanceof PbxReconnector) {
                    $session->context->finish();
                }
                // do something...
            }
            else {
                $this->runPbxReconnectInterval($session);
            }
        }
        // ...
        public function onPbxFinish(SocketSession $session) {
            $this->runPbxReconnectInterval($session);
        }
        // ...
        public function runPbxReconnectInterval(SocketSession $session) {
                    if(Daemon::$process->terminated) {
                return;
            }
            foreach ($this->queue as &$r) {
                if($r instanceof PbxReconnector) {
                    if ($r->attrs->addr == $session->addr) {
                        return;
                    }
                }
            }
            $interval = $this->pushRequest(new PbxReconnector($this, $this));
            $interval->attrs->addr = $session->addr;
        }
        // ...
    }
    // ...
    class PbxReconnector extends Request {
            public $interval = 0.3;
    
        public function run() {
            $pbx_driver_session = $this->appInstance->pbxDriver->getConnection($this->attrs->addr);
            if($pbx_driver_session) {
                if($this->appInstance->config->{'pbxreconnectorlogging'}->value) {
                    Daemon::log('Reconnecting to ' . $this->attrs->addr);
                }
                $pbx_driver_session->context = $this;
                $pbx_driver_session->onConnected(array($this->appInstance, 'onPbxConnected'));
                $pbx_driver_session->onFinish(array($this->appInstance, 'onPbxFinish'));
            }
            $this->sleep($this->interval);
        }
    }

    Connection Asterisk Clients

    namespace PHPDaemon\Clients\Asterisk;
    class Connection extends \PHPDaemon\Network\ClientConnection;

    Asterisk Call Manager Connection

    Constants Connection Asterisk Clients
    Properties Connection Asterisk Clients
    Methods Connection Asterisk Clients

    ConnectionFinished Asterisk Clients

    namespace PHPDaemon\Clients\Asterisk;
    class ConnectionFinished extends \PHPDaemon\Exceptions\ConnectionFinished;

    Driver for Asterisk Call Manager/1.1

    Pool Asterisk Clients

    namespace PHPDaemon\Clients\Asterisk;
    class Pool extends \PHPDaemon\Network\Client;

    Class Pool

    Options Pool Asterisk Clients
    Properties Pool Asterisk Clients
    Methods Pool Asterisk Clients

    DNS Clients

    namespace PHPDaemon\Clients\DNS;

    Connection DNS Clients

    namespace PHPDaemon\Clients\DNS;
    class Connection extends \PHPDaemon\Network\ClientConnection;
    Constants Connection DNS Clients
    Properties Connection DNS Clients
    Methods Connection DNS Clients

    Pool DNS Clients

    namespace PHPDaemon\Clients\DNS;
    class Pool extends \PHPDaemon\Network\Client;
    Options Pool DNS Clients
    Properties Pool DNS Clients
    Methods Pool DNS Clients

    Gibson Clients

    namespace PHPDaemon\Clients\Gibson;

    Connection Gibson Clients

    namespace PHPDaemon\Clients\Gibson;
    class Connection extends \PHPDaemon\Network\ClientConnection;
    Constants Connection Gibson Clients
    Properties Connection Gibson Clients
    Methods Connection Gibson Clients

    Pool Gibson Clients

    namespace PHPDaemon\Clients\Gibson;
    class Pool extends \PHPDaemon\Network\Client;
    Options Pool Gibson Clients
    Methods Pool Gibson Clients

    HTTP Clients

    namespace PHPDaemon\Clients\HTTP;

    Предназначен для выполнения GET и POST запросов на удаленные хосты.

    Клиент использует пространство имен HTTPRequest.

    Примеры HTTP Clients

    Получение файла google.com/robots.txt GET запросом:

    $httpclient = \PHPDaemon\Clients\HTTP\Pool::getInstance();
    
    $httpclient->get('http://www.google.com/robots.txt',
        function ($conn, $success) {
            // обработка данных ответа
        }
    );

    Рабочий пример клиента представлен в Clients/HTTP/Examples/Simple.php

    Connection HTTP Clients

    namespace PHPDaemon\Clients\HTTP;
    class Connection extends \PHPDaemon\Network\ClientConnection;
    Constants Connection HTTP Clients
    Properties Connection HTTP Clients
    Methods Connection HTTP Clients

    Pool HTTP Clients

    namespace PHPDaemon\Clients\HTTP;
    class Pool extends \PHPDaemon\Network\Client;
    Options Pool HTTP Clients
    Methods Pool HTTP Clients

    -#.method ```php:p.inline.wico[data-link=https://github.com/kakserpom/phpdaemon/blob/master/PHPDaemon/Clients/HTTP/Pool.php#L40] ( url $url, array $params ); ( url $url, callable $resultcb );

       -.n Performs GET-request
       -.n.ti `:hc`$url`
       -.n `:hc`$params`
       -.n `:hc`$resultcb` — `:phc`callback ( Connection $conn, boolean $success )`
    
     -#.method ```php:p.inline.wico[data-link=https://github.com/kakserpom/phpdaemon/blob/master/PHPDaemon/Clients/HTTP/Pool.php#L77]
     ( url $url, array $data, array $params );
     ( url $url, array $data, callable $resultcb );

    ICMP Clients

    namespace PHPDaemon\Clients\ICMP;

    Connection ICMP Clients

    namespace PHPDaemon\Clients\ICMP;
    class Connection extends \PHPDaemon\Network\ClientConnection;
    Methods Connection ICMP Clients

    Pool ICMP Clients

    namespace PHPDaemon\Clients\ICMP;
    class Pool extends \PHPDaemon\Network\Client;
    Methods Pool ICMP Clients

    IRC Clients

    namespace PHPDaemon\Clients\IRC;

    Channel IRC Clients

    namespace PHPDaemon\Clients\IRC;
    class Channel extends \PHPDaemon\Structures\ObjectStorage;
    Properties Channel IRC Clients
    Methods Channel IRC Clients

    ChannelParticipant IRC Clients

    namespace PHPDaemon\Clients\IRC;
    class ChannelParticipant;
    Properties ChannelParticipant IRC Clients
    Methods ChannelParticipant IRC Clients

    Connection IRC Clients

    namespace PHPDaemon\Clients\IRC;
    class Connection extends \PHPDaemon\Network\ClientConnection;
    Properties Connection IRC Clients
    Methods Connection IRC Clients

    Pool IRC Clients

    namespace PHPDaemon\Clients\IRC;
    class Pool extends \PHPDaemon\Network\Client;
    Options Pool IRC Clients
    Properties Pool IRC Clients
    Methods Pool IRC Clients

    Lock Clients

    namespace PHPDaemon\Clients\Lock;

    It requires refactoring

    Connection Lock Clients

    namespace PHPDaemon\Clients\Lock;
    class Connection extends \PHPDaemon\Network\ClientConnection;
    Methods Connection Lock Clients

    Pool Lock Clients

    namespace PHPDaemon\Clients\Lock;
    class Pool extends \PHPDaemon\Network\Client;
    Options Pool Lock Clients
    Methods Pool Lock Clients

    Memcache Clients

    namespace PHPDaemon\Clients\Memcache;

    Connection Memcache Clients

    namespace PHPDaemon\Clients\Memcache;
    class Connection extends \PHPDaemon\Network\ClientConnection;
    Constants Connection Memcache Clients
    Properties Connection Memcache Clients

    Pool Memcache Clients

    namespace PHPDaemon\Clients\Memcache;
    class Pool extends \PHPDaemon\Network\Client;
    Options Pool Memcache Clients
    Methods Pool Memcache Clients

    Mongo Clients

    namespace PHPDaemon\Clients\Mongo;

    Collection Mongo Clients

    namespace PHPDaemon\Clients\Mongo;
    class Collection;
    Properties Collection Mongo Clients
    Methods Collection Mongo Clients

    Connection Mongo Clients

    namespace PHPDaemon\Clients\Mongo;
    class Connection extends \PHPDaemon\Network\ClientConnection;
    Constants Connection Mongo Clients
    Properties Connection Mongo Clients
    Methods Connection Mongo Clients

    ConnectionFinished Mongo Clients

    namespace PHPDaemon\Clients\Mongo;
    class ConnectionFinished extends \PHPDaemon\Exceptions\ConnectionFinished;

    Cursor Mongo Clients

    namespace PHPDaemon\Clients\Mongo;
    class Cursor;
    Properties Cursor Mongo Clients
    Methods Cursor Mongo Clients

    MongoId Mongo Clients

    namespace PHPDaemon\Clients\Mongo;
    class MongoId extends \MongoId;
    Methods MongoId Mongo Clients

    Pool Mongo Clients

    namespace PHPDaemon\Clients\Mongo;
    class Pool extends \PHPDaemon\Network\Client;
    Options Pool Mongo Clients
    Constants Pool Mongo Clients
    Properties Pool Mongo Clients
    Methods Pool Mongo Clients

    MySQL Clients

    namespace PHPDaemon\Clients\MySQL;

    Client for the DBMS MySQL

    Use MySQL Clients

    @TODO

    In your application, you should receive an object MySQLClient through Daemon::$appResolver->getInstanceByAppName('MySQLClient') and use as described below.

    Preparing the connection object Use MySQL Clients
    /*
      @method getConnection
      @description Establishes connection.
      @param string Optional. Address.
      @return integer Connection's ID.
    */

    You should get MySQLClientSession object by the method $MySQLClient->getConnection(), then you can put your current request / session / anything else in the current context of the connection (in the context property).

    Then use:

    $this->sql->onConnected(
        function($sql, $success) {
            if (!$success) {
                return;
            }
            // your connection-dependent code
        }
    );

    Examples MySQL Clients

    $sql->query('SHOW VARIABLES', 
       function($sql, $success) {
          $sql->context->queryResult = $sql->resultRows; // save the result
          $sql->context->wakeup(); // wake up the request immediately
       }
    );

    When the callback-function is called, $sql->context contains your subject that you put there before. $sql->resultRows stores the result in an array of associative arrays. $sql->resultFields field contains the response as an array of associative arrays.

    Connection MySQL Clients

    namespace PHPDaemon\Clients\MySQL;
    class Connection extends \PHPDaemon\Network\ClientConnection;
    Constants Connection MySQL Clients
    Properties Connection MySQL Clients
    Methods Connection MySQL Clients

    ConnectionFinished MySQL Clients

    namespace PHPDaemon\Clients\MySQL;
    class ConnectionFinished extends \PHPDaemon\Exceptions\ConnectionFinished;

    Pool MySQL Clients

    namespace PHPDaemon\Clients\MySQL;
    class Pool extends \PHPDaemon\Network\Client;
    Options Pool MySQL Clients
    Constants Pool MySQL Clients
    Methods Pool MySQL Clients

    PostgreSQL Clients

    namespace PHPDaemon\Clients\PostgreSQL;

    Connection PostgreSQL Clients

    namespace PHPDaemon\Clients\PostgreSQL;
    class Connection extends \PHPDaemon\Network\ClientConnection;
    Constants Connection PostgreSQL Clients
    Properties Connection PostgreSQL Clients
    Methods Connection PostgreSQL Clients

    ConnectionFinished PostgreSQL Clients

    namespace PHPDaemon\Clients\PostgreSQL;
    class ConnectionFinished extends \PHPDaemon\Exceptions\ConnectionFinished;

    Pool PostgreSQL Clients

    namespace PHPDaemon\Clients\PostgreSQL;
    class Pool extends \PHPDaemon\Network\Client;
    Options Pool PostgreSQL Clients

    Redis Clients

    namespace PHPDaemon\Clients\Redis;

    Connection Redis Clients

    namespace PHPDaemon\Clients\Redis;
    class Connection extends \PHPDaemon\Network\ClientConnection;
    Constants Connection Redis Clients
    Properties Connection Redis Clients
    Methods Connection Redis Clients

    Lock Redis Clients

    namespace PHPDaemon\Clients\Redis;
    class Lock;
    Methods Lock Redis Clients

    MultiEval Redis Clients

    namespace PHPDaemon\Clients\Redis;
    class MultiEval;

    Easy wrapper for queue of eval's

    Properties MultiEval Redis Clients
    Methods MultiEval Redis Clients

    Pool Redis Clients

    namespace PHPDaemon\Clients\Redis;
    class Pool extends \PHPDaemon\Network\Client;
    Options Pool Redis Clients
    Properties Pool Redis Clients
    Methods Pool Redis Clients

    Valve Clients

    namespace PHPDaemon\Clients\Valve;

    Connection Valve Clients

    namespace PHPDaemon\Clients\Valve;
    class Connection extends \PHPDaemon\Network\ClientConnection;
    Properties Connection Valve Clients
    Methods Connection Valve Clients

    Pool Valve Clients

    namespace PHPDaemon\Clients\Valve;
    class Pool extends \PHPDaemon\Network\Client;
    Options Pool Valve Clients
    Constants Pool Valve Clients
    Methods Pool Valve Clients

    WebSocket Clients

    namespace PHPDaemon\Clients\WebSocket;

    Connection WebSocket Clients

    namespace PHPDaemon\Clients\WebSocket;
    class Connection extends \PHPDaemon\Network\ClientConnection;

    Class Connection

    Constants Connection WebSocket Clients
    Properties Connection WebSocket Clients
    Methods Connection WebSocket Clients

    Pool WebSocket Clients

    namespace PHPDaemon\Clients\WebSocket;
    class Pool extends \PHPDaemon\Network\Client;
    Options Pool WebSocket Clients
    Constants Pool WebSocket Clients
    Methods Pool WebSocket Clients

    XMPP Clients

    namespace PHPDaemon\Clients\XMPP;

    Connection XMPP Clients

    namespace PHPDaemon\Clients\XMPP;
    class Connection extends \PHPDaemon\Network\ClientConnection;
    Properties Connection XMPP Clients
    Methods Connection XMPP Clients

    XMPPRoster XMPP Clients

    namespace PHPDaemon\Clients\XMPP;
    class XMPPRoster;
    Properties XMPPRoster XMPP Clients
    Methods XMPPRoster XMPP Clients

    Pool XMPP Clients

    namespace PHPDaemon\Clients\XMPP;
    class Pool extends \PHPDaemon\Network\Client;
    Options Pool XMPP Clients

    Libraries

    Cache Libraries

    namespace PHPDaemon\Cache;

    Механизм локального LRU-кеша ключ-значение.

    Используется для кеширования замыканий созданных через create_function. Также используется в Clients\DNS

    CappedStorageHits Cache Libraries

    namespace PHPDaemon\Cache;
    class CappedStorageHits extends \PHPDaemon\Cache\CappedStorage;

    CappedStorageHits

    Item Cache Libraries

    namespace PHPDaemon\Cache;
    class Item;

    Item

    Properties Item Cache Libraries
    Methods Item Cache Libraries

    CappedStorage Cache Libraries

    namespace PHPDaemon\Cache;
    class CappedStorage;

    CappedStorage

    Properties CappedStorage Cache Libraries
    Methods CappedStorage Cache Libraries

    ComplexJob Libraries

    namespace PHPDaemon\Core;
    class ComplexJob extends \ArrayAccess;

    ComplexJob class object allows you to hang up the callback function for the completion of all announced it procedures. This is useful when you need to perform a number of independent chains of action.

    Примеры ComplexJob Libraries

    $j = new ComplexJob(function($j) { // Когда всё выполнилось
       D($j['foo']); // this
       D($j['foobar']); // is
       D($j['bar']); // sparta
    });
    
    /* Add a Task */
    $j('foo', function($name, $j) { 
       $j[$name] = 'this'; // Call setResult()
    
       /* Another Problem */
       $j('foobar', function($name, $j) { 
          $j[$name] = 'is';
       });
    });
    
    /* And Another */
    $j('bar', function($name, $j) {
       $j[$name] = 'sparta';
    });
    
    $j(); // Run

    Constants ComplexJob Libraries

    Properties ComplexJob Libraries

    Methods ComplexJob Libraries

    ShellCommand Libraries

    namespace PHPDaemon\Core;
    class ShellCommand extends \PHPDaemon\Network\IOStream;

    Class is the successor IOStream, so that there are available methods such as read[ln], write[ln], and so on.

    Examples ShellCommand Libraries

    Easily perform analogue functions shell_exec ShellCommand Libraries

    ShellCommand::exec('echo "foo"', function($commandInstance, $output) {
       D($output); // foo
    });
    With additional parameters and environment variables Easily perform analogue functions shell_exec ShellCommand Libraries
    $command = 'git log';
    $cb = function($commandInstance, $output) {
         D($output); // foo
    };
    $arguments = ['-1', '--pretty' => 'oneline'];
    $env = [];
    ShellCommand::exec($command, $cb, $arguments, $env);

    Arguments will be screened using escapeshellarg

    Batch Output

    @TODO

    Properties ShellCommand Libraries

    Methods ShellCommand Libraries

    Timer Libraries

    namespace PHPDaemon\Core;
    class Timer;

    With this class can be created in the pending event (timers) time

    Examples Timer Libraries

    $i = 0;
    setTimeout(function($timer) use (&$i) {
     D("5 seconds passed!");
    
     if (++$i < 3) {
        // start the timer for another 5 seconds
        $timer->timeout();
     } else {
        D('Конец');
        $timer->free();
     }
    }, 5e6);

    Global Functions Timer Libraries

    Properties Timer Libraries

    Methods Timer Libraries

    TransportContext Libraries

    namespace PHPDaemon\Core;
    class TransportContext extends AppInstance;

    @TODO

    FS Libraries

    namespace PHPDaemon\FS;

    File FS Libraries

    namespace PHPDaemon\FS;
    class File;

    File

    Properties File FS Libraries
    Methods File FS Libraries

    FileSystem FS Libraries

    namespace PHPDaemon\FS;
    class FileSystem;

    FileSystem

    Properties FileSystem FS Libraries
    Methods FileSystem FS Libraries

    FileWatcher FS Libraries

    namespace PHPDaemon\FS;
    class FileWatcher;

    Implementation of the file watcher

    Properties FileWatcher FS Libraries
    Methods FileWatcher FS Libraries

    PubSub Libraries

    namespace PHPDaemon\PubSub;

    PubSub PubSub Libraries

    namespace PHPDaemon\PubSub;
    class PubSub;

    PubSub

    Methods PubSub PubSub Libraries

    PubSubEvent PubSub Libraries

    namespace PHPDaemon\PubSub;
    class PubSubEvent extends \SplObjectStorage;

    PubSubEvent

    Properties PubSubEvent PubSub Libraries
    Methods PubSubEvent PubSub Libraries

    SockJS Libraries

    namespace PHPDaemon\SockJS;

    Session SockJS Libraries

    namespace PHPDaemon\SockJS;
    class Session;
    Properties Session SockJS Libraries
    Methods Session SockJS Libraries

    Application SockJS Libraries

    namespace PHPDaemon\SockJS;
    class Application extends \PHPDaemon\Core\AppInstance;
    Options Application SockJS Libraries
    Properties Application SockJS Libraries
    Methods Application SockJS Libraries

    WebSocketRouteProxy SockJS Libraries

    namespace PHPDaemon\SockJS;
    class WebSocketRouteProxy;

    WebSocketConnectionProxy SockJS Libraries

    namespace PHPDaemon\SockJS;
    class WebSocketConnectionProxy;

    / TestRelay SockJS Libraries

    Application / TestRelay SockJS Libraries
    namespace PHPDaemon\SockJS\TestRelay;
    class Application extends \PHPDaemon\Core\AppInstance;
    namespace PHPDaemon\SockJS\TestRelay;
    class Close extends \PHPDaemon\WebSocket\Route;
    EchoFeed Close Application / TestRelay SockJS Libraries
    namespace PHPDaemon\SockJS\TestRelay;
    class EchoFeed extends \PHPDaemon\WebSocket\Route;
    namespace PHPDaemon\SockJS\Methods;
    class JsonpSend extends \PHPDaemon\SockJS\Methods\Generic;
    namespace PHPDaemon\SockJS\Methods;
    class Xhr extends \PHPDaemon\SockJS\Methods\Generic;
    namespace PHPDaemon\SockJS\Methods;
    class Generic extends \PHPDaemon\HTTPRequest\Generic;

    Contains some base methods

    namespace PHPDaemon\SockJS\Methods;
    class XhrSend extends \PHPDaemon\SockJS\Methods\Generic;
    namespace PHPDaemon\SockJS\Methods;
    class NotFound extends \PHPDaemon\SockJS\Methods\Generic;
    namespace PHPDaemon\SockJS\Methods;
    class Info extends \PHPDaemon\SockJS\Methods\Generic;
    namespace PHPDaemon\SockJS\Methods;
    class XhrStreaming extends \PHPDaemon\SockJS\Methods\Generic;
    namespace PHPDaemon\SockJS\Methods;
    class Eventsource extends \PHPDaemon\SockJS\Methods\Generic;
    namespace PHPDaemon\SockJS\Methods;
    class Jsonp extends \PHPDaemon\SockJS\Methods\Generic;
    namespace PHPDaemon\SockJS\Methods;
    class Welcome extends \PHPDaemon\SockJS\Methods\Generic;
    namespace PHPDaemon\SockJS\Methods;
    class Htmlfile extends \PHPDaemon\SockJS\Methods\Generic;
    namespace PHPDaemon\SockJS\Methods;
    class IFrame extends \PHPDaemon\SockJS\Methods\Generic;

    Applications

    MongoNode Applications

    namespace PHPDaemon\Examples;
    class MongoNode;

    This application provides MongoDB replication node. This makes it possible to install arbitrary hooks to add / edit / delete objects.

    Requirements MongoNode Applications

    Required module installed pecl / mongo and included phpdaemon / MongoCllient.

    MongoNode When enabled, it immediately gets the new changes in the database.

    Default:

    If the object has the property "_key" serialized its value is sent to the Memcache key under that name, which is set within the meaning of _key. When an object is deleted from the MongoDB, it is removed from Memcache.

    If the object has the property "_ev", its value is sent to the RTEP-event under the name that is specified in the value _ev.

    TelnetHoneypot Applications

    namespace PHPDaemon\Examples;
    class TelnetHoneypot;

    This application provides a simple telnet server for phpDaemon.

    [[email protected] phpdaemon.wiki]# telnet 127.0.0.1 23
    Trying 127.0.0.1...
    Connected to 127.0.0.1.
    Escape character is '^]'.
    ping
    pong

    ServerStatus Applications

    namespace PHPDaemon\Applications;
    class ServerStatus;

    This application provides information about the state of phpDaemon over HTTP, similar to the console command phpd fullstatus.

    It is necessary to add conf/phpd.conf:

    ServerStatus {
        enable    1;
    }
    HTTP {
        enable 1;
        privileged;
    }

    Also conf/AppResolver.php in the method of getRequestRoute() adding a condition to start the method beginRequest() in ServerStatus application. For example, to get information about phpDaemon at http:///ServerStatus/:

    /**
     * Routes incoming request to related application. Method is for overloading.   
     * @param object Request.
     * @param object AppInstance of Upstream.
     * @return string Application's name.
     */
    public function getRequestRoute($req, $upstream) {
        if (preg_match('~^/(ServerStatus|Example)/~', $req->attrs->server['DOCUMENT_URI'], $m)) {
            return $m[1];
        }
    }

    Sample answer:

    Uptime: 1 day. 11 hour. 33 min. 51 sec.
    State of workers:
            Total: 4
            Idle: 4
            Busy: 0
            Shutdown: 20
            Pre-init: 0
            Wait-init: 0
            Init: 0

    If you are using --logworkersetstatus option, the line is:

    Utils

    Binary Utils

    namespace PHPDaemon\Utils;
    class Binary;

    This class provides a set of static methods for working with binary data.

    Methods Binary Utils

    Crypt Utils

    namespace PHPDaemon\Utils;
    class Crypt;

    This class contains methods related to cryptography.

    Methods Crypt Utils

    DateTime Utils

    namespace PHPDaemon\Utils;
    class DateTime extends \DateTime;

    Can pass a Unix timestamp to the constructor.

    Methods DateTime Utils

    Encoding Utils

    namespace PHPDaemon\Utils;
    class Encoding;

    Third-party libraries — forceutf8

    Methods Encoding Utils

    IRC Utils

    namespace PHPDaemon\Utils;
    class IRC;

    Class used in the IRC-client and IRC-bouncer

    Properties IRC Utils

    Methods IRC Utils

    MIME Utils

    namespace PHPDaemon\Utils;
    class MIME;

    Methods MIME Utils

    ShmEntity Utils

    namespace PHPDaemon\Utils;
    class ShmEntity;

    Elastic heap storage in the shared memory

    It used to store an array of workflow status.

    Methods ShmEntity Utils

    Terminal Utils

    namespace PHPDaemon\Utils;
    class Terminal;


    This class needs work: lacks full ncurses support. If you would like to help, click on the cat!

    Methods Terminal Utils

    Structures

    ObjectStorage Structures

    namespace PHPDaemon\Structures;
    class ObjectStorage extends \SplObjectStorage;

    This class provides an object store with a few additional methods

    You can subclass one

    Methods ObjectStorage Structures

    PriorityQueueCallbacks Structures

    namespace PHPDaemon\Structures;
    class PriorityQueueCallbacks extends \SplPriorityQueue;

    Used in Network/Client to store calls, until all available connections are busy

    StackCallbacks Structures

    namespace PHPDaemon\Structures;
    class StackCallbacks extends \SplStack;

    Данный класс предоставляет стек функций обратного вызова с несколькими дополнительными методами

    Используется в Network/Client для хранения стека функций обратного вызова запросов

    Methods StackCallbacks Structures

    Traits

    Примеси (англ. traits).

    Данный раздел описывает доступные для разработчиков встроенные примеси.

    ClassWatchdog Traits

    namespace PHPDaemon\Traits;
    trait ClassWatchdog;

    Данная примесь уже использована во всех базовых классах и при наследовании от них не нужно использовать её повторно.

    Эта примесь нужна, чтобы предотвратить появление ошибки уровня E_ERROR (Fatal error) при обращении к несуществующему методу. E_ERROR же прерывает работу всего рабочего процесса, что недопустимо в реалиях phpDaemon. Настоятельно рекомендуется к использованию во всех используемых классах.

    Определены следующие магические методы:

    StaticObjectWatchdog Traits

    namespace PHPDaemon\Traits;
    trait StaticObjectWatchdog;

    Данная примесь уже использована во всех базовых классах и при наследовании от них не нужно использовать её повторно.

    PHP-машина умеет хранить набор свойств объекта двумя способами: в виде фиксированного массива и в виде ассоциативной таблицы (англ. hash table) с использованием B-дерева. Изначально, при создании любого объекта, свойства хранятся в виде массива с быстрым доступом. При первой попытке установить значение свойства не объявленного директивой visibility $name, набор свойств конвертируется в ассоциативную таблицу. То же самое происходит при удалении (unset) любого свойства). Данная операция сама по себе не самая быстрая, особенно при большом количестве свойств), но и доступ к свойствам после неё замедляется. Разумеется, есть объекты с намеренно динамическим набором свойств, которые сродни ассоциативным массивам и с ними всё в порядке. Но часто бывает так, что программист забывает добавить объявление свойства или даже опечатывается в его названии. Порой это ведёт к сильному ухудшению производительности, которое трудно расследовать.

    Прежде чем говорить, что PHP медленный, неплохо бы научиться его готовить.

    Данная примесь определяет следующие магические методы:

    StrictStaticObjectWatchdog Traits

    namespace PHPDaemon\Traits;
    trait StrictStaticObjectWatchdog;

    Поведение аналогично StaticObjectWatchdog, но эта примесь бросает исключение, вместо записи в журнал.

    Определяет следующие магические методы:

    DeferredEventHandlers Traits

    namespace PHPDaemon\Traits;
    trait DeferredEventHandlers;

    Данная примесь реализует механизм отложенных событий в объекте.

    class MyClass {
        use \PHPDaemon\Traits\DeferredEventHandlers;
        protected function onSomethingEvent($foo, $bar) {
            return function($ev) {
                list ($foo, $bar = $ev->args;
                $ev->setResult("Foo is $foo, bar is $bar");
            };
        }
    }
    $o = new MyClass;
    $o->onSomething(function($ev) {
        D($ev->result);
        // Foo is fooo, bar is barr
    }, 'foo', 'barr');
    
    $o->onSomething(function($ev) {
        D($ev->result);
        // Foo is fooo, bar is barr
    });

    При этом когда результат уже установлен, производящее его замыкание не будет вызвано повторно. Не нужно беспокоиться о повторном вызове еще до того как результат установлен, ожидающие замыкания будут вызваны правильно.

    EventHandlers Traits

    namespace PHPDaemon\Traits;
    trait EventHandlers;

    Данная примесь реализует простой механизм PUB/SUB для объекта.

    class MyClass {
        use \PHPDaemon\Traits\EventHandlers;
    }
    $o = new MyClass;
    
    $o->on('smth', function($o, $foo, $bar) {
        D("Foo is $foo, bar is $bar");
    });
    
    $o->trigger('smth', 'foo', 'barr');
    

    Не забывайте о том, что при удалении такого объекта необходимо вызвать метод cleanupEventHandlers(), чтобы избежать утечек памяти.

    Sessions Traits

    namespace PHPDaemon\Traits;
    trait Sessions;

    Эта примесь реализует механизм сессий, именно реализует, а не является оберткой над session_* функциями.

    Почему мы не можем использовать нативный механизм сессий PHP?

    Как и нативная реализация, поведение сессий основывается на php.ini.

    Текущая реализация поддерживает хранение сессий в файлах, session.serialize_handler = php|php_binary, lock r+! файлов - аналогичный нативному - для предотвращения race condition.

    Вы можете безопасно использовать PhpDaemon c существующими сессиями, сериализация совместима с нативной (См. session_encode, session_decode).

    Пример использования:

    $this->onSessionStart(function ($event) {
        if (!$event->getResult()) {
            //Session open failed
        }
        //Session open succeed
    });

    Данная примесь используется в HTTPRequest и Servers\WebSocket\Route

    DNode Traits

    trait \PHPDaemon\WebSocket\Traits\DNode

    Данная примесь применима в классах-наследниках Servers\WebSocket\Route

    Примесь реализует серверную часть протокола DNode, который служит для Удалённого вызова процедур (RPC).

    Для подключение примеси нужно внести use \PHPDaemon\WebSocket\Traits\DNode в определение своего класса-наследника Servers\WebSocket\Route.

    Затем необходимо определить методы, доступные клиенту. Фактически это делает метод defineLocalMethods, который должен вызываться в onHandshake.

    Давайте, для примера, создадим метод dummy с аргументами $foo, $bar и $callback:

    protected function dummyMethod($foo, $bar, $callback) {
        if (!static::ensureCallback($callback)) {
            /* $callback не содержит функцию обратного вызова */
            return;
        }
        $callback(md5($foo ^ $bar));
    }

    При обращении dummy('Hello', 'World', function(result) {...}) ответом будет вызов этой функции с аргументом bd7815679056a50c3f545b159ce5e385 — результатом выполнения md5('Hello' ^ 'World')

    В качестве аргументов можно передавать передавать собственные функции обратного вызова, но учтите, что они удаляются из памяти после вызова, если возвратное значение не является true. Таким образом, следует понимать ожидается ли повторный вызов, и в этом случае возвращать true. Это делается во избежание утечек памяти.

    Для вызова удаленного метода по имени, используйте callRemote.

    Как вы могли заметить, пример dummyMethod использует вызов static::ensureCallback($callback). Всегда нужно проверять переданный аргумент с помощью ensureCallback перед его исполнением. В противном случае, это обернётся серьёзной брешью безопасности.

    Methods DNode Traits

    Network

    Pool Network

    namespace PHPDaemon\Network;
    abstract class Pool extends ObjectStorage;

    @TODO translate to english

    Keeps objects in the currently active compound and OtkrytyySoket.

    Poole (client or server) can be instantiated from a user application, such as:

    $this->httpclient = \PHPDaemon\Clients\HTTP\Pool::getInstance();

    или

    /* ... */
    $this->pool = \PHPDaemon\Servers\FlashPolicy\Pool::getInstance([
        'listen' => 'tcp://0.0.0.0:843'
    ]);
    $this->pool->onReady();
    /* ... */

    Но не забывайте отправлять ему onReady(), onShutdown() и onConfigUpdated() события.

    В большинстве случаев сервер запускается одноименнным приложением Pool.

    # контекст для ssl соединения (опционально)
    TransportContext:myContext {
        tls;
        certFile "/path/to/cert.pem";
        pkFile "/path/to/privkey.pem";
        passphrase "";
        verifyPeer true;
        allowSelfSigned true;
    }
    
    # слушаем 80 и 443 порт
    Pool:HTTPServer {
        listen "tcp://0.0.0.0:80", "tcp://0.0.0.0:443##myContext";
        port 80;
        privileged;
        maxconcurrency 1;
    }

    Properties Pool Network

    Methods Pool Network

    Client Network

    namespace PHPDaemon\Network;
    abstract class Client extends Pool;

    @TODO

    Options Client Network

    Methods Client Network

    ClientConnection Network

    namespace PHPDaemon\Network;
    class ClientConnection extends Connection;

    @TODO

    Methods ClientConnection Network

    Connection Network

    namespace PHPDaemon\Network;
    abstract class Connection extends IOStream;

    @TODO

    Methods Connection Network

    IOStream Network

    namespace PHPDaemon\Network;
    abstract class IOStream;

    @TODO

    Constants IOStream Network

    Properties IOStream Network

    Methods IOStream Network

    Server Network

    namespace PHPDaemon\Network;
    abstract class Server extends Pool;

    @TODO

    Properties Server Network

    Methods Server Network

    HTTPRequest

    Generic HTTPRequest

    namespace PHPDaemon\HTTPRequest;
    abstract class Generic extends \PHPDaemon\Request\Generic;

    @TODO

    Properties Generic HTTPRequest

    Methods Generic HTTPRequest

    Input HTTPRequest

    namespace PHPDaemon\HTTPRequest;
    class Input extends \EventBuffer;

    @TODO

    FAQ

    How to make the event, which is called after a specified time interval?

    See. Library/Timer

    Publications

    ...

    Contribute

    If you want to help the project, then do not hesitate to start even if you have only a bit of time for it. Any help is appreciated.

    This documentation Contribute

    We are struggling to minimize amount of undocumented parts, but we are running out of hands. Even a paragraph written in 10 minutes is a big deal.

    Making changes This documentation Contribute

    Consider writing in the language you know best among all others. If you are bold enough to add new language, base it upon the most similar one of existing languages.

    1. Fork a repository kakserpom/daemon.io
    2. Change Markdown (.md) files in folder ./docs/<language>/
    3. Compile index.html by executing ./docs/build
    4. Look how it looks in browser
    5. Send Pull Request

    Want to see changes in browser without running the command? Run watch -n1 ./docs/build — it shall be rebuilt every second

    Format of documentation This documentation Contribute

    We use the Markdown with some extensions.

    For your convenience, documentation is split between many small files. Including a file: <!-- import filepath.md -->. Path is relative.

    Constants are used for i18n and shortcuts for frequently used templates. They may be defined as simple as that: <!-- pvar Name Value -->

    Mandatory i18n contants lang, title and menu-* must be present in each translation of this documentation.

    Constants may be used as templates. Calling a template: {Name Value1 Value1...}. Values will be places in result instead of %s.

    Example of a template:
    <!-- pvar tpl-outlink <a target="_blank" href="%s">%s<i class="fa fa-external-link"></i></a> -->

    Example of its usage:
    {tpl-outlink http://en.wikipedia.org/wiki/Markdown Markdown}

    Headings may be defined like that:

    anchor - an identifier for navigation which takes place in URL. Allowed symbols are [a-zA-Z0-9_-]. Must be unique among anchors of its level to avoid URL collisions.

    Formatted heading is used in case if heading in the page body should differ from heading in the navigation bar.

    Examples:

    If you are adding new heading, make sure that anchor is written in English (strictly) and is simple and informative. Anchors are not supposed to be translated

    You can set CSS class of list element.

     -.n Element without list mark
     -.n.ti Element without list mark with indentation from the previous one

    The following classes are currently in use:

    Italic and bold works with *, _ is not available due to the compatibility reasons.

    Wrapping of a code with apostrophes `...` дополнено возможностью применять модификаторы и CSS-классы.
    Модификаторы — это опции, включающие дополнительную обработку текста. w Модификаторы и классы пишутся после открывающего апострофа и должны быть закрыты дополнительным перед началом текста. Перед указанием модификаторов ставится символ : (двоеточие). Каждый модификатор указывается одним латинским символом. Классы указываются с помощью ведущей точки.

    При указании одновременно и модификаторов, и классов, сначала должны быть записаны модификаторы.

    Список модификаторов:

    Из классов на данный момент может применять только .clear, но лучше указывайте модификатор :c.

    Примеры использования:

    Многострочный код Format of documentation This documentation Contribute

    Многострочный код добавлен возможностью подсветки синтаксиса и указанием CSS-классов. Код, содержащий конфигурацию, обозначается синтаксисом ruby.

    Из классов на данный момент может применять только .inline для оформления методов.

    Примеры:

    ```php.inline
    void public post ( url $url, array $data, array $params )
    void public post ( url $url, array $data, callable $resultcb )
    ```

    ```ruby
    Pool:HTTPServer {
        listen "tcp://0.0.0.0:80", "tcp://0.0.0.0:443##myContext";
        port 80;
        privileged;
        maxconcurrency 1;
    }
    ```

    PHPDoc Contribute

    Аналогично, чтобы восполнить пробелы в PHPDoc-комментариях в коде, сделайте Fork основного репозитория, внесите изменения и пошлите Pull Request.

    Учтите, что все PHPDoc-комментарии пишутся строго на английском языке

    Программный код Contribute

    Улучшения программного кода всегда приветствуется. Если у вас есть модуль для публикации, и вы считаете, что он заслуживает включения в основной репозиторий, пришлите Pull Request. Аналогично поступайте с улучшениями существующего кода.

    Authors of documentation

    English proofreading Authors of documentation

    ...

    Old contributors

    Fork me on GitHub