CakePHP
  • Documentation
    • Book
    • API
    • Videos
    • Logos & Trademarks
  • Business Solutions
  • Swag
  • Road Trip
  • Team
  • Community
    • Community
    • Team
    • Issues (Github)
    • YouTube Channel
    • Get Involved
    • Bakery
    • Featured Resources
    • Newsletter
    • Certification
    • My CakePHP
    • CakeFest
    • Facebook
    • Twitter
    • Help & Support
    • Forum
    • Stack Overflow
    • IRC
    • Slack
    • Paid Support
CakePHP

C CakePHP 3.8 Red Velvet API

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 3.8
      • 3.8
      • 3.7
      • 3.6
      • 3.5
      • 3.4
      • 3.3
      • 3.2
      • 3.1
      • 3.0
      • 2.10
      • 2.9
      • 2.8
      • 2.7
      • 2.6
      • 2.5
      • 2.4
      • 2.3
      • 2.2
      • 2.1
      • 2.0
      • 1.3
      • 1.2

Namespaces

  • Cake
    • Auth
      • Storage
    • Cache
      • Engine
    • Collection
      • Iterator
    • Command
    • Console
      • Exception
    • Controller
      • Component
      • Exception
    • Core
      • Configure
        • Engine
      • Exception
      • Retry
    • Database
      • Driver
      • Exception
      • Expression
      • Schema
      • Statement
      • Type
    • Datasource
      • Exception
    • Error
      • Middleware
    • Event
      • Decorator
    • Filesystem
    • Form
    • Http
      • Client
        • Adapter
        • Auth
      • Cookie
      • Exception
      • Middleware
      • Session
    • I18n
      • Formatter
      • Middleware
      • Parser
    • Log
      • Engine
    • Mailer
      • Exception
      • Transport
    • Network
      • Exception
    • ORM
      • Association
      • Behavior
        • Translate
      • Exception
      • Locator
      • Rule
    • Routing
      • Exception
      • Filter
      • Middleware
      • Route
    • Shell
      • Helper
      • Task
    • TestSuite
      • Fixture
      • Stub
    • Utility
      • Exception
    • Validation
    • View
      • Exception
      • Form
      • Helper
      • Widget
  • None

