Commits

Ruslan Osmanov  committed 0f78f9d

Fix: redundant Z_ADDREF_P() calls in EventListener, EventBufferEvent constructors and factory methods

  • Participants
  • Parent commits d565410

Comments (0)

Files changed (5)

File classes/buffer_event.c

 
 	bev->self = zself;
 	bev->input = bev->output = NULL;
-	/* Ensure the object won't be destroyed in case if we are in a callback
-	 * XXX Get rid of this! */
-	Z_ADDREF_P(zself);
+	/* Don't ensure the object won't be destroyed in case if we are in a callback
+	 * User should keep variable somewhere if he/she wants to prevent auto-destruction
+	 * within a callback.
+	 * Z_ADDREF_P(zself);
+	 */
 }
 /* }}} */
 
 
 	bev->self = return_value;
 	/* Ensure the object won't be destroyed in case if we are in a callback */
-	Z_ADDREF_P(return_value);
+	/* Don't ensure the object won't be destroyed in case if we are in a callback
+	 * User should keep variable somewhere if he/she wants to prevent auto-destruction
+	 * within a callback.
+	 * Z_ADDREF_P(return_value);
+	 */
 }
 /* }}} */
 
 
 	bev->self = return_value;
 	/* Ensure the object won't be destroyed in case if we are in a callback */
-	Z_ADDREF_P(return_value);
+	/* Don't ensure the object won't be destroyed in case if we are in a callback
+	 * User should keep variable somewhere if he/she wants to prevent auto-destruction
+	 * within a callback.
+	 * Z_ADDREF_P(return_value);
+	 */
 }
 /* }}} */
 

File examples/listener.php

  * 3) start typing. The server should repeat the input.
  */
 
