74 $parts = explode(
':', $server, 2 );
75 $this->host = $parts[0];
76 $this->
port = isset( $parts[1] ) ? $parts[1] : 80;
86 if ( $this->socket !==
null ) {
92 $this->
log(
"DNS error" );
96 $this->socket = socket_create( AF_INET, SOCK_STREAM, SOL_TCP );
97 socket_set_nonblock( $this->socket );
98 MediaWiki\suppressWarnings();
99 $ok = socket_connect( $this->socket,
$ip, $this->
port );
100 MediaWiki\restoreWarnings();
102 $error = socket_last_error( $this->socket );
103 if ( $error !== self::EINPROGRESS ) {
104 $this->
log(
"connection error: " . socket_strerror( $error ) );
118 if ( $this->readState ==
'idle' ) {
133 if ( !strlen( $this->writeBuffer ) ) {
150 if ( $this->ip ===
null ) {
154 throw new MWException(
'$wgSquidServers does not support IPv6' );
156 MediaWiki\suppressWarnings();
157 $this->ip = gethostbyname( $this->host );
158 if ( $this->ip === $this->host ) {
161 MediaWiki\restoreWarnings();
173 $this->socket =
false;
180 if ( $this->socket ) {
181 MediaWiki\suppressWarnings();
182 socket_set_block( $this->socket );
183 socket_shutdown( $this->socket );
184 socket_close( $this->socket );
185 MediaWiki\restoreWarnings();
187 $this->socket =
null;
188 $this->readBuffer =
'';
203 $host = $url[
'host'];
204 if ( isset( $url[
'port'] ) && strlen( $url[
'port'] ) > 0 ) {
205 $host .=
":" . $url[
'port'];
207 $path = $url[
'path'];
208 if ( isset( $url[
'query'] ) && is_string( $url[
'query'] ) ) {
211 $request[] =
"PURGE $path HTTP/1.1";
216 $request[] =
"Connection: Keep-Alive";
217 $request[] =
"Proxy-Connection: Keep-Alive";
223 $this->requests[] = implode(
"\r\n",
$request );
224 if ( $this->currentRequestIndex ===
null ) {
233 return strlen( $this->writeBuffer ) == 0 && $this->readState ==
'idle';
240 if ( !strlen( $this->writeBuffer ) ) {
248 if ( strlen( $this->writeBuffer ) <= self::BUFFER_SIZE ) {
252 $buf = substr( $this->writeBuffer, 0, self::BUFFER_SIZE );
255 MediaWiki\suppressWarnings();
256 $bytesSent = socket_send(
$socket, $buf, strlen( $buf ),
$flags );
257 MediaWiki\restoreWarnings();
259 if ( $bytesSent ===
false ) {
260 $error = socket_last_error(
$socket );
261 if ( $error != self::EAGAIN && $error != self::EINTR ) {
262 $this->
log(
'write error: ' . socket_strerror( $error ) );
268 $this->writeBuffer = substr( $this->writeBuffer, $bytesSent );
281 MediaWiki\suppressWarnings();
282 $bytesRead = socket_recv(
$socket, $buf, self::BUFFER_SIZE, 0 );
283 MediaWiki\restoreWarnings();
284 if ( $bytesRead ===
false ) {
285 $error = socket_last_error(
$socket );
286 if ( $error != self::EAGAIN && $error != self::EINTR ) {
287 $this->
log(
'read error: ' . socket_strerror( $error ) );
291 } elseif ( $bytesRead === 0 ) {
297 $this->readBuffer .= $buf;
306 switch ( $this->readState ) {
311 $lines = explode(
"\r\n", $this->readBuffer, 2 );
315 if ( $this->readState ==
'status' ) {
320 $this->readBuffer =
$lines[1];
323 if ( $this->bodyRemaining !==
null ) {
324 if ( $this->bodyRemaining > strlen( $this->readBuffer ) ) {
325 $this->bodyRemaining -= strlen( $this->readBuffer );
326 $this->readBuffer =
'';
329 $this->readBuffer = substr( $this->readBuffer, $this->bodyRemaining );
330 $this->bodyRemaining = 0;
336 $this->readBuffer =
'';
340 throw new MWException( __METHOD__ .
': unexpected state' );
348 if ( !preg_match(
'!^HTTP/(\d+)\.(\d+) (\d{3}) (.*)$!',
$line, $m ) ) {
349 $this->
log(
'invalid status line' );
356 $this->
log(
"unexpected status code: $status $reason" );
360 $this->readState =
'header';
367 if ( preg_match(
'/^Content-Length: (\d+)$/i',
$line, $m ) ) {
368 $this->bodyRemaining = intval( $m[1] );
369 } elseif (
$line ===
'' ) {
370 $this->readState =
'body';
375 if ( $this->currentRequestIndex !==
null ) {
376 unset( $this->requests[$this->currentRequestIndex] );
378 if (
count( $this->requests ) ) {
379 $this->readState =
'status';
380 $this->currentRequestIndex =
key( $this->requests );
383 $this->readState =
'idle';
384 $this->currentRequestIndex =
null;
385 $this->writeBuffer =
'';
387 $this->bodyRemaining =
null;
393 protected function log( $msg ) {
394 wfDebugLog(
'squid', __CLASS__ .
" ($this->host): $msg" );