2727 */
2828class Socket implements HttpAdapter, StreamInterface
2929{
30+ /**
31+ * Map SSL transport wrappers to stream crypto method constants
32+ *
33+ * @var array
34+ */
35+ protected static $ sslCryptoTypes = array (
36+ 'ssl ' => STREAM_CRYPTO_METHOD_SSLv23_CLIENT,
37+ 'sslv2 ' => STREAM_CRYPTO_METHOD_SSLv2_CLIENT,
38+ 'sslv3 ' => STREAM_CRYPTO_METHOD_SSLv3_CLIENT,
39+ 'tls ' => STREAM_CRYPTO_METHOD_TLS_CLIENT
40+ );
41+
3042 /**
3143 * The socket for server connection
3244 *
@@ -174,50 +186,53 @@ public function getStreamContext()
174186 */
175187 public function connect ($ host , $ port = 80 , $ secure = false )
176188 {
177- // If the URI should be accessed via SSL, prepend the Hostname with ssl://
178- $ host = ($ secure ? $ this ->config ['ssltransport ' ] : 'tcp ' ) . ':// ' . $ host ;
179-
180189 // If we are connected to the wrong host, disconnect first
181190 if (($ this ->connected_to [0 ] != $ host || $ this ->connected_to [1 ] != $ port )) {
182- if (is_resource ($ this ->socket )) $ this ->close ();
191+ if (is_resource ($ this ->socket )) {
192+ $ this ->close ();
193+ }
183194 }
184195
185196 // Now, if we are not connected, connect
186- if (! is_resource ($ this ->socket ) || ! $ this ->config ['keepalive ' ]) {
197+ if (!is_resource ($ this ->socket ) || ! $ this ->config ['keepalive ' ]) {
187198 $ context = $ this ->getStreamContext ();
199+
188200 if ($ secure || $ this ->config ['sslusecontext ' ]) {
189201 if ($ this ->config ['sslverifypeer ' ] !== null ) {
190- if (! stream_context_set_option ($ context , 'ssl ' , 'verify_peer ' ,
191- $ this ->config ['sslverifypeer ' ])) {
202+ if (!stream_context_set_option ($ context , 'ssl ' , 'verify_peer ' , $ this ->config ['sslverifypeer ' ])) {
192203 throw new AdapterException \RuntimeException ('Unable to set sslverifypeer option ' );
193204 }
194- if (! stream_context_set_option ($ context , 'ssl ' , 'capath ' ,
195- $ this ->config ['sslcapath ' ])) {
205+ }
206+
207+ if ($ this ->config ['sslcapath ' ]) {
208+ if (!stream_context_set_option ($ context , 'ssl ' , 'capath ' , $ this ->config ['sslcapath ' ])) {
196209 throw new AdapterException \RuntimeException ('Unable to set sslcapath option ' );
197210 }
198- if ( $ this -> config [ ' sslallowselfsigned ' ] !== null ) {
199- if (! stream_context_set_option ( $ context , ' ssl ' , ' allow_self_signed ' ,
200- $ this ->config ['sslallowselfsigned ' ]) ) {
201- throw new AdapterException \ RuntimeException ( ' Unable to set sslallowselfsigned option ' );
202- }
211+ }
212+
213+ if ( $ this ->config ['sslallowselfsigned ' ] !== null ) {
214+ if (! stream_context_set_option ( $ context , ' ssl ' , ' allow_self_signed ' , $ this -> config [ ' sslallowselfsigned ' ])) {
215+ throw new AdapterException \ RuntimeException ( ' Unable to set sslallowselfsigned option ' );
203216 }
204217 }
218+
205219 if ($ this ->config ['sslcert ' ] !== null ) {
206- if (! stream_context_set_option ($ context , 'ssl ' , 'local_cert ' ,
207- $ this ->config ['sslcert ' ])) {
220+ if (!stream_context_set_option ($ context , 'ssl ' , 'local_cert ' , $ this ->config ['sslcert ' ])) {
208221 throw new AdapterException \RuntimeException ('Unable to set sslcert option ' );
209222 }
210223 }
224+
211225 if ($ this ->config ['sslpassphrase ' ] !== null ) {
212- if (! stream_context_set_option ($ context , 'ssl ' , 'passphrase ' ,
213- $ this ->config ['sslpassphrase ' ])) {
226+ if (!stream_context_set_option ($ context , 'ssl ' , 'passphrase ' , $ this ->config ['sslpassphrase ' ])) {
214227 throw new AdapterException \RuntimeException ('Unable to set sslpassphrase option ' );
215228 }
216229 }
217230 }
218231
219232 $ flags = STREAM_CLIENT_CONNECT ;
220- if ($ this ->config ['persistent ' ]) $ flags |= STREAM_CLIENT_PERSISTENT ;
233+ if ($ this ->config ['persistent ' ]) {
234+ $ flags |= STREAM_CLIENT_PERSISTENT ;
235+ }
221236
222237 ErrorHandler::start ();
223238 $ this ->socket = stream_socket_client (
@@ -230,21 +245,66 @@ public function connect($host, $port = 80, $secure = false)
230245 );
231246 $ error = ErrorHandler::stop ();
232247
233- if (! $ this ->socket ) {
248+ if (!$ this ->socket ) {
234249 $ this ->close ();
235- throw new AdapterException \RuntimeException (sprintf (
236- 'Unable to connect to %s:%d%s ' ,
237- $ host ,
238- $ port ,
239- ($ error ? '. Error # ' . $ error ->getCode () . ': ' . $ error ->getMessage () : '' )
240- ), 0 , $ error );
250+ throw new AdapterException \RuntimeException (
251+ sprintf (
252+ 'Unable to connect to %s:%d%s ' ,
253+ $ host ,
254+ $ port ,
255+ ($ error ? '. Error # ' . $ error ->getCode () . ': ' . $ error ->getMessage () : '' )
256+ ),
257+ 0 ,
258+ $ error
259+ );
241260 }
242261
243262 // Set the stream timeout
244- if (! stream_set_timeout ($ this ->socket , (int ) $ this ->config ['timeout ' ])) {
263+ if (!stream_set_timeout ($ this ->socket , (int ) $ this ->config ['timeout ' ])) {
245264 throw new AdapterException \RuntimeException ('Unable to set the connection timeout ' );
246265 }
247266
267+ if ($ secure || $ this ->config ['sslusecontext ' ]) {
268+ if ($ this ->config ['ssltransport ' ] && isset (self ::$ sslCryptoTypes [$ this ->config ['ssltransport ' ]])) {
269+ $ sslCryptoMethod = self ::$ sslCryptoTypes [$ this ->config ['ssltransport ' ]];
270+ } else {
271+ $ sslCryptoMethod = STREAM_CRYPTO_METHOD_SSLv23_CLIENT;
272+ }
273+
274+ ErrorHandler::start ();
275+ $ test = stream_socket_enable_crypto ($ this ->socket , true , $ sslCryptoMethod );
276+ $ error = ErrorHandler::stop ();
277+ if (!$ test || $ error ) {
278+ // Error handling is kind of difficult when it comes to SSL
279+ $ errorString = '' ;
280+ while (($ sslError = openssl_error_string ()) != false ) {
281+ $ errorString .= "; SSL error: $ sslError " ;
282+ }
283+ $ this ->close ();
284+
285+ if ((! $ errorString ) && $ this ->config ['sslverifypeer ' ]) {
286+ // There's good chance our error is due to sslcapath not being properly set
287+ if (! ($ this ->config ['sslcapath ' ] && is_dir ($ this ->config ['sslcapath ' ]))) {
288+ $ errorString = 'make sure the "sslcapath" option points to a valid SSL certificate directory ' ;
289+ }
290+ }
291+
292+ if ($ errorString ) {
293+ $ errorString = ": $ errorString " ;
294+ }
295+
296+ throw new AdapterException \RuntimeException (sprintf (
297+ 'Unable to enable crypto on TCP connection %s%s ' ,
298+ $ host ,
299+ $ errorString
300+ ), 0 , $ error );
301+ }
302+
303+ $ host = $ this ->config ['ssltransport ' ] . ":// " . $ host ;
304+ } else {
305+ $ host = 'tcp:// ' . $ host ;
306+ }
307+
248308 // Update connected_to
249309 $ this ->connected_to = array ($ host , $ port );
250310 }
0 commit comments