1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* This file is part of Dedipanel project |
5
|
|
|
* |
6
|
|
|
* (c) 2010-2015 Dedipanel <http://www.dedicated-panel.net> |
7
|
|
|
* |
8
|
|
|
* For the full copyright and license information, please view the LICENSE |
9
|
|
|
* file that was distributed with this source code. |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace DP\GameServer\GameServerBundle\Socket; |
13
|
|
|
|
14
|
|
|
use DP\GameServer\GameServerBundle\Socket\Exception\EmptyPacketException; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* @author Albin Kerouanton |
18
|
|
|
*/ |
19
|
|
|
class Packet |
20
|
|
|
{ |
21
|
|
|
private $content; |
22
|
|
|
private $pos; |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* Constructor |
26
|
|
|
* @param string $content |
27
|
|
|
*/ |
28
|
|
|
public function __construct($content = null) |
29
|
|
|
{ |
30
|
|
|
$this->rewind(); |
31
|
|
|
$this->content = $content; |
32
|
|
|
} |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* Set content |
36
|
|
|
* |
37
|
|
|
* @param string $content |
38
|
|
|
*/ |
39
|
|
|
public function setContent($content) |
40
|
|
|
{ |
41
|
|
|
$this->content = $content; |
42
|
|
|
} |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* @param string $content |
46
|
|
|
*/ |
47
|
|
|
public function setContentFromPos($content) |
48
|
|
|
{ |
49
|
|
|
$this->content = |
50
|
|
|
substr($this->content, 0, $this->pos) . $content; |
51
|
|
|
} |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* Add content to the packet |
55
|
|
|
* |
56
|
|
|
* @param string $content |
57
|
|
|
*/ |
58
|
|
|
public function addContent($content) |
59
|
|
|
{ |
60
|
|
|
if ($content instanceof Packet) { |
61
|
|
|
$content = $content->getContent(); |
62
|
|
|
} |
63
|
|
|
|
64
|
|
|
$before = substr($this->content, 0, $this->pos); |
65
|
|
|
$after = substr($this->content, $this->pos, $this->getLength()); |
66
|
|
|
$str = $before . $content . $after; |
67
|
|
|
|
68
|
|
|
$this->content = $str; |
69
|
|
|
$this->pos += strlen($content); |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* @param string $content |
74
|
|
|
*/ |
75
|
|
|
public function pushContent($content) |
76
|
|
|
{ |
77
|
|
|
$this->content = $content . $this->content; |
78
|
|
|
|
79
|
|
|
return $this; |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* Get content |
84
|
|
|
* |
85
|
|
|
* @return string |
86
|
|
|
*/ |
87
|
|
|
public function __toString() |
88
|
|
|
{ |
89
|
|
|
return $this->content; |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* Get length of packet content |
94
|
|
|
* |
95
|
|
|
* @return int |
96
|
|
|
*/ |
97
|
|
|
public function getLength() |
98
|
|
|
{ |
99
|
|
|
return strlen($this->content); |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
public function key() |
103
|
|
|
{ |
104
|
|
|
return $this->pos; |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* @param integer $pos |
109
|
|
|
*/ |
110
|
|
|
public function setPos($pos) |
111
|
|
|
{ |
112
|
|
|
$this->pos = $pos; |
113
|
|
|
return $this; |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
public function rewind() |
117
|
|
|
{ |
118
|
|
|
$this->pos = 0; |
119
|
|
|
return $this; |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
public function getContent() |
123
|
|
|
{ |
124
|
|
|
if ($this->pos == 0) { |
125
|
|
|
return $this->content; |
126
|
|
|
} |
127
|
|
|
else { |
128
|
|
|
return substr($this->content, $this->pos); |
129
|
|
|
} |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
/** |
133
|
|
|
* Get a byte from the packet content |
134
|
|
|
* |
135
|
|
|
* @param bool $delByte If true, delete the byte that is return |
136
|
|
|
* @return byte |
137
|
|
|
* @throws EmptyPacketException |
138
|
|
|
*/ |
139
|
|
View Code Duplication |
public function getByte($delByte = true) |
|
|
|
|
140
|
|
|
{ |
141
|
|
|
$content = $this->getContent(); |
142
|
|
|
if (empty($content)) throw new EmptyPacketException(); |
143
|
|
|
|
144
|
|
|
// On récupère 1 byte |
145
|
|
|
$data = substr($content, 0, 1); |
146
|
|
|
$data = unpack('cval', $data); |
147
|
|
|
|
148
|
|
|
if ($delByte) $this->setContentFromPos(substr($this->getContent(), 1)); |
149
|
|
|
|
150
|
|
|
return $data['val']; |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
/** |
154
|
|
|
* Get a short from the packet content |
155
|
|
|
* |
156
|
|
|
* @param bool $delShort If true, delete the short that is return |
157
|
|
|
* @return short |
158
|
|
|
* @throws EmptyPacketException |
159
|
|
|
*/ |
160
|
|
View Code Duplication |
public function getShort($delShort = true) |
|
|
|
|
161
|
|
|
{ |
162
|
|
|
$content = $this->getContent(); |
163
|
|
|
if (empty($content)) throw new EmptyPacketException(); |
164
|
|
|
|
165
|
|
|
// On récupère les 2 bytes constituant l'entier court |
166
|
|
|
$data = substr($content, 0, 2); |
167
|
|
|
$data = unpack('sval', $data); |
168
|
|
|
|
169
|
|
|
if ($delShort) $this->setContentFromPos(substr($this->content, 2)); |
170
|
|
|
|
171
|
|
|
return $data['val']; |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
/** |
175
|
|
|
* Get a long from the packet content |
176
|
|
|
* |
177
|
|
|
* @param bool $delLong If true, delete the long that is return |
178
|
|
|
* @return long |
179
|
|
|
* @throws EmptyPacketException |
180
|
|
|
*/ |
181
|
|
View Code Duplication |
public function getLong($delLong = true) |
|
|
|
|
182
|
|
|
{ |
183
|
|
|
$content = $this->getContent(); |
184
|
|
|
if (empty($content)) throw new EmptyPacketException(); |
185
|
|
|
|
186
|
|
|
// On récupère les 4 bytes constituant l'entier long |
187
|
|
|
$data = substr($content, 0, 4); |
188
|
|
|
$data = unpack('lval', $data); |
189
|
|
|
|
190
|
|
|
if ($delLong) $this->setContentFromPos(substr($this->content, 4)); |
191
|
|
|
|
192
|
|
|
return $data['val']; |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
/** |
196
|
|
|
* Get a integer from the packet content |
197
|
|
|
* |
198
|
|
|
* @param bool $delInt If true, delete the integer that is return |
199
|
|
|
* @return integer |
200
|
|
|
* @throws EmptyPacketException |
201
|
|
|
*/ |
202
|
|
View Code Duplication |
public function getInt($delInt = true) |
|
|
|
|
203
|
|
|
{ |
204
|
|
|
$content = $this->getContent(); |
205
|
|
|
if (empty($content)) throw new EmptyPacketException(); |
206
|
|
|
|
207
|
|
|
// On récupère les 4 bytes constituant l'entier |
208
|
|
|
$data = substr($content, 0, 4); |
209
|
|
|
$data = unpack('ival', $data); |
210
|
|
|
|
211
|
|
|
if ($delInt) $this->setContentFromPos(substr($this->content, 4)); |
212
|
|
|
|
213
|
|
|
return $data['val']; |
214
|
|
|
} |
215
|
|
|
|
216
|
|
|
/** |
217
|
|
|
* Get a float from the packet content |
218
|
|
|
* |
219
|
|
|
* @param bool $delFloat If true, delete the float that is return |
220
|
|
|
* @return float |
221
|
|
|
* @throws EmptyPacketException |
222
|
|
|
*/ |
223
|
|
View Code Duplication |
public function getFloat($delFloat = true) |
|
|
|
|
224
|
|
|
{ |
225
|
|
|
$content = $this->getContent(); |
226
|
|
|
if (empty($content)) throw new EmptyPacketException(); |
227
|
|
|
|
228
|
|
|
// On récupère les 4 bytes constituant l'entier |
229
|
|
|
$data = substr($content, 0, 4); |
230
|
|
|
$data = unpack('fval', $data); |
231
|
|
|
|
232
|
|
|
if ($delFloat) $this->setContentFromPos(substr($this->content, 4)); |
233
|
|
|
|
234
|
|
|
return $data['val']; |
235
|
|
|
} |
236
|
|
|
|
237
|
|
|
/** |
238
|
|
|
* Get the first string inside the packet content |
239
|
|
|
* |
240
|
|
|
* @param bool $delString If true, delete the string that is return |
241
|
|
|
* @return string |
242
|
|
|
* @throws EmptyPacketException |
243
|
|
|
*/ |
244
|
|
|
public function getString($delString = true) |
245
|
|
|
{ |
246
|
|
|
$content = $this->getContent(); |
247
|
|
|
if (empty($content)) throw new EmptyPacketException(); |
248
|
|
|
|
249
|
|
|
// On recherche la première occurence du char 0x0 signant la fin |
250
|
|
|
$string = strstr($content, "\0", true); |
251
|
|
|
|
252
|
|
|
if ($delString) { |
253
|
|
|
$pos = strpos($content, "\0"); |
254
|
|
|
$this->setContentFromPos(substr($this->content, $this->pos+$pos+1)); |
255
|
|
|
} |
256
|
|
|
|
257
|
|
|
return $string; |
258
|
|
|
} |
259
|
|
|
|
260
|
|
|
/** |
261
|
|
|
* Extract all vars depending on type specified |
262
|
|
|
* |
263
|
|
|
* @param array $vars |
264
|
|
|
* @return array |
265
|
|
|
*/ |
266
|
|
|
public function extract(array $vars) |
267
|
|
|
{ |
268
|
|
|
$return = array(); |
269
|
|
|
|
270
|
|
|
foreach ($vars AS $varName => $varType) { |
271
|
|
|
$method = 'get' . ucfirst($varType); |
272
|
|
|
$return[$varName] = $this->$method(); |
273
|
|
|
} |
274
|
|
|
|
275
|
|
|
return $return; |
276
|
|
|
} |
277
|
|
|
|
278
|
|
|
public function isEmpty() |
279
|
|
|
{ |
280
|
|
|
return empty($this->content); |
281
|
|
|
} |
282
|
|
|
} |
283
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.