ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
SocketHandler.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the Monolog package.
5  *
6  * (c) Jordi Boggiano <j.boggiano@seld.be>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11 
12 namespace Monolog\Handler;
13 
14 use Monolog\Logger;
15 
23 {
26  private $resource;
27  private $timeout = 0;
28  private $persistent = false;
29  private $errno;
30  private $errstr;
31 
38  {
39  parent::__construct($level, $bubble);
40  $this->connectionString = $connectionString;
41  $this->connectionTimeout = (float) ini_get('default_socket_timeout');
42  }
43 
52  protected function write(array $record)
53  {
54  $this->connectIfNotConnected();
55  $data = $this->generateDataStream($record);
56  $this->writeToSocket($data);
57  }
58 
62  public function close()
63  {
64  if (!$this->isPersistent()) {
65  $this->closeSocket();
66  }
67  }
68 
72  public function closeSocket()
73  {
74  if (is_resource($this->resource)) {
75  fclose($this->resource);
76  $this->resource = null;
77  }
78  }
79 
85  public function setPersistent($boolean)
86  {
87  $this->persistent = (boolean) $boolean;
88  }
89 
97  public function setConnectionTimeout($seconds)
98  {
99  $this->validateTimeout($seconds);
100  $this->connectionTimeout = (float) $seconds;
101  }
102 
110  public function setTimeout($seconds)
111  {
112  $this->validateTimeout($seconds);
113  $this->timeout = (float) $seconds;
114  }
115 
121  public function getConnectionString()
122  {
124  }
125 
131  public function isPersistent()
132  {
133  return $this->persistent;
134  }
135 
141  public function getConnectionTimeout()
142  {
144  }
145 
151  public function getTimeout()
152  {
153  return $this->timeout;
154  }
155 
163  public function isConnected()
164  {
165  return is_resource($this->resource)
166  && !feof($this->resource); // on TCP - other party can close connection.
167  }
168 
172  protected function pfsockopen()
173  {
174  return @pfsockopen($this->connectionString, -1, $this->errno, $this->errstr, $this->connectionTimeout);
175  }
176 
180  protected function fsockopen()
181  {
182  return @fsockopen($this->connectionString, -1, $this->errno, $this->errstr, $this->connectionTimeout);
183  }
184 
190  protected function streamSetTimeout()
191  {
192  $seconds = floor($this->timeout);
193  $microseconds = round(($this->timeout - $seconds)*1e6);
194 
195  return stream_set_timeout($this->resource, $seconds, $microseconds);
196  }
197 
201  protected function fwrite($data)
202  {
203  return @fwrite($this->resource, $data);
204  }
205 
209  protected function streamGetMetadata()
210  {
211  return stream_get_meta_data($this->resource);
212  }
213 
214  private function validateTimeout($value)
215  {
216  $ok = filter_var($value, FILTER_VALIDATE_FLOAT);
217  if ($ok === false || $value < 0) {
218  throw new \InvalidArgumentException("Timeout must be 0 or a positive float (got $value)");
219  }
220  }
221 
222  private function connectIfNotConnected()
223  {
224  if ($this->isConnected()) {
225  return;
226  }
227  $this->connect();
228  }
229 
230  protected function generateDataStream($record)
231  {
232  return (string) $record['formatted'];
233  }
234 
235  private function connect()
236  {
237  $this->createSocketResource();
238  $this->setSocketTimeout();
239  }
240 
241  private function createSocketResource()
242  {
243  if ($this->isPersistent()) {
244  $resource = $this->pfsockopen();
245  } else {
246  $resource = $this->fsockopen();
247  }
248  if (!$resource) {
249  throw new \UnexpectedValueException("Failed connecting to $this->connectionString ($this->errno: $this->errstr)");
250  }
251  $this->resource = $resource;
252  }
253 
254  private function setSocketTimeout()
255  {
256  if (!$this->streamSetTimeout()) {
257  throw new \UnexpectedValueException("Failed setting timeout with stream_set_timeout()");
258  }
259  }
260 
261  private function writeToSocket($data)
262  {
263  $length = strlen($data);
264  $sent = 0;
265  while ($this->isConnected() && $sent < $length) {
266  if (0 == $sent) {
267  $chunk = $this->fwrite($data);
268  } else {
269  $chunk = $this->fwrite(substr($data, $sent));
270  }
271  if ($chunk === false) {
272  throw new \RuntimeException("Could not write to socket");
273  }
274  $sent += $chunk;
275  $socketInfo = $this->streamGetMetadata();
276  if ($socketInfo['timed_out']) {
277  throw new \RuntimeException("Write timed-out");
278  }
279  }
280  if (!$this->isConnected() && $sent < $length) {
281  throw new \RuntimeException("End-of-file reached, probably we got disconnected (sent $sent of $length)");
282  }
283  }
284 }
getConnectionString()
Get current connection string.
const DEBUG
Detailed debug information.
Definition: Logger.php:32
setTimeout($seconds)
Set write timeout.
Stores to any socket - uses fsockopen() or pfsockopen().
Base Handler class providing the Handler structure.
__construct($connectionString, $level=Logger::DEBUG, $bubble=true)
fwrite($data)
Wrapper to allow mocking.
isConnected()
Check to see if the socket is currently available.
write(array $record)
Connect (if necessary) and write to the socket.
fsockopen()
Wrapper to allow mocking.
setPersistent($boolean)
Set socket connection to nbe persistent.
$data
close()
We will not close a PersistentSocket instance so it can be reused in other requests.
streamSetTimeout()
Wrapper to allow mocking.
isPersistent()
Get persistent setting.
setConnectionTimeout($seconds)
Set connection timeout.
pfsockopen()
Wrapper to allow mocking.
getConnectionTimeout()
Get current connection timeout setting.
getTimeout()
Get current in-transfer timeout.
closeSocket()
Close socket, if open.
streamGetMetadata()
Wrapper to allow mocking.