2323 */
2424final class CurlClientState extends ClientState
2525{
26- /** @var array<\CurlMultiHandle|resource> */
27- public $ handles = [];
26+ /** @var \CurlMultiHandle|resource */
27+ public $ handle ;
28+ /** @var \CurlShareHandle|resource */
29+ public $ share ;
2830 /** @var PushedResponse[] */
2931 public $ pushedResponses = [];
3032 /** @var DnsCache */
@@ -37,27 +39,23 @@ final class CurlClientState extends ClientState
3739
3840 public static $ curlVersion ;
3941
40- private $ maxHostConnections ;
41- private $ maxPendingPushes ;
42-
4342 public function __construct (int $ maxHostConnections , int $ maxPendingPushes )
4443 {
4544 self ::$ curlVersion = self ::$ curlVersion ?? curl_version ();
4645
47- array_unshift ( $ this ->handles , $ mh = curl_multi_init () );
46+ $ this ->handle = curl_multi_init ();
4847 $ this ->dnsCache = new DnsCache ();
49- $ this ->maxHostConnections = $ maxHostConnections ;
50- $ this ->maxPendingPushes = $ maxPendingPushes ;
48+ $ this ->reset ();
5149
5250 // Don't enable HTTP/1.1 pipelining: it forces responses to be sent in order
5351 if (\defined ('CURLPIPE_MULTIPLEX ' )) {
54- curl_multi_setopt ($ mh , \CURLMOPT_PIPELINING , \CURLPIPE_MULTIPLEX );
52+ curl_multi_setopt ($ this -> handle , \CURLMOPT_PIPELINING , \CURLPIPE_MULTIPLEX );
5553 }
5654 if (\defined ('CURLMOPT_MAX_HOST_CONNECTIONS ' )) {
57- $ maxHostConnections = curl_multi_setopt ($ mh , \CURLMOPT_MAX_HOST_CONNECTIONS , 0 < $ maxHostConnections ? $ maxHostConnections : \PHP_INT_MAX ) ? 0 : $ maxHostConnections ;
55+ $ maxHostConnections = curl_multi_setopt ($ this -> handle , \CURLMOPT_MAX_HOST_CONNECTIONS , 0 < $ maxHostConnections ? $ maxHostConnections : \PHP_INT_MAX ) ? 0 : $ maxHostConnections ;
5856 }
5957 if (\defined ('CURLMOPT_MAXCONNECTS ' ) && 0 < $ maxHostConnections ) {
60- curl_multi_setopt ($ mh , \CURLMOPT_MAXCONNECTS , $ maxHostConnections );
58+ curl_multi_setopt ($ this -> handle , \CURLMOPT_MAXCONNECTS , $ maxHostConnections );
6159 }
6260
6361 // Skip configuring HTTP/2 push when it's unsupported or buggy, see https://bugs.php.net/77535
@@ -70,40 +68,31 @@ public function __construct(int $maxHostConnections, int $maxPendingPushes)
7068 return ;
7169 }
7270
73- // Clone to prevent a circular reference
74- $ multi = clone $ this ;
75- $ multi ->handles = [$ mh ];
76- $ multi ->pushedResponses = &$ this ->pushedResponses ;
77- $ multi ->logger = &$ this ->logger ;
78- $ multi ->handlesActivity = &$ this ->handlesActivity ;
79- $ multi ->openHandles = &$ this ->openHandles ;
80- $ multi ->lastTimeout = &$ this ->lastTimeout ;
81-
82- curl_multi_setopt ($ mh , \CURLMOPT_PUSHFUNCTION , static function ($ parent , $ pushed , array $ requestHeaders ) use ($ multi , $ maxPendingPushes ) {
83- return $ multi ->handlePush ($ parent , $ pushed , $ requestHeaders , $ maxPendingPushes );
71+ curl_multi_setopt ($ this ->handle , \CURLMOPT_PUSHFUNCTION , function ($ parent , $ pushed , array $ requestHeaders ) use ($ maxPendingPushes ) {
72+ return $ this ->handlePush ($ parent , $ pushed , $ requestHeaders , $ maxPendingPushes );
8473 });
8574 }
8675
8776 public function reset ()
8877 {
8978 foreach ($ this ->pushedResponses as $ url => $ response ) {
9079 $ this ->logger && $ this ->logger ->debug (sprintf ('Unused pushed response: "%s" ' , $ url ));
91-
92- foreach ($ this ->handles as $ mh ) {
93- curl_multi_remove_handle ($ mh , $ response ->handle );
94- }
80+ curl_multi_remove_handle ($ this ->handle , $ response ->handle );
9581 curl_close ($ response ->handle );
9682 }
9783
9884 $ this ->pushedResponses = [];
9985 $ this ->dnsCache ->evictions = $ this ->dnsCache ->evictions ?: $ this ->dnsCache ->removals ;
10086 $ this ->dnsCache ->removals = $ this ->dnsCache ->hostnames = [];
10187
102- if (\defined ('CURLMOPT_PUSHFUNCTION ' )) {
103- curl_multi_setopt ($ this ->handles [0 ], \CURLMOPT_PUSHFUNCTION , null );
104- }
88+ $ this ->share = curl_share_init ();
89+
90+ curl_share_setopt ($ this ->share , \CURLSHOPT_SHARE , \CURL_LOCK_DATA_DNS );
91+ curl_share_setopt ($ this ->share , \CURLSHOPT_SHARE , \CURL_LOCK_DATA_SSL_SESSION );
10592
106- $ this ->__construct ($ this ->maxHostConnections , $ this ->maxPendingPushes );
93+ if (\defined ('CURL_LOCK_DATA_CONNECT ' )) {
94+ curl_share_setopt ($ this ->share , \CURLSHOPT_SHARE , \CURL_LOCK_DATA_CONNECT );
95+ }
10796 }
10897
10998 private function handlePush ($ parent , $ pushed , array $ requestHeaders , int $ maxPendingPushes ): int
0 commit comments