EventBufferEvent::sslFilter

(PECL event >= 1.2.6-beta)

EventBufferEvent::sslFilter — Crea un nuevo evento búfer SSL búfer para enviar sus datos a otro evento búfer

Descripción

public static EventBufferEvent EventBufferEvent::sslFilter ( EventBase $base , EventBufferEvent $underlying , EventSslContext $ctx , int $state [, int $options = 0 ] )

Crea un nuevo evento búfer SSL búfer para enviar sus datos a otro evento búfer

Nota:

Esta función está disponible solo si This function is available only if Event es compilado con suporte para OpenSSL.

Parámetros

base

Evento base asociado.

underlying

El socket evento búfer para usar en esta SSL.

ctx

Objecto de la clase EventSslContext.

state

El estado actual de la conexión SSL: EventBufferEvent::SSL_OPEN , EventBufferEvent::SSL_ACCEPTING o EventBufferEvent::SSL_CONNECTING .

options

Una o más opciones del evento búfer.

Valores devueltos

Devuelve un nuevo objecto SSL EventBufferEvent.

Ejemplos

Ejemplo #1 Simple SMTP server

<?php
 
/*
 * Author: Andrew Rose <hello at andrewrose dot co dot uk>
 *
 * Usage:
 * 1) Prepare cert.pem certificate and privkey.pem private key files.
 * 2) Launch the server script
 * 3) Open TLS connection, e.g.:
 *      $ openssl s_client -connect localhost:25 -starttls smtp -crlf
 * 4) Start testing the commands listed in `cmd` method below.
 */

class Handler {
    public 
$domainName = FALSE;
    public 
$connections = [];
    public 
$buffers = [];
    public 
$maxRead = 256000;

    public function 
__construct() {
        
$this->ctx = new EventSslContext(EventSslContext::SSLv3_SERVER_METHOD, [
            
EventSslContext::OPT_LOCAL_CERT  => 'cert.pem',
            
EventSslContext::OPT_LOCAL_PK    => 'privkey.pem',
            
//EventSslContext::OPT_PASSPHRASE  => '',
            
EventSslContext::OPT_VERIFY_PEER => false, // change to true with authentic cert
            
EventSslContext::OPT_ALLOW_SELF_SIGNED => true // change to false with authentic cert
        
]);

        
$this->base = new EventBase();
        if (!
$this->base) {
            exit(
"Couldn't open event base\n");
        }

        if (!
$this->listener = new EventListener($this->base,
            [
$this, 'ev_accept'],
            
$this->ctx,
            
EventListener::OPT_CLOSE_ON_FREE | EventListener::OPT_REUSEABLE,
            -
1,
            
'0.0.0.0:25'))
        {
            exit(
"Couldn't create listener\n");
        }

        
$this->listener->setErrorCallback([$this, 'ev_error']);
        
$this->base->dispatch();
    }

    public function 
ev_accept($listener, $fd, $address, $ctx) {
        static 
$id = 0;
        
$id += 1;

        
$this->connections[$id]['clientData'] = '';
        
$this->connections[$id]['cnx'] = new EventBufferEvent($this->base, $fd,
            
EventBufferEvent::OPT_CLOSE_ON_FREE);

        if (!
$this->connections[$id]['cnx']) {
            echo 
"Failed creating buffer\n";
            
$this->base->exit(NULL);
            exit(
1);
        }

        
$this->connections[$id]['cnx']->setCallbacks([$this, "ev_read"], NULL,
            [
$this, 'ev_error'], $id);
        
$this->connections[$id]['cnx']->enable(Event::READ | Event::WRITE);

        
$this->ev_write($id, '220 '.$this->domainName." wazzzap?\r\n");
    }

    function 
ev_error($listener, $ctx) {
        
$errno = EventUtil::getLastSocketErrno();

        
fprintf(STDERR, "Got an error %d (%s) on the listener. Shutting down.\n",
            
$errno, EventUtil::getLastSocketError());

        if (
$errno != 0) {
            
$this->base->exit(NULL);
            exit();
        }
    }

    public function 
ev_close($id) {
        
$this->connections[$id]['cnx']->disable(Event::READ | Event::WRITE);
        unset(
$this->connections[$id]);
    }

    protected function 
ev_write($id, $string) {
        echo 
'S('.$id.'): '.$string;
        
$this->connections[$id]['cnx']->write($string);
    }

    public function 
ev_read($buffer, $id) {
        while(
$buffer->input->length > 0) {
            
$this->connections[$id]['clientData'] .= $buffer->input->read($this->maxRead);
            
$clientDataLen = strlen($this->connections[$id]['clientData']);

            if(
$this->connections[$id]['clientData'][$clientDataLen-1] == "\n"
                
&& $this->connections[$id]['clientData'][$clientDataLen-2] == "\r")
            {
                
// remove the trailing \r\n
                
$line = substr($this->connections[$id]['clientData'], 0,
                    
strlen($this->connections[$id]['clientData']) - 2);

                
$this->connections[$id]['clientData'] = '';
                
$this->cmd($buffer, $id, $line);
            }
        }
    }

    protected function 
cmd($buffer, $id, $line) {
        switch (
$line) {
            case 
strncmp('EHLO ', $line, 4):
                
$this->ev_write($id, "250-STARTTLS\r\n");
                
$this->ev_write($id, "250 OK ehlo\r\n");
                break;

            case 
strncmp('HELO ', $line, 4):
                
$this->ev_write($id, "250-STARTTLS\r\n");
                
$this->ev_write($id, "250 OK helo\r\n");
                break;

            case 
strncmp('QUIT', $line, 3):
                
$this->ev_write($id, "250 OK quit\r\n");
                
$this->ev_close($id);
                break;

            case 
strncmp('STARTTLS', $line, 3):
                
$this->ev_write($id, "220 Ready to start TLS\r\n");
                
$this->connections[$id]['cnx'] = EventBufferEvent::sslFilter($this->base,
                    
$this->connections[$id]['cnx'], $this->ctx,
                    
EventBufferEvent::SSL_ACCEPTING,
                    
EventBufferEvent::OPT_CLOSE_ON_FREE);
                
$this->connections[$id]['cnx']->setCallbacks([$this, "ev_read"], NULL, [$this, 'ev_error'], $id);
                
$this->connections[$id]['cnx']->enable(Event::READ | Event::WRITE);
                break;

            default:
                echo 
'unknown command: '.$line."\n";
                break;
        }
    }
}

new 
Handler();

Ver también