-function echo_read_cb($bev, $ctx) {
-	/* This callback is invoked when there is data to read on $bev. */
-	$input	= $bev->getInput();
-	$output = $bev->getOutput();
+class MyListener {
+	public $base,
+		$listener,
+		$bev,
+		$socket;
+
+	public function __construct($port) {
+		$this->base = new EventBase();
+		if (!$this->base) {
+			echo "Couldn't open event base";
+			exit(1);
+		}
+
+		// Variant #1
+		$this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
+		if (!socket_bind($this->socket, '0.0.0.0', $port)) {
+			echo "Unable to bind socket\n";
+			exit(1);
+		}
+		$this->listener = new EventListener($this->base,
+			array($this, "accept_conn_cb"), $this->base,
+			EventListener::OPT_CLOSE_ON_FREE | EventListener::OPT_REUSEABLE,
+			-1, $this->socket);
+
+/*		Variant #2
+ *		$this->listener = new EventListener($this->base,
+ *			array($this, "accept_conn_cb"), $this->base,
+ *			EventListener::OPT_CLOSE_ON_FREE | EventListener::OPT_REUSEABLE, -1,
+ *			"0.0.0.0:$port");
+ */
 
-	/* Copy all the data from the input buffer to the output buffer. */
-	$output->addBuffer($input);
-}
+		if (!$this->listener) {
+			echo "Couldn't create listener";
+			exit(1);
+		}
 
-function echo_event_cb($bev, $events, $ctx) {
-	if ($events & EventBufferEvent::ERROR)
-		echo "Error from bufferevent\n";
+		$this->listener->setErrorCallback(array($this, "accept_error_cb"));
+	}
 
-	if ($events & (EventBufferEvent::EOF | EventBufferEvent::ERROR)) {
-		$bev->free();
+	public function dispatch() {
+		$this->base->dispatch();
+	}
+
+	// This callback is invoked when there is data to read on $bev
+	public function echo_read_cb($bev, $ctx) {
+		// Copy all the data from the input buffer to the output buffer
+		
+		// Variant #1
+		$bev->output->addBuffer($bev->input);
+
+		/* Variant #2 */
+		/*
+		$input	= $bev->getInput();
+		$output = $bev->getOutput();
+		$output->addBuffer($input);
+		*/
 	}
-}
 
-function accept_conn_cb($listener, $fd, $address, $ctx) {
-	/* We got a new connection! Set up a bufferevent for it. */
-	$base = $ctx;
-	//$base = $listener->getBase();
+	public function echo_event_cb($bev, $events, $ctx) {
+		if ($events & EventBufferEvent::ERROR)
+			echo "Error from bufferevent\n";
 
-	$bev = new EventBufferEvent($base, $fd, EventBufferEvent::OPT_CLOSE_ON_FREE);
+		if ($events & (EventBufferEvent::EOF | EventBufferEvent::ERROR)) {
+			$bev->free();
+		}
+	}
 
-	$bev->setCallbacks("echo_read_cb", NULL, "echo_event_cb", NULL);
+	public function accept_conn_cb($listener, $fd, $address, $ctx) {
+		/* We got a new connection! Set up a bufferevent for it. */
+		//$base = $ctx;
+		//$base = $listener->getBase();
+		$base = $this->base;
 
-	$bev->enable(Event::READ | Event::WRITE);
+		$this->bev = new EventBufferEvent($base, $fd, EventBufferEvent::OPT_CLOSE_ON_FREE);
 
-	//$bev->ref();
-}
+		$this->bev->setCallbacks(array($this, "echo_read_cb"), NULL, array($this, "echo_event_cb"), NULL);
+
+		$this->bev->enable(Event::READ | Event::WRITE);
+	}
 
-function accept_error_cb($listener, $ctx) {
-	$base = $listener->getBase();
+	public function accept_error_cb($listener, $ctx) {
+		//$base = $listener->getBase();
+		$base = $this->base;
 
-	fprintf(STDERR, "Got an error %d (%s) on the listener. "
-		."Shutting down.\n",
-		EventUtil::getLastSocketErrno(),
-		EventUtil::getLastSocketError());
+		fprintf(STDERR, "Got an error %d (%s) on the listener. "
+			."Shutting down.\n",
+			EventUtil::getLastSocketErrno(),
+			EventUtil::getLastSocketError());
 
-	$base->exit(NULL);
+		$base->exit(NULL);
+	}
 }
 
 $port = 9808;
 	return 1;
 }
 
-$base = new EventBase();
-if (!$base) {
-	echo "Couldn't open event base";
-	exit(1);
-}
-
-/* Variant #1 */
-$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
-if (!socket_bind($socket, '0.0.0.0', $port)) {
-	echo "Unable to bind socket\n";
-	exit(1);
-}
-$listener = new EventListener($base, "accept_conn_cb", $base,
-	EventListener::OPT_CLOSE_ON_FREE | EventListener::OPT_REUSEABLE, -1, $socket);
-
-/* Variant #2 */
-/*
-$listener = new EventListener($base, "accept_conn_cb", $base,
-	EventListener::OPT_CLOSE_ON_FREE | EventListener::OPT_REUSEABLE, -1, "0.0.0.0:$port");
- */
-
-if (!$listener) {
-	echo "Couldn't create listener";
-	exit(1);
-}
-$listener->setErrorCallback("accept_error_cb");
-
-$base->dispatch();
+$l = new MyListener($port);
+$l->dispatch();

File examples/ssl-echo-server/server.php

  * $ socat - SSL:127.0.0.1:9998,verify=1,cafile=examples/ssl-echo-server/cert.pem
  */
 
-// This callback is invoked when there is data to read on $bev.
-function ssl_read_cb($bev, $ctx) {
-	$in = $bev->getInput();
-
-	printf("Received %zu bytes\n", $in->length);
-    printf("----- data ----\n");
-    printf("%ld:\t%s\n", (int) $in->length, $in->pullup(-1));
+class MySslEchoServer {
+	public $port,
+		$base,
+		$bev,
+		$listener,
+		$ctx;
+
+	function __construct ($port, $host = "127.0.0.1") {
+		$this->port = $port;
+		$this->ctx = $this->init_ssl();
+		if (!$this->ctx) {
+			exit("Failed creating SSL context\n");
+		}
 
-	$bev->writeBuffer($in);
-}
+		$this->base = new EventBase();
+		if (!$this->base) {
+			exit("Couldn't open event base\n");
+		}
 
-// This callback is invoked when some even occurs on the event listener,
-// e.g. connection closed, or an error occured
-function ssl_event_cb($bev, $events, $ctx) {
-	if ($events & EventBufferEvent::ERROR) {
-		// Fetch errors from the SSL error stack
-		while ($err = $bev->sslError()) {
-			fprintf(STDERR, "Bufferevent error %s.\n", $err);
+		$this->listener = new EventListener($this->base,
+			array($this, "ssl_accept_cb"), $this->ctx,
+			EventListener::OPT_CLOSE_ON_FREE | EventListener::OPT_REUSEABLE,
+			-1, "$host:$port");
+		if (!$this->listener) {
+			exit("Couldn't create listener\n");
 		}
-	}
 
-	if ($events & (EventBufferEvent::EOF | EventBufferEvent::ERROR)) {
-		$bev->free();
+		$this->listener->setErrorCallback(array($this, "accept_error_cb"));
+	}
+	function dispatch() {
+		$this->base->dispatch();
 	}
-}
 
-// This callback is invoked when a client accepts new connection
-function ssl_accept_cb($listener, $fd, $address, $ctx) {
-	// We got a new connection! Set up a bufferevent for it.
-	$base = $listener->getBase();
+	// This callback is invoked when there is data to read on $bev.
+	function ssl_read_cb($bev, $ctx) {
+		$in = $bev->input; //$bev->getInput();
 
-	$bev = EventBufferEvent::sslSocket($base, $fd, $ctx,
-		EventBufferEvent::SSL_ACCEPTING, EventBufferEvent::OPT_CLOSE_ON_FREE);
+		printf("Received %zu bytes\n", $in->length);
+    	printf("----- data ----\n");
+    	printf("%ld:\t%s\n", (int) $in->length, $in->pullup(-1));
 
-	if (!$bev) {
-		echo "Failed creating ssl buffer\n";
-		$base->exit(NULL);
-		exit(1);
+		$bev->writeBuffer($in);
 	}
 
-	$bev->enable(Event::READ);
-	$bev->setCallbacks("ssl_read_cb", NULL, "ssl_event_cb", NULL);
-}
+	// This callback is invoked when some even occurs on the event listener,
+	// e.g. connection closed, or an error occured
+	function ssl_event_cb($bev, $events, $ctx) {
+		if ($events & EventBufferEvent::ERROR) {
+			// Fetch errors from the SSL error stack
+			while ($err = $bev->sslError()) {
+				fprintf(STDERR, "Bufferevent error %s.\n", $err);
+			}
+		}
 
-// This callback is invoked when we failed to setup new connection for a client
-function accept_error_cb($listener, $ctx) {
-	$base = $listener->getBase();
+		if ($events & (EventBufferEvent::EOF | EventBufferEvent::ERROR)) {
+			$bev->free();
+		}
+	}
 
-	fprintf(STDERR, "Got an error %d (%s) on the listener. "
-		."Shutting down.\n",
-		EventUtil::getLastSocketErrno(),
-		EventUtil::getLastSocketError());
+	// This callback is invoked when a client accepts new connection
+	function ssl_accept_cb($listener, $fd, $address, $ctx) {
+		// We got a new connection! Set up a bufferevent for it.
+		$this->bev = EventBufferEvent::sslSocket($this->base, $fd, $this->ctx,
+			EventBufferEvent::SSL_ACCEPTING, EventBufferEvent::OPT_CLOSE_ON_FREE);
 
-	$base->exit(NULL);
-}
+		if (!$this->bev) {
+			echo "Failed creating ssl buffer\n";
+			$this->base->exit(NULL);
+			exit(1);
+		}
 
-// Initialize SSL structures, create an EventSslContext
-// Optionally create self-signed certificates
-function init_ssl($port) {
-	// We *must* have entropy. Otherwise there's no point to crypto.
-	if (!EventUtil::sslRandPoll()) {
-		exit("EventUtil::sslRandPoll failed\n");
+		$this->bev->enable(Event::READ);
+		$this->bev->setCallbacks(array($this, "ssl_read_cb"), NULL,
+			array($this, "ssl_event_cb"), NULL);
 	}
 
-	$local_cert = __DIR__."/cert.pem";
-	$local_pk   = __DIR__."/privkey.pem";
-
-	if (!file_exists($local_cert) || !file_exists($local_pk)) {
-		echo "Couldn't read $local_cert or $local_pk file.  To generate a key\n",
-			"and self-signed certificate, run:\n",
-			"  openssl genrsa -out $local_pk 2048\n",
-			"  openssl req -new -key $local_pk -out cert.req\n",
-			"  openssl x509 -req -days 365 -in cert.req -signkey $local_pk -out $local_cert\n";
+	// This callback is invoked when we failed to setup new connection for a client
+	function accept_error_cb($listener, $ctx) {
+		fprintf(STDERR, "Got an error %d (%s) on the listener. "
+			."Shutting down.\n",
+			EventUtil::getLastSocketErrno(),
+			EventUtil::getLastSocketError());
 
-		return FALSE;
+		$this->base->exit(NULL);
 	}
 
-	$ctx = new EventSslContext(EventSslContext::SSLv3_SERVER_METHOD, array (
- 		EventSslContext::OPT_LOCAL_CERT  => $local_cert,
- 		EventSslContext::OPT_LOCAL_PK    => $local_pk,
- 		//EventSslContext::OPT_PASSPHRASE  => "echo server",
- 		EventSslContext::OPT_VERIFY_PEER => true,
- 		EventSslContext::OPT_ALLOW_SELF_SIGNED => false,
-	));
+	// Initialize SSL structures, create an EventSslContext
+	// Optionally create self-signed certificates
+	function init_ssl() {
+		// We *must* have entropy. Otherwise there's no point to crypto.
+		if (!EventUtil::sslRandPoll()) {
+			exit("EventUtil::sslRandPoll failed\n");
+		}
+
+		$local_cert = __DIR__."/cert.pem";
+		$local_pk   = __DIR__."/privkey.pem";
 
-	return $ctx;
+		if (!file_exists($local_cert) || !file_exists($local_pk)) {
+			echo "Couldn't read $local_cert or $local_pk file.  To generate a key\n",
+				"and self-signed certificate, run:\n",
+				"  openssl genrsa -out $local_pk 2048\n",
+				"  openssl req -new -key $local_pk -out cert.req\n",
+				"  openssl x509 -req -days 365 -in cert.req -signkey $local_pk -out $local_cert\n";
+
+			return FALSE;
+		}
+
+		$ctx = new EventSslContext(EventSslContext::SSLv3_SERVER_METHOD, array (
+ 			EventSslContext::OPT_LOCAL_CERT  => $local_cert,
+ 			EventSslContext::OPT_LOCAL_PK    => $local_pk,
+ 			//EventSslContext::OPT_PASSPHRASE  => "echo server",
+ 			EventSslContext::OPT_VERIFY_PEER => true,
+ 			EventSslContext::OPT_ALLOW_SELF_SIGNED => false,
+		));
+
+		return $ctx;
+	}
 }
 
 // Allow to override the port
 	exit("Invalid port\n");
 }
 
-$host = "127.0.0.1";
-
-$ctx = init_ssl($port);
-if (!$ctx) {
-	exit("Failed creating SSL context\n");
-}
-
-$base = new EventBase();
-if (!$base) {
-	exit("Couldn't open event base\n");
-}
-
-$listener = new EventListener($base, "ssl_accept_cb", $ctx,
-	EventListener::OPT_CLOSE_ON_FREE | EventListener::OPT_REUSEABLE,
-	-1, "$host:$port");
-if (!$listener) {
-	exit("Couldn't create listener\n");
-}
-$listener->setErrorCallback("accept_error_cb");
 
-$base->dispatch();
+$l = new MySslEchoServer($port);
+$l->dispatch();
   <date>2013-02-22</date>
   <!--{{{ Current version -->
   <version>
-    <release>1.2.4</release>
+    <release>1.2.5</release>
     <api>1.2.1</api>
   </version>
   <stability>
   </stability>
   <license uri="http://www.php.net/license">PHP</license>
   <notes><![CDATA[
-  Fix: deleted redundant len argument of EventBuffer::readLine
-  Fix: EventBuffer::readLine returned non-dup'd string. Caused bugs with pointers.
+  Fix: redundant Z_ADDREF_P() calls in EventListener, EventBufferEvent constructors and factory methods
   ]]></notes>
   <!--}}}-->
   <!--{{{ Contents -->
   </extsrcrelease>
   <!--{{{ changelog-->
   <changelog>
+  <!--{{{ 1.2.5-alpha -->
+  <version>
+    <release>1.2.5</release>
+    <api>1.2.1</api>
+  </version>
+  <stability>
+    <release>alpha</release>
+    <api>alpha</api>
+  </stability>
+  <license uri="http://www.php.net/license">PHP</license>
+  <notes><![CDATA[
+  Fix: redundant Z_ADDREF_P() calls in EventListener, EventBufferEvent constructors and factory methods
+  ]]></notes>
+  <!--}}}-->
   <!--{{{ 1.2.4-alpha -->
   <version>
     <release>1.2.4</release>
 #ifndef PHP_EVENT_H
 #define PHP_EVENT_H
 
-#define PHP_EVENT_VERSION "1.2.4-alpha"
+#define PHP_EVENT_VERSION "1.2.5-alpha"
 
 
 extern zend_module_entry event_module_entry;