Ruslan Osmanov avatar Ruslan Osmanov committed a70bed0

EventBufferEvent::createPair() made static
Add: tests for EventBase argument passed by ref

Comments (0)

Files changed (16)

classes/buffer_event.c

 /* {{{ proto EventBufferEvent EventBufferEvent::__construct(EventBase base[, mixed socket = NULL[, int options = 0[, callable readcb[, callable writecb[, callable eventcb[, mixed arg = NULL]]]]]]);
  *
  * Create a socket-based buffer event.
- * options is one of EVENT_BEV_OPT_* constants, or 0.
+ * options is one of EventBufferEvent::OPT_* constants, or 0.
  * Passing NULL to socket parameter means that the socket stream should be created later,
  * e.g. by means of bufferevent_socket_connect().
  *

examples/sslfilter.php

+<?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  => './ssl-echo-server/cert.pem',
+            EventSslContext::OPT_LOCAL_PK    => './ssl-echo-server/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();
    Forced passing EventBase argument by reference. A method accepting EventBase
    will generate fatal error in case if corresponding argument is not passed by
    reference.
+
+   EventBufferEvent::createPair method made static.
   ]]></notes>
   <!--}}}-->
   <!--{{{ Contents -->
         <file role="doc" name="listener.php"/>
         <file role="doc" name="misc.php"/>
         <file role="doc" name="signal.php"/>
+        <file role="doc" name="sslfilter.php"/>
         <file role="doc" name="timer.php"/>
         <file role="doc" name="uppercase_proxy.php"/>
       </dir>
         <file role="test" name="10-event-data-dtor.phpt"/>
         <file role="test" name="11-gc-cycles.phpt"/>
         <file role="test" name="12-serialization.phpt"/>
+        <file role="test" name="13-bevent-pair.phpt"/>
+        <file role="test" name="14-httpconn-error.phpt"/>
+        <file role="test" name="15-dnsbase-error.phpt"/>
+        <file role="test" name="16-http-error.phpt"/>
+        <file role="test" name="17-event-settimer-error.phpt"/>
+        <file role="test" name="18-timer-error.phpt"/>
+        <file role="test" name="19-event-signal-error.phpt"/>
+        <file role="test" name="20-bevent-error.phpt"/>
+        <file role="test" name="21-bevent-sslfilter-error.phpt"/>
+        <file role="test" name="21-bevent-sslsocket-error.phpt"/>
       </dir>
     </dir>
   </contents>
    Forced passing EventBase argument by reference. A method accepting EventBase
    will generate fatal error in case if corresponding argument is not passed by
    reference.
+
+   EventBufferEvent::createPair method made static.
   ]]></notes>
     </release>
     <!--}}}-->
 	PHP_ME(EventBufferEvent, writeBuffer,       arginfo_bufferevent_write_buffer,  ZEND_ACC_PUBLIC)
 	PHP_ME(EventBufferEvent, read,              arginfo_bufferevent_read,          ZEND_ACC_PUBLIC)
 	PHP_ME(EventBufferEvent, readBuffer,        arginfo_bufferevent_write_buffer,  ZEND_ACC_PUBLIC)
-	PHP_ME(EventBufferEvent, createPair,        arginfo_bufferevent_pair_new,      ZEND_ACC_PUBLIC)
+	PHP_ME(EventBufferEvent, createPair,        arginfo_bufferevent_pair_new,      ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
 	PHP_ME(EventBufferEvent, setPriority,       arginfo_bufferevent_priority_set,  ZEND_ACC_PUBLIC)
 	PHP_ME(EventBufferEvent, setTimeouts,       arginfo_bufferevent_set_timeouts,  ZEND_ACC_PUBLIC)
 #ifdef HAVE_EVENT_OPENSSL_LIB

tests/07-listener-error-win32.phpt

 --TEST--
-Check for EventListener error behaviour 
+Check for EventListener error behaviour
 --SKIPIF--
 <?php
 if (!class_exists("EventListener")) die("skip Event extra functions are disabled");
 	var_dump(is_null($listener) != $expect);
 }
 
+$l = new EventListener(new EventBase(), function() {}, NULL, EventUtil::AF_UNIX, 0, 'unix:/tmp/1.sock');
+
 ?>
 --EXPECT--
 bool(true)
+
+Fatal error: EventListener::__construct(): EventBase must be passed by reference in %s on line %d

tests/07-listener-error.phpt

 --TEST--
-Check for EventListener error behaviour 
+Check for EventListener error behaviour
 --SKIPIF--
 <?php
 if (!class_exists("EventListener")) die("skip Event extra functions are disabled");
 	var_dump(is_null($listener) != $expect);
 }
 
+$l = new EventListener(new EventBase(), function() {}, NULL, EventUtil::AF_UNIX, 0, 'unix:/tmp/1.sock');
 ?>
---EXPECT--
+--EXPECTF--
 bool(true)
 bool(true)
 bool(true)
 bool(true)
+
+Fatal error: EventListener::__construct(): EventBase must be passed by reference in %s on line %d

tests/13-bevent-pair.phpt

+--TEST--
+Check for EventBufferEvent::createPair()
+--FILE--
+<?php
+$base = new EventBase();
+
+$pair = EventBufferEvent::createPair($base);
+
+$pair[0]->enable(Event::WRITE);
+$pair[1]->enable(Event::READ);
+$pair[0]->write("xyz");
+echo $pair[1]->read(10) == "xyz" ? "ok" : 'failed', PHP_EOL;
+$base->loop();
+
+$pair[0]->disable(Event::WRITE);
+$pair[0]->write("xyz");
+echo $pair[1]->read(10) == "" ? "ok" : 'failed', PHP_EOL;
+$base->loop();
+
+EventBufferEvent::createPair(new EventBase());
+?>
+--EXPECTF--
+ok
+ok
+
+Fatal error: EventBufferEvent::createPair(): EventBase must be passed by reference in %s on line %d

tests/14-httpconn-error.phpt

+--TEST--
+Check for EventHttpConnection::__construct() error behavior
+--FILE--
+<?php
+$e = new EventHttpConnection(new EventBase(), NULL, '10.10.0.1', 9899);
+?>
+--EXPECTF--
+
+Fatal error: EventHttpConnection::__construct(): EventBase must be passed by reference in %s on line %d

tests/15-dnsbase-error.phpt

+--TEST--
+Check for EventDnsBase::__construct() error behavior
+--FILE--
+<?php
+$e = new EventDnsBase(new EventBase(), TRUE);
+?>
+--EXPECTF--
+
+Fatal error: EventDnsBase::__construct(): EventBase must be passed by reference in %s on line %d

tests/16-http-error.phpt

+--TEST--
+Check for EventHttp::__construct() error behavior
+--FILE--
+<?php
+$e = new EventHttp(new EventBase());
+?>
+--EXPECTF--
+
+Fatal error: EventHttp::__construct(): EventBase must be passed by reference in %s on line %d

tests/17-event-settimer-error.phpt

+--TEST--
+Check for Event::set() error behavior
+--FILE--
+<?php
+$b = new EventBase();
+$e = new Event($b, 0, Event::READ, function() {});
+$e->set(new EventBase(), 1);
+?>
+--EXPECTF--
+
+Fatal error: Event::set(): EventBase must be passed by reference in %s on line %d

tests/18-timer-error.phpt

+--TEST--
+Check for Event::timer() error behavior
+--FILE--
+<?php
+$e = Event::timer(new EventBase(), function() {});
+?>
+--EXPECTF--
+
+Fatal error: Event::timer(): EventBase must be passed by reference in %s on line %d

tests/19-event-signal-error.phpt

+--TEST--
+Check for Event::signal() error behavior
+--SKIPIF--
+<?php
+if (!extension_loaded('pcntl')) die('SKIP pcntl extension required');
+?>
+--FILE--
+<?php
+$e = Event::signal(new EventBase(), SIGTERM, function() {});
+?>
+--EXPECTF--
+
+Fatal error: Event::signal(): EventBase must be passed by reference in %s on line %d

tests/20-bevent-error.phpt

+--TEST--
+Check for EventBufferEvent::__construct() error behavior
+--FILE--
+<?php
+$b = new EventBufferEvent(new EventBase());
+?>
+--EXPECTF--
+
+Fatal error: EventBufferEvent::__construct(): EventBase must be passed by reference in %s on line %d

tests/21-bevent-sslfilter-error.phpt

+--TEST--
+Check for EventBufferEvent::sslFilter() error behavior
+--FILE--
+<?php
+$base = new EventBase();
+$b = new EventBufferEvent($base);
+$ctx = new EventSslContext(EventSslContext::SSLv3_SERVER_METHOD, []);
+EventBufferEvent::sslFilter(new EventBase(), $b, $ctx, EventBufferEvent::SSL_ACCEPTING);
+?>
+--EXPECTF--
+
+Fatal error: EventBufferEvent::sslFilter(): EventBase must be passed by reference in %s on line %d

tests/21-bevent-sslsocket-error.phpt

+--TEST--
+Check for EventBufferEvent::sslSocket() error behavior
+--FILE--
+<?php
+$ctx = new EventSslContext(EventSslContext::SSLv3_SERVER_METHOD, []);
+EventBufferEvent::sslSocket(new EventBase(), NULL, $ctx, EventBufferEvent::SSL_ACCEPTING);
+?>
+--EXPECTF--
+
+Fatal error: EventBufferEvent::sslSocket(): EventBase must be passed by reference in %s on line %d
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.