Passed
Push — master ( edb799...f409da )
by Petr
07:56
created

Answer   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 157
Duplicated Lines 0 %

Test Coverage

Coverage 95.45%

Importance

Changes 0
Metric Value
eloc 58
dl 0
loc 157
ccs 63
cts 66
cp 0.9545
rs 10
c 0
b 0
f 0
wmc 23

16 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A getHeader() 0 5 2
A process() 0 8 1
A getSequence() 0 3 1
A getInitialSumChunk() 0 3 1
A getKey() 0 3 1
A getCommand() 0 3 1
A getContent() 0 3 1
A getExtraData() 0 3 1
A processContent() 0 8 2
A getFilePosition() 0 3 1
A getChecksumPacket() 0 5 1
A processHeader() 0 8 1
A getDataLength() 0 3 1
A checkSize() 0 9 4
A checkResponse() 0 14 3
1
<?php
2
3
namespace kalanis\RemoteRequest\Protocols\Fsp;
4
5
6
use kalanis\RemoteRequest\Interfaces\IRRTranslations;
7
use kalanis\RemoteRequest\Protocols;
8
use kalanis\RemoteRequest\RequestException;
9
10
11
/**
12
 * Class Answer
13
 * @package RemoteRequest\Protocols\Fsp
14
 * Process server's answer - FSP packet
15
 */
16
class Answer extends Protocols\Dummy\Answer
17
{
18
    use Traits\THeader;
19
    use Traits\TChecksum;
20
21
    /** @var int */
22
    protected $headChecksum = 0;
23
    /** @var int */
24
    protected $headCommand = 0;
25
    /** @var int */
26
    protected $headServerKey = 0;
27
    /** @var int */
28
    protected $headSequence = 0;
29
    /** @var int */
30
    protected $headDataLength = 0;
31
    /** @var int */
32
    protected $headFilePosition = 0;
33
    /** @var string */
34
    protected $header = '';
35
    /** @var string */
36
    protected $content = '';
37
    /** @var string */
38
    protected $extra = '';
39
40
    /** @var IRRTranslations */
41
    protected $lang = null;
42
    /** @var bool */
43
    public $canDump = false; // for dump info about checksums
44
45 20
    public function __construct(IRRTranslations $lang)
46
    {
47 20
        $this->lang = $lang;
48 20
    }
49
50
    /**
51
     * @throws RequestException
52
     * @return Answer
53
     */
54 18
    public function process(): Answer
55
    {
56 18
        $this->checkSize();
57 16
        $this->getHeader();
58 16
        $this->processHeader();
59 16
        $this->processContent();
60 16
        $this->checkResponse();
61 15
        return $this;
62
    }
63
64
    /**
65
     * @throws RequestException
66
     */
67 18
    protected function checkSize(): void
68
    {
69
        // @phpstan-ignore-next-line
70 18
        $loadSize = is_resource($this->body) ? fstat($this->body)['size'] : strlen(strval($this->body));
71 18
        if (Protocols\Fsp::HEADER_SIZE > $loadSize) {
72 1
            throw new RequestException($this->lang->rrFspResponseShort($loadSize));
73
        }
74 17
        if (Protocols\Fsp::MAX_PACKET_SIZE < $loadSize) {
75 1
            throw new RequestException($this->lang->rrFspResponseLarge($loadSize));
76
        }
77 16
    }
78
79 16
    protected function getHeader(): void
80
    {
81 16
        $this->header = is_resource($this->body)
82 15
            ? strval(stream_get_contents($this->body, Protocols\Fsp::HEADER_SIZE, 0))
83 1
            : strval(substr(strval($this->body), 0, Protocols\Fsp::HEADER_SIZE))
84
        ;
85 16
    }
86
87 16
    protected function processHeader(): void
88
    {
89 16
        $this->headCommand = Strings::cutter($this->header, 0, 1);
90 16
        $this->headChecksum = Strings::cutter($this->header, 1, 1);
91 16
        $this->headServerKey = Strings::cutter($this->header, 2, 2);
92 16
        $this->headSequence = Strings::cutter($this->header, 4, 2);
93 16
        $this->headDataLength = Strings::cutter($this->header, 6, 2);
94 16
        $this->headFilePosition = Strings::cutter($this->header, 8, 4);
95 16
    }
96
97 16
    protected function processContent(): void
98
    {
99 16
        $content = is_resource($this->body)
100 15
            ? strval(stream_get_contents($this->body, -1, Protocols\Fsp::HEADER_SIZE))
101 16
            : strval(substr(strval($this->body), Protocols\Fsp::HEADER_SIZE))
102
        ;
103 16
        $this->content = strval(substr($content, 0, $this->getDataLength()));
104 16
        $this->extra = strval(substr($content, $this->getDataLength()));
105 16
    }
106
107
    /**
108
     * Generate server checksum from data and compare them
109
     * @throws RequestException
110
     */
111 16
    protected function checkResponse(): void
112
    {
113 16
        $checksum = $this->computeCheckSum();
114
        // @codeCoverageIgnoreStart
115
        // necessary dumper - who can calculate checksums from their head?
116 16
        if ($this->canDump) {
117
            var_dump(['chksums',
0 ignored issues
show
Security Debugging Code introduced by
var_dump(array('chksums'...($this->headChecksum))) looks like debug code. Are you sure you do not want to remove it?
Loading history...
118
                'calc_raw' => $checksum, 'calc_hex' => dechex($checksum), 'calc_bin' => decbin($checksum),
119
                'got_raw' => $this->headChecksum, 'got_hex' => dechex($this->headChecksum), 'got_bin' => decbin($this->headChecksum)
120
            ]);
121
        }
122
        // @codeCoverageIgnoreEnd
123 16
        if ($checksum != $this->headChecksum ) {
124 1
            throw new RequestException($this->lang->rrFspInvalidChecksum($checksum, $this->headChecksum));
125
        }
126 15
    }
127
128 16
    public function getInitialSumChunk(): int
129
    {
130 16
        return 0;
131
    }
132
133 16
    public function getChecksumPacket(): string
134
    {
135 16
        $content = $this->header . $this->content . $this->extra ;
136 16
        $content[1] = chr(0); // null checksum
137 16
        return $content;
138
    }
139
140 15
    public function getCommand(): int
141
    {
142 15
        return intval($this->headCommand);
143
    }
144
145 3
    public function getKey(): int
146
    {
147 3
        return intval($this->headServerKey);
148
    }
149
150 3
    public function getSequence(): int
151
    {
152 3
        return intval($this->headSequence);
153
    }
154
155 16
    public function getDataLength(): int
156
    {
157 16
        return intval($this->headDataLength);
158
    }
159
160 8
    public function getFilePosition(): int
161
    {
162 8
        return intval($this->headFilePosition);
163
    }
164
165 12
    public function getContent(): string
166
    {
167 12
        return strval($this->content);
168
    }
169
170 6
    public function getExtraData(): string
171
    {
172 6
        return strval($this->extra);
173
    }
174
}
175