Completed
Branch feature-persistent-connect (647c46)
by Evgenij
03:19
created

SslDataFlushEventHandler::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php
2
/**
3
 * Async sockets
4
 *
5
 * @copyright Copyright (c) 2016, 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
20
/**
21
 * Class SslDataFlushEventHandler. This decorator flushes unread data containing in socket buffer
22
 * which will be evaluated to empty string
23
 */
24
class SslDataFlushEventHandler implements EventHandlerInterface
25
{
26
    /**
27
     * Next handler
28
     *
29
     * @var EventHandlerInterface|null
30
     */
31
    private $next;
32
33
    /**
34
     * Array of socket descriptors currently in flush
35
     *
36
     * @var bool[]
37
     */
38
    private $inFlushingOperations = [];
39
40
    /**
41
     * SslDataFlushEventHandler constructor.
42
     *
43
     * @param EventHandlerInterface|null $next Next event handler
44
     */
45 7
    public function __construct(EventHandlerInterface $next = null)
46
    {
47 7
        $this->next = $next;
48 7
    }
49
50
    /** {@inheritdoc} */
51 7
    public function invokeEvent(Event $event)
52
    {
53 7
        switch ($event->getType()) {
54 7
            case EventType::DATA_ALERT:
55
                /** @var DataAlertEvent $event */
56 2
                $this->onDataAlert($event);
57 2
                break;
58 6
            case EventType::READ:
59
                /** @var ReadEvent $event */
60 5
                $this->onRead($event);
61 5
                break;
62 1
            default:
63 1
                $this->callNextHandler($event);
64 7
        }
65 7
    }
66
67
    /**
68
     * Handle first data alert and try to flush ssl data by empty frame
69
     *
70
     * @param DataAlertEvent $event Event object
71
     *
72
     * @return void
73
     */
74 2
    private function onDataAlert(DataAlertEvent $event)
75
    {
76 2
        if ($event->getAttempt() !== 1) {
77 1
            $this->callNextHandler($event);
78 1
            return;
79
        }
80
81 1
        $event->nextIs(
82 1
            new ReadOperation(
83 1
                new EmptyFramePicker()
84 1
            )
85 1
        );
86
87 1
        $key = spl_object_hash($event->getSocket());
88 1
        $this->inFlushingOperations[$key] = true;
89 1
    }
90
91
    /**
92
     * Handle read data
93
     *
94
     * @param ReadEvent $event Read event
95
     *
96
     * @return void
97
     */
98 5
    private function onRead(ReadEvent $event)
99
    {
100 5
        $key   = spl_object_hash($event->getSocket());
101 5
        $frame = $event->getFrame();
102 5
        if (!($frame instanceof EmptyFrame) || !isset($this->inFlushingOperations[$key])) {
103 4
            $this->callNextHandler($event);
104 4
            return;
105
        }
106
107 1
        unset($this->inFlushingOperations[$key]);
108 1
    }
109
110
    /**
111
     * Call next event handler
112
     *
113
     * @param Event $event Event object
114
     *
115
     * @return void
116
     */
117 6
    private function callNextHandler(Event $event)
118
    {
119 6
        if ($this->next) {
120 6
            $this->next->invokeEvent($event);
121 6
        }
122 6
    }
123
}
124