SslDataFlushEventHandler   A
last analyzed

Complexity

Total Complexity 11

Size/Duplication

Total Lines 125
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 90%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 11
c 1
b 0
f 0
lcom 1
cbo 5
dl 0
loc 125
ccs 36
cts 40
cp 0.9
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A invokeEvent() 0 19 3
A onDataAlert() 0 20 2
A onRead() 0 15 3
A callNextHandler() 0 10 2
1
<?php
2
/**
3
 * Async sockets
4
 *
5
 * @copyright Copyright (c) 2015-2017, Efimov Evgenij <[email protected]>
6
 *
7
 * This source file is subject to the MIT license that is bundled
8
 * with this source code in the file LICENSE.
9
 */
10
namespace AsyncSockets\RequestExecutor;
11
12
use AsyncSockets\Event\DataAlertEvent;
13
use AsyncSockets\Event\Event;
14
use AsyncSockets\Event\EventType;
15
use AsyncSockets\Event\ReadEvent;
16
use AsyncSockets\Frame\EmptyFrame;
17
use AsyncSockets\Frame\EmptyFramePicker;
18
use AsyncSockets\Operation\ReadOperation;
19
use AsyncSockets\Socket\SocketInterface;
20
21
/**
22
 * Class SslDataFlushEventHandler. This decorator flushes unread data containing in socket buffer
23
 * which will be evaluated to empty string
24
 */
25
class SslDataFlushEventHandler implements EventHandlerInterface
26
{
27
    /**
28
     * Next handler
29
     *
30
     * @var EventHandlerInterface|null
31
     */
32
    private $next;
33
34
    /**
35
     * Array of socket descriptors currently in flush
36
     *
37
     * @var bool[]
38
     */
39
    private $inFlushingOperations = [];
40
41
    /**
42
     * SslDataFlushEventHandler constructor.
43
     *
44
     * @param EventHandlerInterface|null $next Next event handler
45
     */
46 7
    public function __construct(EventHandlerInterface $next = null)
47
    {
48 7
        $this->next = $next;
49 7
    }
50
51
    /** {@inheritdoc} */
52 7
    public function invokeEvent(
53
        Event $event,
54
        RequestExecutorInterface $executor,
55
        SocketInterface $socket,
56
        ExecutionContext $context
57
    ) {
58 7
        switch ($event->getType()) {
59 7
            case EventType::DATA_ALERT:
60
                /** @var DataAlertEvent $event */
61 1
                $this->onDataAlert($event, $executor, $socket, $context);
62 1
                break;
63 7
            case EventType::READ:
64
                /** @var ReadEvent $event */
65 1
                $this->onRead($event, $executor, $socket, $context);
66 1
                break;
67 6
            default:
68 6
                $this->callNextHandler($event, $executor, $socket, $context);
69 7
        }
70 7
    }
71
72
    /**
73
     * Handle first data alert and try to flush ssl data by empty frame
74
     *
75
     * @param DataAlertEvent           $event    Event object
76
     * @param RequestExecutorInterface $executor Request executor fired an event
77
     * @param SocketInterface          $socket   Socket connected with event
78
     * @param ExecutionContext         $context  Global data context
79
     *
80
     * @return void
81
     */
82 1
    private function onDataAlert(
83
        DataAlertEvent $event,
84
        RequestExecutorInterface $executor,
85
        SocketInterface $socket,
86
        ExecutionContext $context
87
    ) {
88 1
        if ($event->getAttempt() !== 1) {
89
            $this->callNextHandler($event, $executor, $socket, $context);
90
            return;
91
        }
92
93 1
        $event->nextIs(
94 1
            new ReadOperation(
95 1
                new EmptyFramePicker()
96 1
            )
97 1
        );
98
99 1
        $key = spl_object_hash($socket);
100 1
        $this->inFlushingOperations[$key] = true;
101 1
    }
102
103
    /**
104
     * Handle read data
105
     *
106
     * @param ReadEvent                $event    Read event
107
     * @param RequestExecutorInterface $executor Request executor fired an event
108
     * @param SocketInterface          $socket   Socket connected with event
109
     * @param ExecutionContext         $context  Global data context
110
     *
111
     * @return void
112
     */
113 1
    private function onRead(
114
        ReadEvent $event,
115
        RequestExecutorInterface $executor,
116
        SocketInterface $socket,
117
        ExecutionContext $context
118
    ) {
119 1
        $key   = spl_object_hash($socket);
120 1
        $frame = $event->getFrame();
121 1
        if (!($frame instanceof EmptyFrame) || !isset($this->inFlushingOperations[$key])) {
122
            $this->callNextHandler($event, $executor, $socket, $context);
123
            return;
124
        }
125
126 1
        unset($this->inFlushingOperations[$key]);
127 1
    }
128
129
    /**
130
     * Call next event handler
131
     *
132
     * @param Event                    $event    Event object
133
     * @param RequestExecutorInterface $executor Request executor fired an event
134
     * @param SocketInterface          $socket   Socket connected with event
135
     * @param ExecutionContext         $context  Global data context
136
     *
137
     * @return void
138
     */
139 6
    private function callNextHandler(
140
        Event $event,
141
        RequestExecutorInterface $executor,
142
        SocketInterface $socket,
143
        ExecutionContext $context
144
    ) {
145 6
        if ($this->next) {
146 6
            $this->next->invokeEvent($event, $executor, $socket, $context);
147 6
        }
148 6
    }
149
}
150