1 | <?php |
||
4 | class Client |
||
5 | { |
||
6 | const SEQUENCE_MAX = 4294967295; |
||
7 | |||
8 | /** @var int */ |
||
9 | private $sequence = 0; |
||
10 | |||
11 | /** @var int */ |
||
12 | private $lastAck = 0; |
||
13 | |||
14 | /** @var int */ |
||
15 | private $windowSize; |
||
16 | |||
17 | /** @var SocketInterface */ |
||
18 | private $socket; |
||
19 | |||
20 | /** @var EncoderInterface */ |
||
21 | private $encoder; |
||
22 | |||
23 | /** |
||
24 | * @param SocketInterface $socket |
||
25 | * @param EncoderInterface $encoder |
||
26 | * @param int $windowSize |
||
27 | */ |
||
28 | 1 | public function __construct(SocketInterface $socket, EncoderInterface $encoder, $windowSize = 5000) |
|
34 | |||
35 | /** |
||
36 | * @param array $hash |
||
37 | * @return int |
||
38 | */ |
||
39 | 1 | public function write(array $hash) |
|
40 | { |
||
41 | 1 | $frame = $this->encoder->toCompressedFrame($hash, $this->nextSequence()); |
|
42 | 1 | if ($this->unackedSequenceSize() >= $this->windowSize) { |
|
43 | $this->ack(); |
||
44 | } |
||
45 | 1 | return $this->socket->write($frame); |
|
46 | } |
||
47 | |||
48 | /** |
||
49 | * @param int $windowSize |
||
50 | */ |
||
51 | 1 | private function setWindowSize($windowSize) |
|
57 | |||
58 | /** |
||
59 | * @return int |
||
60 | */ |
||
61 | 1 | private function nextSequence() |
|
62 | { |
||
63 | 1 | if ($this->sequence + 1 > self::SEQUENCE_MAX) { |
|
64 | $this->sequence = 0; |
||
65 | } |
||
66 | |||
67 | 1 | return ++$this->sequence; |
|
68 | } |
||
69 | |||
70 | /** |
||
71 | * @throws \RuntimeException |
||
72 | */ |
||
73 | private function ack() |
||
74 | { |
||
75 | list(, $type) = $this->readVersionAndType(); |
||
76 | if ($type != 'A') { |
||
77 | throw new \RuntimeException(sprintf("Whoa we shouldn't get this frame: %s", var_export($type, true))); |
||
78 | } |
||
79 | $this->lastAck = $this->readLastAck(); |
||
80 | if ($this->unackedSequenceSize() >= $this->windowSize) { |
||
81 | $this->ack(); |
||
82 | } |
||
83 | } |
||
84 | |||
85 | /** |
||
86 | * @return int |
||
87 | */ |
||
88 | 1 | private function unackedSequenceSize() |
|
92 | |||
93 | /** |
||
94 | * @return array |
||
95 | */ |
||
96 | private function readVersionAndType() |
||
102 | |||
103 | /** |
||
104 | * @return int |
||
105 | */ |
||
106 | private function readLastAck() |
||
111 | } |
||
112 |