Overview

Namespaces

  • Evenement
  • None
  • PHP
  • Psr
    • Http
      • Message
  • Ratchet
    • Http
    • RFC6455
      • Handshake
      • Messaging
    • Server
    • Session
      • Serialize
      • Storage
        • Proxy
    • Wamp
    • WebSocket
  • React
    • EventLoop
      • Tick
      • Timer
    • Socket
    • Stream
  • Symfony
    • Component
      • HttpFoundation
        • Session
          • Attribute
          • Flash
          • Storage
            • Handler
            • Proxy
      • Routing
        • Annotation
        • Exception
        • Generator
          • Dumper
        • Loader
          • DependencyInjection
        • Matcher
          • Dumper
        • Tests
          • Annotation
          • Fixtures
            • AnnotatedClasses
            • OtherAnnotatedClasses
          • Generator
            • Dumper
          • Loader
          • Matcher
            • Dumper

Classes

  • Connector
  • DnsConnector
  • LimitingServer
  • SecureConnector
  • SecureServer
  • Server
  • TcpConnector
  • TimeoutConnector
  • UnixConnector

Interfaces

  • ConnectionInterface
  • ConnectorInterface
  • ServerInterface
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php
  2: 
  3: namespace React\Socket;
  4: 
  5: use Evenement\EventEmitter;
  6: use React\EventLoop\LoopInterface;
  7: use React\Socket\Server;
  8: use React\Socket\ConnectionInterface;
  9: use React\Stream\Stream;
 10: 
 11: /**
 12:  * The `SecureServer` class implements the `ServerInterface` and is responsible
 13:  * for providing a secure TLS (formerly known as SSL) server.
 14:  *
 15:  * It does so by wrapping a `Server` instance which waits for plaintext
 16:  * TCP/IP connections and then performs a TLS handshake for each connection.
 17:  *
 18:  * ```php
 19:  * $server = new Server(8000, $loop);
 20:  * $server = new SecureServer($server, $loop, array(
 21:  *     // tls context options here…
 22:  * ));
 23:  * ```
 24:  *
 25:  * Whenever a client completes the TLS handshake, it will emit a `connection` event
 26:  * with a connection instance implementing [`ConnectionInterface`](#connectioninterface):
 27:  *
 28:  * ```php
 29:  * $server->on('connection', function (ConnectionInterface $connection) {
 30:  *     echo 'Secure connection from' . $connection->getRemoteAddress() . PHP_EOL;
 31:  *
 32:  *     $connection->write('hello there!' . PHP_EOL);
 33:  *     …
 34:  * });
 35:  * ```
 36:  *
 37:  * Whenever a client fails to perform a successful TLS handshake, it will emit an
 38:  * `error` event and then close the underlying TCP/IP connection:
 39:  *
 40:  * ```php
 41:  * $server->on('error', function (Exception $e) {
 42:  *     echo 'Error' . $e->getMessage() . PHP_EOL;
 43:  * });
 44:  * ```
 45:  *
 46:  * See also the `ServerInterface` for more details.
 47:  *
 48:  * Note that the `SecureServer` class is a concrete implementation for TLS sockets.
 49:  * If you want to typehint in your higher-level protocol implementation, you SHOULD
 50:  * use the generic `ServerInterface` instead.
 51:  *
 52:  * @see ServerInterface
 53:  * @see ConnectionInterface
 54:  */
 55: final class SecureServer extends EventEmitter implements ServerInterface
 56: {
 57:     private $tcp;
 58:     private $encryption;
 59:     private $context;
 60: 
 61:     /**
 62:      * Creates a secure TLS server and starts waiting for incoming connections
 63:      *
 64:      * It does so by wrapping a `Server` instance which waits for plaintext
 65:      * TCP/IP connections and then performs a TLS handshake for each connection.
 66:      * It thus requires valid [TLS context options],
 67:      * which in its most basic form may look something like this if you're using a
 68:      * PEM encoded certificate file:
 69:      *
 70:      * ```php
 71:      * $server = new Server(8000, $loop);
 72:      * $server = new SecureServer($server, $loop, array(
 73:      *     'local_cert' => 'server.pem'
 74:      * ));
 75:      * ```
 76:      *
 77:      * Note that the certificate file will not be loaded on instantiation but when an
 78:      * incoming connection initializes its TLS context.
 79:      * This implies that any invalid certificate file paths or contents will only cause
 80:      * an `error` event at a later time.
 81:      *
 82:      * If your private key is encrypted with a passphrase, you have to specify it
 83:      * like this:
 84:      *
 85:      * ```php
 86:      * $server = new Server(8000, $loop);
 87:      * $server = new SecureServer($server, $loop, array(
 88:      *     'local_cert' => 'server.pem',
 89:      *     'passphrase' => 'secret'
 90:      * ));
 91:      * ```
 92:      *
 93:      * Note that available [TLS context options],
 94:      * their defaults and effects of changing these may vary depending on your system
 95:      * and/or PHP version.
 96:      * Passing unknown context options has no effect.
 97:      *
 98:      * Advanced usage: Despite allowing any `ServerInterface` as first parameter,
 99:      * you SHOULD pass a `Server` instance as first parameter, unless you
100:      * know what you're doing.
101:      * Internally, the `SecureServer` has to set the required TLS context options on
102:      * the underlying stream resources.
103:      * These resources are not exposed through any of the interfaces defined in this
104:      * package, but only through the `React\Stream\Stream` class.
105:      * The `Server` class is guaranteed to emit connections that implement
106:      * the `ConnectionInterface` and also extend the `Stream` class in order to
107:      * expose these underlying resources.
108:      * If you use a custom `ServerInterface` and its `connection` event does not
109:      * meet this requirement, the `SecureServer` will emit an `error` event and
110:      * then close the underlying connection.
111:      *
112:      * @param ServerInterface|Server $tcp
113:      * @param LoopInterface $loop
114:      * @param array $context
115:      * @throws \BadMethodCallException for legacy HHVM < 3.8 due to lack of support
116:      * @see Server
117:      * @link http://php.net/manual/en/context.ssl.php for TLS context options
118:      */
119:     public function __construct(ServerInterface $tcp, LoopInterface $loop, array $context)
120:     {
121:         if (!function_exists('stream_socket_enable_crypto')) {
122:             throw new \BadMethodCallException('Encryption not supported on your platform (HHVM < 3.8?)'); // @codeCoverageIgnore
123:         }
124: 
125:         // default to empty passphrase to surpress blocking passphrase prompt
126:         $context += array(
127:             'passphrase' => ''
128:         );
129: 
130:         $this->tcp = $tcp;
131:         $this->encryption = new StreamEncryption($loop);
132:         $this->context = $context;
133: 
134:         $that = $this;
135:         $this->tcp->on('connection', function ($connection) use ($that) {
136:             $that->handleConnection($connection);
137:         });
138:         $this->tcp->on('error', function ($error) use ($that) {
139:             $that->emit('error', array($error));
140:         });
141:     }
142: 
143:     public function getAddress()
144:     {
145:         return $this->tcp->getAddress();
146:     }
147: 
148:     public function pause()
149:     {
150:         $this->tcp->pause();
151:     }
152: 
153:     public function resume()
154:     {
155:         $this->tcp->resume();
156:     }
157: 
158:     public function close()
159:     {
160:         return $this->tcp->close();
161:     }
162: 
163:     /** @internal */
164:     public function handleConnection(ConnectionInterface $connection)
165:     {
166:         if (!$connection instanceof Stream) {
167:             $this->emit('error', array(new \UnexpectedValueException('Connection event MUST emit an instance extending Stream in order to access underlying stream resource')));
168:             $connection->end();
169:             return;
170:         }
171: 
172:         foreach ($this->context as $name => $value) {
173:             stream_context_set_option($connection->stream, 'ssl', $name, $value);
174:         }
175: 
176:         $that = $this;
177: 
178:         $this->encryption->enable($connection)->then(
179:             function ($conn) use ($that) {
180:                 $that->emit('connection', array($conn));
181:             },
182:             function ($error) use ($that, $connection) {
183:                 $that->emit('error', array($error));
184:                 $connection->end();
185:             }
186:         );
187:     }
188: }
189: 
Ratchet API documentation generated by ApiGen 2.8.0