THRIFT-948: SSL socket support for PHP

Client: php
Patch: Mansi Nahar

Adds TSSLServerSocket and TSSLSocket to PHP
This commit is contained in:
jfarrell 2016-09-20 13:30:16 -04:00
parent 54f49f8635
commit 311c98455a
4 changed files with 237 additions and 11 deletions

View File

@ -0,0 +1,94 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
namespace Thrift\Server;
use Thrift\Transport\TSSLSocket;
/**
* Socket implementation of a server agent.
*
* @package thrift.transport
*/
class TSSLServerSocket extends TServerSocket
{
/**
* Remote port
*
* @var resource
*/
protected $context_ = null;
/**
* ServerSocket constructor
*
* @param string $host Host to listen on
* @param int $port Port to listen on
* @param resource $context Stream context
* @return void
*/
public function __construct($host = 'localhost', $port = 9090, $context = null)
{
$ssl_host = $this->getSSLHost($host);
parent::__construct($ssl_host, $port);
$this->context_ = $context;
}
public function getSSLHost($host)
{
$transport_protocol_loc = strpos($host, "://");
if ($transport_protocol_loc === false) {
$host = 'ssl://'.$host;
}
return $host;
}
/**
* Opens a new socket server handle
*
* @return void
*/
public function listen()
{
$this->listener_ = @stream_socket_server(
$this->host_ . ':' . $this->port_,
$errno,
$errstr,
STREAM_SERVER_BIND|STREAM_SERVER_LISTEN,
$this->context_);
}
/**
* Implementation of accept. If not client is accepted in the given time
*
* @return TSocket
*/
protected function acceptImpl()
{
$handle = @stream_socket_accept($this->listener_, $this->acceptTimeout_ / 1000.0);
if(!$handle) return null;
$socket = new TSSLSocket();
$socket->setHandle($handle);
return $socket;
}
}

View File

@ -1,4 +1,24 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.transport
*/
namespace Thrift\Server;
@ -16,28 +36,28 @@ class TServerSocket extends TServerTransport
*
* @var resource
*/
private $listener_;
protected $listener_;
/**
* Port for the listener to listen on
*
* @var int
*/
private $port_;
protected $port_;
/**
* Timeout when listening for a new client
*
* @var int
*/
private $acceptTimeout_ = 30000;
protected $acceptTimeout_ = 30000;
/**
* Host to listen on
*
* @var string
*/
private $host_;
protected $host_;
/**
* ServerSocket constructor

View File

@ -0,0 +1,112 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.transport
*/
namespace Thrift\Transport;
use Thrift\Exception\TException;
use Thrift\Exception\TTransportException;
use Thrift\Factory\TStringFuncFactory;
/**
* Sockets implementation of the TTransport interface.
*
* @package thrift.transport
*/
class TSSLSocket extends TSocket
{
/**
* Remote port
*
* @var resource
*/
protected $context_ = null;
/**
* Socket constructor
*
* @param string $host Remote hostname
* @param int $port Remote port
* @param resource $context Stream context
* @param bool $persist Whether to use a persistent socket
* @param string $debugHandler Function to call for error logging
*/
public function __construct($host='localhost',
$port=9090,
$context=null,
$debugHandler=null) {
$this->host_ = $this->getSSLHost($host);
$this->port_ = $port;
$this->context_ = $context;
$this->debugHandler_ = $debugHandler ? $debugHandler : 'error_log';
}
/**
* Creates a host name with SSL transport protocol
* if no transport protocol already specified in
* the host name.
*
* @param string $host Host to listen on
* @return string $host Host name with transport protocol
*/
private function getSSLHost($host)
{
$transport_protocol_loc = strpos($host, "://");
if ($transport_protocol_loc === false) {
$host = 'ssl://'.$host;
}
return $host;
}
/**
* Connects the socket.
*/
public function open()
{
if ($this->isOpen()) {
throw new TTransportException('Socket already connected', TTransportException::ALREADY_OPEN);
}
if (empty($this->host_)) {
throw new TTransportException('Cannot open null host', TTransportException::NOT_OPEN);
}
if ($this->port_ <= 0) {
throw new TTransportException('Cannot open without port', TTransportException::NOT_OPEN);
}
$this->handle_ = @stream_socket_client($this->host_.':'.$this->port_,
$errno,
$errstr,
$this->sendTimeoutSec_ + ($this->sendTimeoutUsec_ / 1000000),
STREAM_CLIENT_CONNECT,
$this->context_);
// Connect failed?
if ($this->handle_ === FALSE) {
$error = 'TSocket: Could not connect to '.$this->host_.':'.$this->port_.' ('.$errstr.' ['.$errno.'])';
if ($this->debug_) {
call_user_func($this->debugHandler_, $error);
}
throw new TException($error);
}
}
}

View File

@ -38,7 +38,7 @@ class TSocket extends TTransport
*
* @var resource
*/
private $handle_ = null;
protected $handle_ = null;
/**
* Remote hostname
@ -61,7 +61,7 @@ class TSocket extends TTransport
*
* @var int
*/
private $sendTimeoutSec_ = 0;
protected $sendTimeoutSec_ = 0;
/**
* Send timeout in microseconds.
@ -70,7 +70,7 @@ class TSocket extends TTransport
*
* @var int
*/
private $sendTimeoutUsec_ = 100000;
protected $sendTimeoutUsec_ = 100000;
/**
* Recv timeout in seconds
@ -79,7 +79,7 @@ class TSocket extends TTransport
*
* @var int
*/
private $recvTimeoutSec_ = 0;
protected $recvTimeoutSec_ = 0;
/**
* Recv timeout in microseconds
@ -88,7 +88,7 @@ class TSocket extends TTransport
*
* @var int
*/
private $recvTimeoutUsec_ = 750000;
protected $recvTimeoutUsec_ = 750000;
/**
* Persistent socket or plain?
@ -270,7 +270,7 @@ class TSocket extends TTransport
$readable = @stream_select($read, $null, $null, $this->recvTimeoutSec_, $this->recvTimeoutUsec_);
if ($readable > 0) {
$data = @stream_socket_recvfrom($this->handle_, $len);
$data = fread($this->handle_, $len);
if ($data === false) {
throw new TTransportException('TSocket: Could not read '.$len.' bytes from '.
$this->host_.':'.$this->port_);
@ -304,7 +304,7 @@ class TSocket extends TTransport
$writable = @stream_select($null, $write, $null, $this->sendTimeoutSec_, $this->sendTimeoutUsec_);
if ($writable > 0) {
// write buffer to stream
$written = @stream_socket_sendto($this->handle_, $buf);
$written = fwrite($this->handle_, $buf);
if ($written === -1 || $written === false) {
throw new TTransportException('TSocket: Could not write '.TStringFuncFactory::create()->strlen($buf).' bytes '.
$this->host_.':'.$this->port_);