Message::append()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
namespace gries\Rcon;
4
5
use gries\Rcon\Exception\InvalidPacketException;
6
7
/**
8
 * Class Message
9
 *
10
 * This is a representation of a RCON Message.
11
 * A message MUST always have a type and an ID before sending it.
12
 *
13
 * @package gries\Rcon
14
 */
15
class Message
16
{
17
    /**
18
     * The reply type of  a failed authentication request.
19
     *
20
     * @var int
21
     */
22
    const TYPE_AUTH_FAILURE = -1;
23
24
    /**
25
     * Type for server responses.
26
     */
27
    const TYPE_RESPONSE_VALUE = 0;
28
29
    /**
30
     * Standard type for commands.
31
     *
32
     * @var int
33
     */
34
    const TYPE_COMMAND = 2;
35
36
    /**
37
     * Type for authentication with the server.
38
     *
39
     * @var int
40
     */
41
    const TYPE_AUTH = 3;
42
43
    /**
44
     * @var mixed The type of this message.
45
     */
46
    protected $type;
47
48
    /**
49
     * The body of this message.
50
     *
51
     * @var string
52
     */
53
    protected $body;
54
55
    /**
56
     * The id of this message.
57
     *
58
     * @var int
59
     */
60
    protected $id;
61
62
    /**
63
     * @param string $body
64
     * @param int    $type
65
     * @param null   $id
66
     */
67
    public function __construct($body = '', $type = Message::TYPE_COMMAND, $id = null)
68
    {
69
        $this->body = $body;
70
        $this->type = $type;
71
        $this->id = $id;
72
    }
73
74
    /**
75
     * The message id used for this message.
76
     * This will be encoded in the RconData.
77
     *
78
     * @param int $id
79
     *
80
     * @return string
81
     */
82
    public function convertToRconData($id)
83
    {
84
        $idAndTypePacked = pack('VV', $id, $this->type);
85
        $endOfMessage    = chr(0) . chr(0);
86
87
        $message = $idAndTypePacked . $this->body . $endOfMessage;
88
89
        $data = pack("V", strlen($message)) . $message;
90
91
        return $data;
92
    }
93
94
    /**
95
     * Get the type of this message.
96
     *
97
     * @return int|mixed
98
     */
99
    public function getType()
100
    {
101
        return $this->type;
102
    }
103
104
    /**
105
     * Parses data from a RCON Response.
106
     * Note: the first 4 bytes that indicate the size of the packet MUST not be included.
107
     *
108
     * @param $data
109
     * @param bool|$fragmented If the data comes from a fragmented response only the id and body will be present.
110
     *
111
     * @throws InvalidPacketException
112
     */
113
    public function initializeFromRconData($data, $fragmented = false)
114
    {
115
        if ($fragmented) {
116
            $packet = unpack("V1id/a*body", $data);
117
            $packet['type'] =  static::TYPE_RESPONSE_VALUE;
118
        } else {
119
            // 8 byte for id + type and atleast 2 byte if the body is empty
120
            if (mb_strlen($data) < 10) {
121
                throw new InvalidPacketException();
122
            }
123
124
            $packet = unpack("V1id/V1type/a*body", $data);
125
        }
126
127
        if (!is_array($packet) ||
128
            !isset($packet['id']) ||
129
            !isset($packet['body']) ||
130
            !isset($packet['type'])
131
        ) {
132
            throw new InvalidPacketException();
133
        }
134
135
        $this->id = $packet['id'];
136
        $this->type = $packet['type'];
137
        $this->body = rtrim($packet['body']); // removes null bytes at the end of the string
138
    }
139
140
    /**
141
     * The content of this message.
142
     *
143
     * @return string
144
     */
145
    public function getBody()
146
    {
147
        return $this->body;
148
    }
149
150
    /**
151
     * Get the id of this message.
152
     *
153
     * @return int
154
     */
155
    public function getId()
156
    {
157
        return $this->id;
158
    }
159
160
    /**
161
     * Append a message to this message.
162
     * This will only append the body, the id/type will be unchanged.
163
     *
164
     * @param Message $message
165
     */
166
    public function append(Message $message)
167
    {
168
        $this->body .= $message->getBody();
169
    }
170
}
171