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
12namespace Monolog\Handler;
13
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}
Base Handler class providing the Handler structure.
Stores to any socket - uses fsockopen() or pfsockopen().
setTimeout($seconds)
Set write timeout.
streamSetTimeout()
Wrapper to allow mocking.
fwrite($data)
Wrapper to allow mocking.
write(array $record)
Connect (if necessary) and write to the socket.
isConnected()
Check to see if the socket is currently available.
pfsockopen()
Wrapper to allow mocking.
fsockopen()
Wrapper to allow mocking.
getConnectionString()
Get current connection string.
setConnectionTimeout($seconds)
Set connection timeout.
close()
We will not close a PersistentSocket instance so it can be reused in other requests.
getConnectionTimeout()
Get current connection timeout setting.
streamGetMetadata()
Wrapper to allow mocking.
setPersistent($boolean)
Set socket connection to nbe persistent.
__construct($connectionString, $level=Logger::DEBUG, $bubble=true)
isPersistent()
Get persistent setting.
getTimeout()
Get current in-transfer timeout.
closeSocket()
Close socket, if open.
Monolog log channel.
Definition: Logger.php:28
const DEBUG
Detailed debug information.
Definition: Logger.php:32
$data