AbstractConnection::checkBlockingListeners()   B
last analyzed

Complexity

Conditions 5
Paths 4

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
dl 0
loc 17
ccs 0
cts 13
cp 0
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 10
nc 4
nop 0
crap 30
1
<?php
2
3
/**
4
 * Copyright 2014 Fabian Grutschus. All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without modification,
7
 * are permitted provided that the following conditions are met:
8
 *
9
 * 1. Redistributions of source code must retain the above copyright notice, this
10
 *   list of conditions and the following disclaimer.
11
 *
12
 * 2. Redistributions in binary form must reproduce the above copyright notice,
13
 *   this list of conditions and the following disclaimer in the documentation
14
 *   and/or other materials provided with the distribution.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
 *
27
 * The views and conclusions contained in the software and documentation are those
28
 * of the authors and should not be interpreted as representing official policies,
29
 * either expressed or implied, of the copyright holders.
30
 *
31
 * @author    Fabian Grutschus <[email protected]>
32
 * @copyright 2014 Fabian Grutschus. All rights reserved.
33
 * @license   BSD
34
 * @link      http://github.com/fabiang/xmpp
35
 */
36
37
namespace Fabiang\Xmpp\Connection;
38
39
use Fabiang\Xmpp\Stream\XMLStream;
40
use Fabiang\Xmpp\EventListener\EventListenerInterface;
41
use Fabiang\Xmpp\Event\EventManager;
42
use Fabiang\Xmpp\Event\EventManagerInterface;
43
use Fabiang\Xmpp\EventListener\BlockingEventListenerInterface;
44
use Fabiang\Xmpp\Options;
45
use Fabiang\Xmpp\Exception\TimeoutException;
46
use Psr\Log\LogLevel;
47
48
/**
49
 * Connection test double.
50
 *
51
 * @package Xmpp\Connection
52
 */