Classes

  • Socket
  1: <?php
  2: /**
  3:  * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  4:  * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  5:  *
  6:  * Licensed under The MIT License
  7:  * For full copyright and license information, please see the LICENSE.txt
  8:  * Redistributions of files must retain the above copyright notice.
  9:  *
 10:  * @copyright     Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
 11:  * @link          https://cakephp.org CakePHP(tm) Project
 12:  * @since         1.2.0
 13:  * @license       https://opensource.org/licenses/mit-license.php MIT License
 14:  */
 15: namespace Cake\Network;
 16: 
 17: use Cake\Core\Exception\Exception as CakeException;
 18: use Cake\Core\InstanceConfigTrait;
 19: use Cake\Network\Exception\SocketException;
 20: use Cake\Validation\Validation;
 21: use Exception;
 22: use InvalidArgumentException;
 23: 
 24: /**
 25:  * CakePHP network socket connection class.
 26:  *
 27:  * Core base class for network communication.
 28:  */
 29: class Socket
 30: {
 31:     use InstanceConfigTrait;
 32: 
 33:     /**
 34:      * Object description
 35:      *
 36:      * @var string
 37:      */
 38:     public $description = 'Remote DataSource Network Socket Interface';
 39: 
 40:     /**
 41:      * Default configuration settings for the socket connection
 42:      *
 43:      * @var array
 44:      */
 45:     protected $_defaultConfig = [
 46:         'persistent' => false,
 47:         'host' => 'localhost',
 48:         'protocol' => 'tcp',
 49:         'port' => 80,
 50:         'timeout' => 30
 51:     ];
 52: 
 53:     /**
 54:      * Reference to socket connection resource
 55:      *
 56:      * @var resource|null
 57:      */
 58:     public $connection;
 59: 
 60:     /**
 61:      * This boolean contains the current state of the Socket class
 62:      *
 63:      * @var bool
 64:      */
 65:     public $connected = false;
 66: 
 67:     /**
 68:      * This variable contains an array with the last error number (num) and string (str)
 69:      *
 70:      * @var array
 71:      */
 72:     public $lastError = [];
 73: 
 74:     /**
 75:      * True if the socket stream is encrypted after a Cake\Network\Socket::enableCrypto() call
 76:      *
 77:      * @var bool
 78:      */
 79:     public $encrypted = false;
 80: 
 81:     /**
 82:      * Contains all the encryption methods available
 83:      *
 84:      * SSLv2 and SSLv3 are deprecated, and should not be used as they
 85:      * have several published vulnerablilities.
 86:      *
 87:      * @var array
 88:      */
 89:     protected $_encryptMethods = [
 90:         // @codingStandardsIgnoreStart
 91:         // @deprecated Will be removed in 4.0.0
 92:         'sslv2_client' => STREAM_CRYPTO_METHOD_SSLv2_CLIENT,
 93:         // @deprecated Will be removed in 4.0.0
 94:         'sslv3_client' => STREAM_CRYPTO_METHOD_SSLv3_CLIENT,
 95:         'sslv23_client' => STREAM_CRYPTO_METHOD_SSLv23_CLIENT,
 96:         'tls_client' => STREAM_CRYPTO_METHOD_TLS_CLIENT,
 97:         'tlsv10_client' => STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT,
 98:         'tlsv11_client' => STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT,
 99:         'tlsv12_client' => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT,
100:         // @deprecated Will be removed in 4.0.0
101:         'sslv2_server' => STREAM_CRYPTO_METHOD_SSLv2_SERVER,
102:         // @deprecated Will be removed in 4.0.0
103:         'sslv3_server' => STREAM_CRYPTO_METHOD_SSLv3_SERVER,
104:         'sslv23_server' => STREAM_CRYPTO_METHOD_SSLv23_SERVER,
105:         'tls_server' => STREAM_CRYPTO_METHOD_TLS_SERVER,
106:         'tlsv10_server' => STREAM_CRYPTO_METHOD_TLSv1_0_SERVER,
107:         'tlsv11_server' => STREAM_CRYPTO_METHOD_TLSv1_1_SERVER,
108:         'tlsv12_server' => STREAM_CRYPTO_METHOD_TLSv1_2_SERVER
109:         // @codingStandardsIgnoreEnd
110:     ];
111: 
112:     /**
113:      * Used to capture connection warnings which can happen when there are
114:      * SSL errors for example.
115:      *
116:      * @var array
117:      */
118:     protected $_connectionErrors = [];
119: 
120:     /**
121:      * Constructor.
122:      *
123:      * @param array $config Socket configuration, which will be merged with the base configuration
124:      * @see \Cake\Network\Socket::$_baseConfig
125:      */
126:     public function __construct(array $config = [])
127:     {
128:         $this->setConfig($config);
129:     }
130: 
131:     /**
132:      * Connect the socket to the given host and port.
133:      *
134:      * @return bool Success
135:      * @throws \Cake\Network\Exception\SocketException
136:      */
137:     public function connect()
138:     {
139:         if ($this->connection) {
140:             $this->disconnect();
141:         }
142: 
143:         $hasProtocol = strpos($this->_config['host'], '://') !== false;
144:         if ($hasProtocol) {
145:             list($this->_config['protocol'], $this->_config['host']) = explode('://', $this->_config['host']);
146:         }
147:         $scheme = null;
148:         if (!empty($this->_config['protocol'])) {
149:             $scheme = $this->_config['protocol'] . '://';
150:         }
151: 
152:         $this->_setSslContext($this->_config['host']);
153:         if (!empty($this->_config['context'])) {
154:             $context = stream_context_create($this->_config['context']);
155:         } else {
156:             $context = stream_context_create();
157:         }
158: 
159:         $connectAs = STREAM_CLIENT_CONNECT;
160:         if ($this->_config['persistent']) {
161:             $connectAs |= STREAM_CLIENT_PERSISTENT;
162:         }
163: 
164:         set_error_handler([$this, '_connectionErrorHandler']);
165:         $remoteSocketTarget = $scheme . $this->_config['host'];
166:         $port = (int)$this->_config['port'];
167:         if ($port > 0) {
168:             $remoteSocketTarget .= ':' . $port;
169:         }
170:         $this->connection = stream_socket_client(
171:             $remoteSocketTarget,
172:             $errNum,
173:             $errStr,
174:             $this->_config['timeout'],
175:             $connectAs,
176:             $context
177:         );
178:         restore_error_handler();
179: 
180:         if (!empty($errNum) || !empty($errStr)) {
181:             $this->setLastError($errNum, $errStr);
182:             throw new SocketException($errStr, $errNum);
183:         }
184: 
185:         if (!$this->connection && $this->_connectionErrors) {
186:             $message = implode("\n", $this->_connectionErrors);
187:             throw new SocketException($message, E_WARNING);
188:         }
189: 
190:         $this->connected = is_resource($this->connection);
191:         if ($this->connected) {
192:             stream_set_timeout($this->connection, $this->_config['timeout']);
193:         }
194: 
195:         return $this->connected;
196:     }
197: 
198:     /**
199:      * Configure the SSL context options.
200:      *
201:      * @param string $host The host name being connected to.
202:      * @return void
203:      */
204:     protected function _setSslContext($host)
205:     {
206:         foreach ($this->_config as $key => $value) {
207:             if (substr($key, 0, 4) !== 'ssl_') {
208:                 continue;
209:             }
210:             $contextKey = substr($key, 4);
211:             if (empty($this->_config['context']['ssl'][$contextKey])) {
212:                 $this->_config['context']['ssl'][$contextKey] = $value;
213:             }
214:             unset($this->_config[$key]);
215:         }
216:         if (!isset($this->_config['context']['ssl']['SNI_enabled'])) {
217:             $this->_config['context']['ssl']['SNI_enabled'] = true;
218:         }
219:         if (empty($this->_config['context']['ssl']['peer_name'])) {
220:             $this->_config['context']['ssl']['peer_name'] = $host;
221:         }
222:         if (empty($this->_config['context']['ssl']['cafile'])) {
223:             $dir = dirname(dirname(__DIR__));
224:             $this->_config['context']['ssl']['cafile'] = $dir . DIRECTORY_SEPARATOR .
225:                 'config' . DIRECTORY_SEPARATOR . 'cacert.pem';
226:         }
227:         if (!empty($this->_config['context']['ssl']['verify_host'])) {
228:             $this->_config['context']['ssl']['CN_match'] = $host;
229:         }
230:         unset($this->_config['context']['ssl']['verify_host']);
231:     }
232: 
233:     /**
234:      * socket_stream_client() does not populate errNum, or $errStr when there are
235:      * connection errors, as in the case of SSL verification failure.
236:      *
237:      * Instead we need to handle those errors manually.
238:      *
239:      * @param int $code Code number.
240:      * @param string $message Message.
241:      * @return void
242:      */
243:     protected function _connectionErrorHandler($code, $message)
244:     {
245:         $this->_connectionErrors[] = $message;
246:     }
247: 
248:     /**
249:      * Get the connection context.
250:      *
251:      * @return array|null Null when there is no connection, an array when there is.
252:      */
253:     public function context()
254:     {
255:         if (!$this->connection) {
256:             return null;
257:         }
258: 
259:         return stream_context_get_options($this->connection);
260:     }
261: 
262:     /**
263:      * Get the host name of the current connection.
264:      *
265:      * @return string Host name
266:      */
267:     public function host()
268:     {
269:         if (Validation::ip($this->_config['host'])) {
270:             return gethostbyaddr($this->_config['host']);
271:         }
272: 
273:         return gethostbyaddr($this->address());
274:     }
275: 
276:     /**
277:      * Get the IP address of the current connection.
278:      *
279:      * @return string IP address
280:      */
281:     public function address()
282:     {
283:         if (Validation::ip($this->_config['host'])) {
284:             return $this->_config['host'];
285:         }
286: 
287:         return gethostbyname($this->_config['host']);
288:     }
289: 
290:     /**
291:      * Get all IP addresses associated with the current connection.
292:      *
293:      * @return array IP addresses
294:      */
295:     public function addresses()
296:     {
297:         if (Validation::ip($this->_config['host'])) {
298:             return [$this->_config['host']];
299:         }
300: 
301:         return gethostbynamel($this->_config['host']);
302:     }
303: 
304:     /**
305:      * Get the last error as a string.
306:      *
307:      * @return string|null Last error
308:      */
309:     public function lastError()
310:     {
311:         if (!empty($this->lastError)) {
312:             return $this->lastError['num'] . ': ' . $this->lastError['str'];
313:         }
314: 
315:         return null;
316:     }
317: 
318:     /**
319:      * Set the last error.
320:      *
321:      * @param int $errNum Error code
322:      * @param string $errStr Error string
323:      * @return void
324:      */
325:     public function setLastError($errNum, $errStr)
326:     {
327:         $this->lastError = ['num' => $errNum, 'str' => $errStr];
328:     }
329: 
330:     /**
331:      * Write data to the socket.
332:      *
333:      * The bool false return value is deprecated and will be int 0 in the next major.
334:      * Please code respectively to be future proof.
335:      *
336:      * @param string $data The data to write to the socket.
337:      * @return int|false Bytes written.
338:      */
339:     public function write($data)
340:     {
341:         if (!$this->connected && !$this->connect()) {
342:             return false;
343:         }
344:         $totalBytes = strlen($data);
345:         $written = 0;
346:         while ($written < $totalBytes) {
347:             $rv = fwrite($this->connection, substr($data, $written));
348:             if ($rv === false || $rv === 0) {
349:                 return $written;
350:             }
351:             $written += $rv;
352:         }
353: 
354:         return $written;
355:     }
356: 
357:     /**
358:      * Read data from the socket. Returns false if no data is available or no connection could be
359:      * established.
360:      *
361:      * The bool false return value is deprecated and will be null in the next major.
362:      * Please code respectively to be future proof.
363:      *
364:      * @param int $length Optional buffer length to read; defaults to 1024
365:      * @return mixed Socket data
366:      */
367:     public function read($length = 1024)
368:     {
369:         if (!$this->connected && !$this->connect()) {
370:             return false;
371:         }
372: 
373:         if (!feof($this->connection)) {
374:             $buffer = fread($this->connection, $length);
375:             $info = stream_get_meta_data($this->connection);
376:             if ($info['timed_out']) {
377:                 $this->setLastError(E_WARNING, 'Connection timed out');
378: 
379:                 return false;
380:             }
381: 
382:             return $buffer;
383:         }
384: 
385:         return false;
386:     }
387: 
388:     /**
389:      * Disconnect the socket from the current connection.
390:      *
391:      * @return bool Success
392:      */
393:     public function disconnect()
394:     {
395:         if (!is_resource($this->connection)) {
396:             $this->connected = false;
397: 
398:             return true;
399:         }
400:         $this->connected = !fclose($this->connection);
401: 
402:         if (!$this->connected) {
403:             $this->connection = null;
404:         }
405: 
406:         return !$this->connected;
407:     }
408: 
409:     /**
410:      * Destructor, used to disconnect from current connection.
411:      */
412:     public function __destruct()
413:     {
414:         $this->disconnect();
415:     }
416: 
417:     /**
418:      * Resets the state of this Socket instance to it's initial state (before Object::__construct got executed)
419:      *
420:      * @param array|null $state Array with key and values to reset
421:      * @return bool True on success
422:      */
423:     public function reset($state = null)
424:     {
425:         if (empty($state)) {
426:             static $initalState = [];
427:             if (empty($initalState)) {
428:                 $initalState = get_class_vars(__CLASS__);
429:             }
430:             $state = $initalState;
431:         }
432: 
433:         foreach ($state as $property => $value) {
434:             $this->{$property} = $value;
435:         }
436: 
437:         return true;
438:     }
439: 
440:     /**
441:      * Encrypts current stream socket, using one of the defined encryption methods
442:      *
443:      * @param string $type can be one of 'ssl2', 'ssl3', 'ssl23' or 'tls'
444:      * @param string $clientOrServer can be one of 'client', 'server'. Default is 'client'
445:      * @param bool $enable enable or disable encryption. Default is true (enable)
446:      * @return bool True on success
447:      * @throws \InvalidArgumentException When an invalid encryption scheme is chosen.
448:      * @throws \Cake\Network\Exception\SocketException When attempting to enable SSL/TLS fails
449:      * @see stream_socket_enable_crypto
450:      */
451:     public function enableCrypto($type, $clientOrServer = 'client', $enable = true)
452:     {
453:         if (!array_key_exists($type . '_' . $clientOrServer, $this->_encryptMethods)) {
454:             throw new InvalidArgumentException('Invalid encryption scheme chosen');
455:         }
456:         $method = $this->_encryptMethods[$type . '_' . $clientOrServer];
457: 
458:         // Prior to PHP 5.6.7 TLS_CLIENT was any version of TLS. This was changed in 5.6.7
459:         // to fix backwards compatibility issues, and now only resolves to TLS1.0
460:         //
461:         // See https://github.com/php/php-src/commit/10bc5fd4c4c8e1dd57bd911b086e9872a56300a0
462:         if (version_compare(PHP_VERSION, '5.6.7', '>=')) {
463:             if ($method == STREAM_CRYPTO_METHOD_TLS_CLIENT) {
464:                 // @codingStandardsIgnoreStart
465:                 $method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
466:                 // @codingStandardsIgnoreEnd
467:             }
468:             if ($method == STREAM_CRYPTO_METHOD_TLS_SERVER) {
469:                 // @codingStandardsIgnoreStart
470:                 $method |= STREAM_CRYPTO_METHOD_TLSv1_1_SERVER | STREAM_CRYPTO_METHOD_TLSv1_2_SERVER;
471:                 // @codingStandardsIgnoreEnd
472:             }
473:         }
474: 
475:         try {
476:             if ($this->connection === null) {
477:                 throw new CakeException('You must call connect() first.');
478:             }
479:             $enableCryptoResult = stream_socket_enable_crypto($this->connection, $enable, $method);
480:         } catch (Exception $e) {
481:             $this->setLastError(null, $e->getMessage());
482:             throw new SocketException($e->getMessage(), null, $e);
483:         }
484:         if ($enableCryptoResult === true) {
485:             $this->encrypted = $enable;
486: 
487:             return true;
488:         }
489:         $errorMessage = 'Unable to perform enableCrypto operation on the current socket';
490:         $this->setLastError(null, $errorMessage);
491:         throw new SocketException($errorMessage);
492:     }
493: }
494: 
Follow @CakePHP
#IRC
OpenHub
Rackspace
  • Business Solutions
  • Showcase
  • Documentation
  • Book
  • API
  • Videos
  • Logos & Trademarks
  • Community
  • Team
  • Issues (Github)
  • YouTube Channel
  • Get Involved
  • Bakery
  • Featured Resources
  • Newsletter
  • Certification
  • My CakePHP
  • CakeFest
  • Facebook
  • Twitter
  • Help & Support
  • Forum
  • Stack Overflow
  • IRC
  • Slack
  • Paid Support

Generated using CakePHP API Docs