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.7 Red Velvet API

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