| 1 /* $Id$ */ |
|
| 2 |
|
| 3 /* |
|
| 4 * (C) Copyright 2012 Tomek Wasilczyk <www.wasilczyk.pl> |
|
| 5 * |
|
| 6 * This program is free software; you can redistribute it and/or modify |
|
| 7 * it under the terms of the GNU Lesser General Public License Version |
|
| 8 * 2.1 as published by the Free Software Foundation. |
|
| 9 * |
|
| 10 * This program is distributed in the hope that it will be useful, |
|
| 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 13 * GNU Lesser General Public License for more details. |
|
| 14 * |
|
| 15 * You should have received a copy of the GNU Lesser General Public |
|
| 16 * License along with this program; if not, write to the Free Software |
|
| 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, |
|
| 18 * USA. |
|
| 19 */ |
|
| 20 |
|
| 21 /** |
|
| 22 * \file tvbuff.c |
|
| 23 * |
|
| 24 * \brief Bufor wspierający obsługę pakietów typu Type-Value(s) |
|
| 25 */ |
|
| 26 |
|
| 27 #include <stdlib.h> |
|
| 28 #include <string.h> |
|
| 29 |
|
| 30 #include "tvbuff.h" |
|
| 31 |
|
| 32 #include "internal.h" |
|
| 33 |
|
| 34 struct gg_tvbuff |
|
| 35 { |
|
| 36 const char *buffer; |
|
| 37 size_t length; |
|
| 38 size_t offset; |
|
| 39 int valid; |
|
| 40 }; |
|
| 41 |
|
| 42 /** |
|
| 43 * \internal Tworzy nową instancję bufora. |
|
| 44 * |
|
| 45 * \param buffer Bufor źródłowy; nie może być modyfikowany (w szczególności |
|
| 46 * zwalniany) przez cały okres korzystania z jego opakowanej wersji. |
|
| 47 * \param length Długość bufora źródłowego. |
|
| 48 * |
|
| 49 * \return Zaalokowane opakowanie bufora - musi być zwolnione przez free lub |
|
| 50 * gg_tvbuff_close. |
|
| 51 */ |
|
| 52 gg_tvbuff_t *gg_tvbuff_new(const char *buffer, size_t length) |
|
| 53 { |
|
| 54 gg_tvbuff_t *tvb; |
|
| 55 |
|
| 56 tvb = malloc(sizeof(gg_tvbuff_t)); |
|
| 57 if (tvb == NULL) |
|
| 58 return NULL; |
|
| 59 memset(tvb, 0, sizeof(gg_tvbuff_t)); |
|
| 60 |
|
| 61 if (buffer == NULL && length > 0) { |
|
| 62 gg_debug(GG_DEBUG_ERROR, "// gg_tvbuff_new() " |
|
| 63 "invalid arguments\n"); |
|
| 64 tvb->valid = 0; |
|
| 65 return tvb; |
|
| 66 } |
|
| 67 |
|
| 68 tvb->buffer = buffer; |
|
| 69 tvb->length = length; |
|
| 70 tvb->offset = 0; |
|
| 71 tvb->valid = 1; |
|
| 72 |
|
| 73 return tvb; |
|
| 74 } |
|
| 75 |
|
| 76 /** |
|
| 77 * \internal Zwalnia opakowanie bufora. Przed zwolnieniem sprawdza, czy |
|
| 78 * przeczytano go do końca. |
|
| 79 * |
|
| 80 * \param tvb Bufor. |
|
| 81 * |
|
| 82 * \return Wartość różna od 0, jeżeli bufor tuż przed zwolnieniem był oznaczony |
|
| 83 * jako prawidłowy |
|
| 84 */ |
|
| 85 int gg_tvbuff_close(gg_tvbuff_t *tvb) |
|
| 86 { |
|
| 87 int valid; |
|
| 88 |
|
| 89 gg_tvbuff_expected_eob(tvb); |
|
| 90 valid = gg_tvbuff_is_valid(tvb); |
|
| 91 free(tvb); |
|
| 92 |
|
| 93 return valid; |
|
| 94 } |
|
| 95 |
|
| 96 /** |
|
| 97 * \internal Sprawdza, czy wszystkie odczyty z bufora były prawidłowe. |
|
| 98 * |
|
| 99 * \param tvb Bufor. |
|
| 100 * |
|
| 101 * \return Wartość różna od 0, jeżeli wszystkie odczyty były prawidłowe. |
|
| 102 */ |
|
| 103 int gg_tvbuff_is_valid(const gg_tvbuff_t *tvb) |
|
| 104 { |
|
| 105 if (tvb == NULL) |
|
| 106 return 0; |
|
| 107 return tvb->valid; |
|
| 108 } |
|
| 109 |
|
| 110 /** |
|
| 111 * \internal Zwraca pozostałą do odczytania liczbę bajtów w buforze. |
|
| 112 * |
|
| 113 * \param tvb Bufor. |
|
| 114 * |
|
| 115 * \return Pozostała liczba bajtów do odczytania. |
|
| 116 */ |
|
| 117 size_t gg_tvbuff_get_remaining(const gg_tvbuff_t *tvb) |
|
| 118 { |
|
| 119 if (!gg_tvbuff_is_valid(tvb)) |
|
| 120 return 0; |
|
| 121 |
|
| 122 return tvb->length - tvb->offset; |
|
| 123 } |
|
| 124 |
|
| 125 /** |
|
| 126 * \internal Sprawdza, czy w buforze pozostała określona liczba bajtów do |
|
| 127 * odczytania. Jeżeli nie została - oznacza bufor jako nieprawidłowy. |
|
| 128 * |
|
| 129 * \param tvb Bufor. |
|
| 130 * \param length Ilość bajtów do odczytania. |
|
| 131 * |
|
| 132 * \return Wartość różna od 0, jeżeli można odczytać podaną liczbę bajtów. |
|
| 133 */ |
|
| 134 int gg_tvbuff_have_remaining(gg_tvbuff_t *tvb, size_t length) |
|
| 135 { |
|
| 136 if (!gg_tvbuff_is_valid(tvb)) |
|
| 137 return 0; |
|
| 138 |
|
| 139 if (gg_tvbuff_get_remaining(tvb) >= length) |
|
| 140 return 1; |
|
| 141 |
|
| 142 gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_have_remaining() failed " |
|
| 143 "(%" GG_SIZE_FMT " < %" GG_SIZE_FMT ")\n", |
|
| 144 gg_tvbuff_get_remaining(tvb), length); |
|
| 145 tvb->valid = 0; |
|
| 146 return 0; |
|
| 147 } |
|
| 148 |
|
| 149 /** |
|
| 150 * \internal Pomija określoną liczbę bajtów w buforze. Jeżeli w wyniku ich |
|
| 151 * pominięcia wyjdzie poza zakres, oznacza bufor jako nieprawidłowy. |
|
| 152 * |
|
| 153 * \param tvb Bufor |
|
| 154 * \param amount Liczba bajtów do pominięcia |
|
| 155 */ |
|
| 156 void gg_tvbuff_skip(gg_tvbuff_t *tvb, size_t amount) |
|
| 157 { |
|
| 158 if (!gg_tvbuff_is_valid(tvb)) |
|
| 159 return; |
|
| 160 |
|
| 161 if (tvb->offset + amount > tvb->length) { |
|
| 162 gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_skip() failed\n"); |
|
| 163 tvb->valid = 0; |
|
| 164 return; |
|
| 165 } |
|
| 166 |
|
| 167 tvb->offset += amount; |
|
| 168 } |
|
| 169 |
|
| 170 /** |
|
| 171 * \internal Cofa się o określoną liczbę bajtów w buforze. Jeżeli cofnie przed |
|
| 172 * pierwszy znak, oznacza bufor jako nieprawidłowy. |
|
| 173 * |
|
| 174 * \param tvb Bufor |
|
| 175 * \param amount Liczba bajtów do cofnięcia |
|
| 176 */ |
|
| 177 void gg_tvbuff_rewind(gg_tvbuff_t *tvb, size_t amount) |
|
| 178 { |
|
| 179 if (!gg_tvbuff_is_valid(tvb)) |
|
| 180 return; |
|
| 181 |
|
| 182 if (tvb->offset < amount) { |
|
| 183 gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_rewind() failed\n"); |
|
| 184 tvb->valid = 0; |
|
| 185 return; |
|
| 186 } |
|
| 187 |
|
| 188 tvb->offset -= amount; |
|
| 189 } |
|
| 190 |
|
| 191 /** |
|
| 192 * \internal Sprawdza, czy pod aktualną pozycją w buforze występuje podana |
|
| 193 * wartość. Jeżeli tak, przesuwa aktualną pozycję do przodu. |
|
| 194 * |
|
| 195 * \param tvb Bufor. |
|
| 196 * \param value Wartość do sprawdzenia |
|
| 197 * |
|
| 198 * \return Wartość różna od 0, jeżeli znaleziono podaną wartość. |
|
| 199 */ |
|
| 200 int gg_tvbuff_match(gg_tvbuff_t *tvb, uint8_t value) |
|
| 201 { |
|
| 202 if (!gg_tvbuff_is_valid(tvb)) |
|
| 203 return 0; |
|
| 204 |
|
| 205 if (!gg_tvbuff_have_remaining(tvb, 1)) { |
|
| 206 gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_match() failed\n"); |
|
| 207 return 0; |
|
| 208 } |
|
| 209 |
|
| 210 if (tvb->buffer[tvb->offset] != value) |
|
| 211 return 0; |
|
| 212 |
|
| 213 tvb->offset++; |
|
| 214 return 1; |
|
| 215 } |
|
| 216 |
|
| 217 /** |
|
| 218 * \internal Odczytuje z bufora liczbę 8-bitową. |
|
| 219 * |
|
| 220 * \param tvb Bufor |
|
| 221 * |
|
| 222 * \return Odczytana liczba |
|
| 223 */ |
|
| 224 uint8_t gg_tvbuff_read_uint8(gg_tvbuff_t *tvb) |
|
| 225 { |
|
| 226 if (!gg_tvbuff_is_valid(tvb)) |
|
| 227 return 0; |
|
| 228 |
|
| 229 if (!gg_tvbuff_have_remaining(tvb, 1)) { |
|
| 230 gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_read_uint8() " |
|
| 231 "failed at %" GG_SIZE_FMT "\n", tvb->offset); |
|
| 232 return 0; |
|
| 233 } |
|
| 234 |
|
| 235 return tvb->buffer[tvb->offset++]; |
|
| 236 } |
|
| 237 |
|
| 238 /** |
|
| 239 * \internal Odczytuje z bufora liczbę 32-bitową. |
|
| 240 * |
|
| 241 * \param tvb Bufor |
|
| 242 * |
|
| 243 * \return Odczytana liczba |
|
| 244 */ |
|
| 245 uint32_t gg_tvbuff_read_uint32(gg_tvbuff_t *tvb) |
|
| 246 { |
|
| 247 uint32_t val; |
|
| 248 |
|
| 249 if (!gg_tvbuff_is_valid(tvb)) |
|
| 250 return 0; |
|
| 251 |
|
| 252 if (!gg_tvbuff_have_remaining(tvb, 4)) { |
|
| 253 gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_read_uint32() " |
|
| 254 "failed at %" GG_SIZE_FMT "\n", tvb->offset); |
|
| 255 return 0; |
|
| 256 } |
|
| 257 |
|
| 258 memcpy(&val, tvb->buffer + tvb->offset, 4); |
|
| 259 tvb->offset += 4; |
|
| 260 |
|
| 261 return gg_fix32(val); |
|
| 262 } |
|
| 263 |
|
| 264 /** |
|
| 265 * \internal Odczytuje z bufora liczbę 64-bitową. |
|
| 266 * |
|
| 267 * \param tvb Bufor |
|
| 268 * |
|
| 269 * \return Odczytana liczba |
|
| 270 */ |
|
| 271 uint64_t gg_tvbuff_read_uint64(gg_tvbuff_t *tvb) |
|
| 272 { |
|
| 273 uint64_t val; |
|
| 274 |
|
| 275 if (!gg_tvbuff_is_valid(tvb)) |
|
| 276 return 0; |
|
| 277 |
|
| 278 if (!gg_tvbuff_have_remaining(tvb, 8)) { |
|
| 279 gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_read_uint64() " |
|
| 280 "failed at %" GG_SIZE_FMT "\n", tvb->offset); |
|
| 281 return 0; |
|
| 282 } |
|
| 283 |
|
| 284 memcpy(&val, tvb->buffer + tvb->offset, 8); |
|
| 285 tvb->offset += 8; |
|
| 286 |
|
| 287 return gg_fix64(val); |
|
| 288 } |
|
| 289 |
|
| 290 /** |
|
| 291 * \internal Odczytuje z bufora skompresowaną liczbę całkowitą. |
|
| 292 * Liczba taka może być zapisana w buforze na 1-9 bajtach, w zależności |
|
| 293 * od jej wartości. |
|
| 294 * |
|
| 295 * Skompresowana liczba jest zapisywana od najmłodszego bajtu do najstarszego |
|
| 296 * niezerowego. W każdym bajcie zapisuje się bit sterujący (równy 0, jeżeli jest |
|
| 297 * to ostatni bajt do przeczytania, lub 1 w p.p.) oraz 7 kolejnych bitów z |
|
| 298 * kompresowanej liczby. |
|
| 299 * |
|
| 300 * Przykładowo, liczby mniejsze od 128 (1000.0000b) są zapisywane dokładnie tak, |
|
| 301 * jak uint8_t; a np. 12345 (0011.0000.0011.1001b) zostanie zapisana jako 0x60B9 |
|
| 302 * (0110.0000.1011.1001b). |
|
| 303 * |
|
| 304 * \param tvb Bufor. |
|
| 305 * |
|
| 306 * \return Odczytana liczba. |
|
| 307 */ |
|
| 308 uint64_t gg_tvbuff_read_packed_uint(gg_tvbuff_t *tvb) |
|
| 309 { |
|
| 310 uint64_t val = 0; |
|
| 311 int i, val_len = 0; |
|
| 312 |
|
| 313 if (!gg_tvbuff_is_valid(tvb)) |
|
| 314 return 0; |
|
| 315 |
|
| 316 while (gg_tvbuff_have_remaining(tvb, 1)) { |
|
| 317 val_len++; |
|
| 318 if (!(gg_tvbuff_read_uint8(tvb) & 0x80)) |
|
| 319 break; |
|
| 320 } |
|
| 321 |
|
| 322 if (!gg_tvbuff_is_valid(tvb)) { |
|
| 323 gg_debug(GG_DEBUG_WARNING, |
|
| 324 "// gg_tvbuff_read_packed_uint() failed\n"); |
|
| 325 return 0; |
|
| 326 } |
|
| 327 |
|
| 328 if (val_len > 9) { |
|
| 329 gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_read_packed_uint() " |
|
| 330 "packed uint size too big: %d\n", val_len); |
|
| 331 tvb->valid = 0; |
|
| 332 return 0; |
|
| 333 } |
|
| 334 |
|
| 335 for (i = 1; i <= val_len; i++) { |
|
| 336 uint64_t old_val = val; |
|
| 337 val <<= 7; |
|
| 338 if (old_val != (val >> 7)) { |
|
| 339 gg_debug(GG_DEBUG_WARNING, |
|
| 340 "// gg_tvbuff_read_packed_uint() overflow\n"); |
|
| 341 tvb->valid = 0; |
|
| 342 return 0; |
|
| 343 } |
|
| 344 val |= (uint8_t)(tvb->buffer[tvb->offset - i] & ~0x80); |
|
| 345 } |
|
| 346 |
|
| 347 return val; |
|
| 348 } |
|
| 349 |
|
| 350 /** |
|
| 351 * \internal Odczytuje z bufora podciąg bez kopiowania danych. |
|
| 352 * |
|
| 353 * \param tvb Bufor źródłowy |
|
| 354 * \param length Ilość bajtów do odczytania |
|
| 355 * |
|
| 356 * \return Wskaźnik na początek odczytanych danych, lub NULL w przypadku |
|
| 357 * niepowodzenia |
|
| 358 */ |
|
| 359 const char *gg_tvbuff_read_buff(gg_tvbuff_t *tvb, size_t length) |
|
| 360 { |
|
| 361 const char *buff; |
|
| 362 |
|
| 363 if (!gg_tvbuff_is_valid(tvb)) |
|
| 364 return NULL; |
|
| 365 |
|
| 366 if (!gg_tvbuff_have_remaining(tvb, length)) { |
|
| 367 gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_get_buff() " |
|
| 368 "failed at %" GG_SIZE_FMT ":%" GG_SIZE_FMT "\n", |
|
| 369 tvb->offset, length); |
|
| 370 return NULL; |
|
| 371 } |
|
| 372 |
|
| 373 buff = tvb->buffer + tvb->offset; |
|
| 374 tvb->offset += length; |
|
| 375 return buff; |
|
| 376 } |
|
| 377 |
|
| 378 /** |
|
| 379 * \internal Odczytuje z bufora podciąg kopiując go do nowego obszaru pamięci. |
|
| 380 * |
|
| 381 * \param tvb Bufor źródłowy |
|
| 382 * \param buffer Bufor docelowy |
|
| 383 * \param length Ilość bajtów do odczytania |
|
| 384 */ |
|
| 385 void gg_tvbuff_read_buff_cpy(gg_tvbuff_t *tvb, char *buffer, size_t length) |
|
| 386 { |
|
| 387 if (!gg_tvbuff_is_valid(tvb)) |
|
| 388 return; |
|
| 389 |
|
| 390 if (!gg_tvbuff_have_remaining(tvb, length)) { |
|
| 391 gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_read_buff() " |
|
| 392 "failed at %" GG_SIZE_FMT ":%" GG_SIZE_FMT "\n", |
|
| 393 tvb->offset, length); |
|
| 394 return; |
|
| 395 } |
|
| 396 |
|
| 397 if (buffer == NULL && length > 0) { |
|
| 398 gg_debug(GG_DEBUG_ERROR, "// gg_tvbuff_new() " |
|
| 399 "invalid arguments\n"); |
|
| 400 tvb->valid = 0; |
|
| 401 return; |
|
| 402 } |
|
| 403 |
|
| 404 memcpy(buffer, tvb->buffer + tvb->offset, length); |
|
| 405 tvb->offset += length; |
|
| 406 } |
|
| 407 |
|
| 408 /** |
|
| 409 * \internal Odczytuje z bufora ciąg tekstowy (mogący zawierać dowolne znaki, |
|
| 410 * również \0) bez kopiowania danych. |
|
| 411 * |
|
| 412 * \param tvb Bufor źródłowy |
|
| 413 * \param length Zmienna, do której zostanie zapisana długość odczytanego ciągu |
|
| 414 * |
|
| 415 * \return Wskaźnik na początek odczytanych danych, lub NULL w przypadku |
|
| 416 * niepowodzenia |
|
| 417 */ |
|
| 418 const char *gg_tvbuff_read_str(gg_tvbuff_t *tvb, size_t *length) |
|
| 419 { |
|
| 420 size_t offset; |
|
| 421 uint32_t str_len; |
|
| 422 const char *str; |
|
| 423 |
|
| 424 if (!gg_tvbuff_is_valid(tvb)) |
|
| 425 return NULL; |
|
| 426 |
|
| 427 offset = tvb->offset; |
|
| 428 str_len = gg_tvbuff_read_packed_uint(tvb); |
|
| 429 if (!gg_tvbuff_is_valid(tvb) || |
|
| 430 !gg_tvbuff_have_remaining(tvb, str_len)) |
|
| 431 { |
|
| 432 gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_read_str() failed at " |
|
| 433 "%" GG_SIZE_FMT ":%d\n", offset, str_len); |
|
| 434 return NULL; |
|
| 435 } |
|
| 436 |
|
| 437 str = gg_tvbuff_read_buff(tvb, str_len); |
|
| 438 |
|
| 439 if (!gg_tvbuff_is_valid(tvb)) |
|
| 440 return NULL; |
|
| 441 |
|
| 442 if (length != NULL) |
|
| 443 *length = str_len; |
|
| 444 if (str_len == 0) |
|
| 445 return NULL; |
|
| 446 return str; |
|
| 447 } |
|
| 448 |
|
| 449 /** |
|
| 450 * \internal Odczytuje z bufora ciąg tekstowy (mogący zawierać dowolne znaki, |
|
| 451 * również \0) kopiując go do nowego obszaru pamięci. Zwrócony ciąg będzie |
|
| 452 * zawsze zakończony znakiem \0. |
|
| 453 * |
|
| 454 * \param tvb Bufor źródłowy |
|
| 455 * \param dst Zmienna, do której zostanie zapisany wskaźnik na odczytany ciąg. |
|
| 456 * Po użyciu, blok ten powinien zostać zwolniony za pomocą \c free() |
|
| 457 * |
|
| 458 * \return Wskaźnik na początek odczytanych danych, lub NULL w przypadku |
|
| 459 * niepowodzenia |
|
| 460 */ |
|
| 461 void gg_tvbuff_read_str_dup(gg_tvbuff_t *tvb, char **dst) |
|
| 462 { |
|
| 463 size_t offset; |
|
| 464 uint32_t str_len; |
|
| 465 char *str; |
|
| 466 |
|
| 467 if (!gg_tvbuff_is_valid(tvb)) |
|
| 468 return; |
|
| 469 |
|
| 470 offset = tvb->offset; |
|
| 471 str_len = gg_tvbuff_read_packed_uint(tvb); |
|
| 472 if (!gg_tvbuff_is_valid(tvb) || |
|
| 473 !gg_tvbuff_have_remaining(tvb, str_len)) |
|
| 474 { |
|
| 475 gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_read_str_dup() failed " |
|
| 476 "at %" GG_SIZE_FMT ":%d\n", offset, str_len); |
|
| 477 return; |
|
| 478 } |
|
| 479 |
|
| 480 str = malloc(str_len + 1); |
|
| 481 if (str == NULL) { |
|
| 482 gg_debug(GG_DEBUG_ERROR, "// gg_tvbuff_read_str_dup() " |
|
| 483 "not enough free memory: %d + 1\n", str_len); |
|
| 484 tvb->valid = 0; |
|
| 485 return; |
|
| 486 } |
|
| 487 |
|
| 488 gg_tvbuff_read_buff_cpy(tvb, str, str_len); |
|
| 489 str[str_len] = '\0'; |
|
| 490 |
|
| 491 if (*dst != NULL) { |
|
| 492 gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_read_str_dup() " |
|
| 493 "destination already filled, freeing it...\n"); |
|
| 494 free(*dst); |
|
| 495 } |
|
| 496 *dst = str; |
|
| 497 } |
|
| 498 |
|
| 499 /** |
|
| 500 * \internal Odczytuje z bufora identyfikator użytkownika. |
|
| 501 * |
|
| 502 * \param tvb Bufor |
|
| 503 * |
|
| 504 * \return Identyfikator użytkownika, lub 0 w przypadku niepowodzenia |
|
| 505 */ |
|
| 506 uin_t gg_tvbuff_read_uin(gg_tvbuff_t *tvb) |
|
| 507 { |
|
| 508 uin_t uin = 0; |
|
| 509 uint32_t uin_len, full_len; |
|
| 510 uint8_t uin_type; |
|
| 511 const char *raw; |
|
| 512 |
|
| 513 if (!gg_tvbuff_is_valid(tvb)) |
|
| 514 return 0; |
|
| 515 |
|
| 516 full_len = gg_tvbuff_read_packed_uint(tvb); |
|
| 517 uin_type = gg_tvbuff_read_uint8(tvb); |
|
| 518 uin_len = gg_tvbuff_read_uint8(tvb); |
|
| 519 |
|
| 520 if (!gg_tvbuff_is_valid(tvb)) |
|
| 521 return 0; |
|
| 522 |
|
| 523 if (full_len != uin_len + 2 || |
|
| 524 uin_type != 0 || |
|
| 525 uin_len > 10) |
|
| 526 { |
|
| 527 gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_read_uin() failed (1)\n"); |
|
| 528 tvb->valid = 0; |
|
| 529 return 0; |
|
| 530 } |
|
| 531 |
|
| 532 raw = gg_tvbuff_read_buff(tvb, uin_len); |
|
| 533 if (raw) |
|
| 534 uin = gg_str_to_uin(raw, uin_len); |
|
| 535 |
|
| 536 if (uin == 0) { |
|
| 537 gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_read_uin() failed (2)\n"); |
|
| 538 tvb->valid = 0; |
|
| 539 return 0; |
|
| 540 } |
|
| 541 |
|
| 542 return uin; |
|
| 543 } |
|
| 544 |
|
| 545 /** |
|
| 546 * \internal Odczytuje z bufora liczbę 8-bitową i porównuje z podaną. Jeżeli te |
|
| 547 * się różnią, zostaje wygenerowane ostrzeżenie. |
|
| 548 * |
|
| 549 * \param tvb Bufor |
|
| 550 * \param value Oczekiwana wartość |
|
| 551 */ |
|
| 552 void gg_tvbuff_expected_uint8(gg_tvbuff_t *tvb, uint8_t value) |
|
| 553 { |
|
| 554 uint8_t got; |
|
| 555 size_t offset; |
|
| 556 |
|
| 557 offset = tvb->offset; |
|
| 558 got = gg_tvbuff_read_uint8(tvb); |
|
| 559 if (!gg_tvbuff_is_valid(tvb)) |
|
| 560 return; |
|
| 561 |
|
| 562 if (got != value) |
|
| 563 gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_expected_uint8() " |
|
| 564 "expected %#02x, but %#02x found at %" GG_SIZE_FMT "\n", |
|
| 565 value, got, offset); |
|
| 566 } |
|
| 567 |
|
| 568 /** |
|
| 569 * \internal Odczytuje z bufora liczbę 32-bitową i porównuje z podaną. Jeżeli te |
|
| 570 * się różnią, zostaje wygenerowane ostrzeżenie. |
|
| 571 * |
|
| 572 * \param tvb Bufor |
|
| 573 * \param value Oczekiwana wartość |
|
| 574 */ |
|
| 575 void gg_tvbuff_expected_uint32(gg_tvbuff_t *tvb, uint32_t value) |
|
| 576 { |
|
| 577 uint32_t got; |
|
| 578 size_t offset; |
|
| 579 |
|
| 580 offset = tvb->offset; |
|
| 581 got = gg_tvbuff_read_uint32(tvb); |
|
| 582 if (!gg_tvbuff_is_valid(tvb)) |
|
| 583 return; |
|
| 584 |
|
| 585 if (got != value) |
|
| 586 gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_expected_uint32() " |
|
| 587 "expected %#08x, but %#08x found at %" GG_SIZE_FMT "\n", |
|
| 588 value, got, offset); |
|
| 589 } |
|
| 590 |
|
| 591 /** |
|
| 592 * \internal Oczekuje końca bufora. Jeżeli w buforze są jeszcze dane do |
|
| 593 * przeczytania, generuje ostrzeżenie. |
|
| 594 * |
|
| 595 * \param tvb Bufor. |
|
| 596 */ |
|
| 597 void gg_tvbuff_expected_eob(const gg_tvbuff_t *tvb) |
|
| 598 { |
|
| 599 if (!gg_tvbuff_is_valid(tvb)) |
|
| 600 return; |
|
| 601 |
|
| 602 if (gg_tvbuff_get_remaining(tvb) != 0) |
|
| 603 gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_expected_eob() " |
|
| 604 "unexpected %" GG_SIZE_FMT " bytes, first=%#02x\n", |
|
| 605 gg_tvbuff_get_remaining(tvb), |
|
| 606 tvb->buffer[tvb->offset]); |
|
| 607 } |
|