53
abstract class AbstractConnection implements ConnectionInterface
54
{
55
56
    /**
57
     *
58
     * @var XMLStream
59
     */
60
    protected $outputStream;
61
62
    /**
63
     *
64
     * @var XMLStream
65
     */
66
    protected $inputStream;
67
68
    /**
69
     * Options.
70
     *
71
     * @var Options
72
     */
73
    protected $options;
74
75
    /**
76
     * Eventmanager.
77
     *
78
     * @var EventManagerInterface
79
     */
80
    protected $events;
81
82
    /**
83
     * Event listeners.
84
     *
85
     * @var EventListenerInterface[]
86
     */
87
    protected $listeners = [];
88
89
    /**
90
     * Connected.
91
     *
92
     * @var boolean
93
     */
94
    protected $connected = false;
95
96
    /**
97
     *
98
     * @var boolean
99
     */
100
    protected $ready = false;
101
102
    /**
103
     * Timestamp of last response data received.
104
     *
105
     * @var integer
106
     */
107
    private $lastResponse;
108
109
    /**
110
     * Last blocking event listener.
111
     *
112
     * Cached to reduce debug output a bit.
113
     *
114
     * @var BlockingEventListenerInterface
115
     */
116
    private $lastBlockingListener;
117
118
    /**
119
     * {@inheritDoc}
120
     */
121 3
    public function getOutputStream()
122
    {
123 3
        if (null === $this->outputStream) {
124 3
            $this->outputStream = new XMLStream();
125 3
        }
126
127 3
        return $this->outputStream;
128
    }
129
130
    /**
131
     * {@inheritDoc}
132
     */
133 3
    public function getInputStream()
134
    {
135 3
        if (null === $this->inputStream) {
136 3
            $this->inputStream = new XMLStream();
137 3
        }
138
139 3
        return $this->inputStream;
140
    }
141
142
    /**
143
     * {@inheritDoc}
144
     */
145 3
    public function setOutputStream(XMLStream $outputStream)
146
    {
147 3
        $this->outputStream = $outputStream;
148 3
        return $this;
149
    }
150
151
    /**
152
     * {@inheritDoc}
153
     */
154 3
    public function setInputStream(XMLStream $inputStream)
155
    {
156 3
        $this->inputStream = $inputStream;
157 3
        return $this;
158
    }
159
160
    /**
161
     * {@inheritDoc}
162
     */
163 3
    public function addListener(EventListenerInterface $eventListener)
164
    {
165 3
        $this->listeners[] = $eventListener;
166 3
        return $this;
167
    }
168
169
    /**
170
     * {@inheritDoc}
171
     */
172 6
    public function isConnected()
173
    {
174 6
        return $this->connected;
175
    }
176
177
    /**
178
     * {@inheritDoc}
179
     */
180
    public function isReady()
181
    {
182
        return $this->ready;
183
    }
184
185
    /**
186
     * {@inheritDoc}
187
     */
188
    public function setReady($flag)
189
    {
190
        $this->ready = (bool) $flag;
191
        return $this;
192
    }
193
194
    /**
195
     * Reset streams.
196
     *
197
     * @return void
198
     */
199 3
    public function resetStreams()
200
    {
201 3
        $this->getInputStream()->reset();
202 3
        $this->getOutputStream()->reset();
203 3
    }
204
205
    /**
206
     * {@inheritDoc}
207
     */
208 3
    public function getEventManager()
209
    {
210 3
        if (null === $this->events) {
211 3
            $this->setEventManager(new EventManager());
212 3
        }
213
214 3
        return $this->events;
215
    }
216
217
    /**
218
     * {@inheritDoc}
219
     */
220 3
    public function setEventManager(EventManagerInterface $events)
221
    {
222 3
        $this->events = $events;
223 3
        return $this;
224
    }
225
226
    /**
227
     * Get listeners.
228
     *
229
     * @return EventListenerInterface
230
     */
231 3
    public function getListeners()
232
    {
233 3
        return $this->listeners;
234
    }
235
236
    /**
237
     * {@inheritDoc}
238
     */
239
    public function getOptions()
240
    {
241
        return $this->options;
242
    }
243
244
    /**
245
     * {@inheritDoc}
246
     */
247
    public function setOptions(Options $options)
248
    {
249
        $this->options = $options;
250
        return $this;
251
    }
252
253
    /**
254
     * Call logging event.
255
     *
256
     * @param string  $message Log message
257
     * @param integer $level   Log level
258
     * @return void
259
     */
260 3
    protected function log($message, $level = LogLevel::DEBUG)
261
    {
262 3
        $this->getEventManager()->trigger('logger', $this, [$message, $level]);
263 3
    }
264
265
    /**
266
     * Check blocking event listeners.
267
     *
268
     * @return boolean
269
     */
270
    protected function checkBlockingListeners()
271
    {
272
        $blocking = false;
273
        foreach ($this->listeners as $listener) {
274
            $instanceof = $listener instanceof BlockingEventListenerInterface;
275
            if ($instanceof && true === $listener->isBlocking()) {
276
                // cache the last blocking listener. Reducing output.
277
                if ($this->lastBlockingListener !== $listener) {
278
                    $this->log('Listener "' . get_class($listener) . '" is currently blocking', LogLevel::DEBUG);
279
                    $this->lastBlockingListener = $listener;
280
                }
281
                $blocking = true;
282
            }
283
        }
284
285
        return $blocking;
286
    }
287
288
    /**
289
     * Check for timeout.
290
     *
291
     * @param string $buffer Function required current received buffer
292
     * @throws TimeoutException
293
     */
294 3
    protected function checkTimeout($buffer)
295
    {
296 3
        if (!empty($buffer)) {
297
            $this->lastResponse = time();
298
            return;
299
        }
300
301 3
        if (null === $this->lastResponse) {
302 3
            $this->lastResponse = time();
303 3
        }
304
305 3
        $timeout = $this->getOptions()->getTimeout();
306
307 3
        if (time() >= $this->lastResponse + $timeout) {
308 3
            throw new TimeoutException('Connection lost after ' . $timeout . ' seconds');
309
        }
310
    }
311
}
312