Completed
Push — master ( f6f9ee...3634a4 )
by Benjamin
01:59 queued 11s
created

StreamSocketClient::getSocket()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 5
cts 5
cp 1
rs 9.6666
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 0
crap 2
1
<?php
2
3
/*
4
 * This file is part of the php-gelf package.
5
 *
6
 * (c) Benjamin Zikarsky <http://benjamin-zikarsky.de>
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 Gelf\Transport;
13
14
use RuntimeException;
15
16
/**
17
 * StreamSocketClient is a very simple OO-Wrapper around the PHP
18
 * stream_socket-library and some specific stream-functions like
19
 * fwrite, etc.
20
 *
21
 * @author Benjamin Zikarsky <[email protected]>
22
 */
23
class StreamSocketClient
24
{
25
    /**
26
     * @deprecated deprecated since v1.4.0
27
     */
28
    const SOCKET_TIMEOUT = 30;
29
30
    /**
31
     * @var string
32
     */
33
    protected $host;
34
35
    /**
36
     * @var integer
37
     */
38
    protected $port;
39
40
    /**
41
     * @var string
42
     */
43
    protected $scheme;
44
45
    /**
46
     * @var array
47
     */
48
    protected $context;
49
50
    /**
51
     * @var resource
52
     */
53
    protected $socket;
54
55
    /**
56
     * @var int
57
     */
58
    protected $connectTimeout = self::SOCKET_TIMEOUT;
59
60
    /**
61
     * @param string  $scheme
62
     * @param string  $host
63
     * @param integer $port
64
     * @param array   $context
65
     */
66 42
    public function __construct($scheme, $host, $port, array $context = array())
67
    {
68 42
        $this->scheme = $scheme;
69 42
        $this->host = $host;
70 42
        $this->port = $port;
71 42
        $this->context = $context;
72 42
    }
73
74
    /**
75
     * Destructor, closes socket if possible
76
     */
77 42
    public function __destruct()
78
    {
79 42
        $this->close();
80 42
    }
81
82
    /**
83
     * Initializes socket-client
84
     *
85
     * @deprecated deprecated since v1.4.0
86
     *
87
     * @param string  $scheme  like "udp" or "tcp"
88
     * @param string  $host
89
     * @param integer $port
90
     * @param array   $context
91
     *
92
     * @return resource
93
     *
94
     * @throws RuntimeException on connection-failure
95
     */
96
    protected static function initSocket($scheme, $host, $port, array $context)
97
    {
98
        $socketDescriptor = sprintf("%s://%s:%d", $scheme, $host, $port);
99
        $socket = @stream_socket_client(
100
            $socketDescriptor,
101
            $errNo,
102
            $errStr,
103
            static::SOCKET_TIMEOUT,
104
            \STREAM_CLIENT_CONNECT,
105
            stream_context_create($context)
106
        );
107
108
        if ($socket === false) {
109
            throw new RuntimeException(
110
                sprintf(
111
                    "Failed to create socket-client for %s: %s (%s)",
112
                    $socketDescriptor,
113
                    $errStr,
114
                    $errNo
115
                )
116
            );
117
        }
118
119
        // set non-blocking for UDP
120
        if (strcasecmp("udp", $scheme) == 0) {
121
            stream_set_blocking($socket, 0);
122
        }
123
124
        return $socket;
125
    }
126
127
128
    /**
129
     * Internal function mimicking the behaviour of static::initSocket
130
     * which will get new functionality instead of the deprecated
131
     * "factory"
132
     *
133
     * @return resource
134
     *
135
     * @throws RuntimeException on connection-failure
136
     */
137 15
    private function buildSocket()
138
    {
139 15
        $socketDescriptor = sprintf(
140 15
            "%s://%s:%d",
141 15
            $this->scheme,
142 15
            $this->host,
143 15
            $this->port
144 15
        );
145
146 15
        $socket = @stream_socket_client(
147 15
            $socketDescriptor,
148 15
            $errNo,
149 15
            $errStr,
150 15
            $this->connectTimeout,
151 15
            \STREAM_CLIENT_CONNECT,
152 15
            stream_context_create($this->context)
153 15
        );
154
155 15
        if ($socket === false) {
156 1
            throw new RuntimeException(
157 1
                sprintf(
158 1
                    "Failed to create socket-client for %s: %s (%s)",
159 1
                    $socketDescriptor,
160 1
                    $errStr,
161
                    $errNo
162 1
                )
163 1
            );
164
        }
165
166
        // set non-blocking for UDP
167 14
        if (strcasecmp("udp", $this->scheme) == 0) {
168 4
            stream_set_blocking($socket, 0);
169 4
        }
170
171 14
        return $socket;
172
    }
173
174
    /**
175
     * Returns raw-socket-resource
176
     *
177
     * @return resource
178
     */
179 15
    public function getSocket()
180
    {
181
        // lazy initializing of socket-descriptor
182 15
        if (!$this->socket) {
183 15
            $this->socket = $this->buildSocket();
184 14
        }
185
186 14
        return $this->socket;
187
    }
188
189
    /**
190
     * Writes a given string to the socket and returns the
191
     * number of written bytes
192
     *
193
     * @param string $buffer
194
     *
195
     * @return int
196
     *
197
     * @throws RuntimeException on write-failure
198
     */
199 9
    public function write($buffer)
200
    {
201 9
        $socket = $this->getSocket();
202 9
        $byteCount = @fwrite($socket, $buffer);
203 9
        $bufLen = strlen($buffer);
204
205 8
        if ($byteCount === false) {
206
            throw new \RuntimeException("Failed to write to socket");
207
        }
208
209 8
        if ($byteCount !== $bufLen) {
210 1
            throw new \RuntimeException("Incomplete write: Only $byteCount of $bufLen written");
211
        }
212
213 8
        return $byteCount;
214
    }
215
216
    /**
217
     * Reads a given number of bytes from the socket
218
     *
219
     * @param integer $byteCount
220
     *
221
     * @return string
222
     */
223 2
    public function read($byteCount)
224
    {
225 2
        return fread($this->getSocket(), $byteCount);
226
    }
227
228
    /**
229
     * Closes underlying socket explicitly
230
     */
231 42
    public function close()
232
    {
233 42
        if (!is_resource($this->socket)) {
234 29
            return;
235
        }
236
237 14
        fclose($this->socket);
238 14
        $this->socket = null;
239 14
    }
240
241
    /**
242
     * Returns the current connect-timeout
243
     *
244
     * @return int
245
     */
246 1
    public function getConnectTimeout()
247
    {
248 1
        return $this->connectTimeout;
249
    }
250
251
    /**
252
     * Sets the connect-timeout
253
     *
254
     * @param int $timeout
255
     */
256 1
    public function setConnectTimeout($timeout)
257
    {
258 1
        $this->connectTimeout = $timeout;
259 1
    }
260
}
261