unpack.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. #include "unpack.h"
  2. #include "hevent.h"
  3. #include "herr.h"
  4. #include "hlog.h"
  5. #include "hmath.h"
  6. int hio_unpack(hio_t* io, void* buf, int readbytes) {
  7. unpack_setting_t* setting = io->unpack_setting;
  8. switch(setting->mode) {
  9. case UNPACK_BY_FIXED_LENGTH:
  10. return hio_unpack_by_fixed_length(io, buf, readbytes);
  11. case UNPACK_BY_DELIMITER:
  12. return hio_unpack_by_delimiter(io, buf, readbytes);
  13. case UNPACK_BY_LENGTH_FIELD:
  14. return hio_unpack_by_length_field(io, buf, readbytes);
  15. default:
  16. hio_read_cb(io, buf, readbytes);
  17. return readbytes;
  18. }
  19. }
  20. int hio_unpack_by_fixed_length(hio_t* io, void* buf, int readbytes) {
  21. const unsigned char* sp = (const unsigned char*)io->readbuf.base;
  22. assert(buf == sp + io->readbuf.offset);
  23. const unsigned char* ep = sp + io->readbuf.offset + readbytes;
  24. unpack_setting_t* setting = io->unpack_setting;
  25. int fixed_length = setting->fixed_length;
  26. assert(io->readbuf.len >= fixed_length);
  27. const unsigned char* p = sp;
  28. int remain = ep - p;
  29. int handled = 0;
  30. while (remain >= fixed_length) {
  31. hio_read_cb(io, (void*)p, fixed_length);
  32. handled += fixed_length;
  33. p += fixed_length;
  34. remain -= fixed_length;
  35. }
  36. io->readbuf.offset = remain;
  37. if (remain) {
  38. // [p, p+remain] => [base, base+remain]
  39. if (p != (unsigned char*)io->readbuf.base) {
  40. memmove(io->readbuf.base, p, remain);
  41. }
  42. }
  43. return handled;
  44. }
  45. int hio_unpack_by_delimiter(hio_t* io, void* buf, int readbytes) {
  46. const unsigned char* sp = (const unsigned char*)io->readbuf.base;
  47. assert(buf == sp + io->readbuf.offset);
  48. const unsigned char* ep = sp + io->readbuf.offset + readbytes;
  49. unpack_setting_t* setting = io->unpack_setting;
  50. unsigned char* delimiter = setting->delimiter;
  51. int delimiter_bytes = setting->delimiter_bytes;
  52. // [offset - package_eof_bytes + 1, offset + readbytes]
  53. const unsigned char* p = sp + io->readbuf.offset - delimiter_bytes + 1;
  54. if (p < sp) p = sp;
  55. int remain = ep - p;
  56. int handled = 0;
  57. int i = 0;
  58. while (remain >= delimiter_bytes) {
  59. for (i = 0; i < delimiter_bytes; ++i) {
  60. if (p[i] != delimiter[i]) {
  61. goto not_match;
  62. }
  63. }
  64. match:
  65. p += delimiter_bytes;
  66. remain -= delimiter_bytes;
  67. hio_read_cb(io, (void*)sp, p - sp);
  68. handled += p - sp;
  69. sp = p;
  70. continue;
  71. not_match:
  72. ++p;
  73. --remain;
  74. }
  75. remain = ep - sp;
  76. io->readbuf.offset = remain;
  77. if (remain) {
  78. // [sp, sp+remain] => [base, base+remain]
  79. if (sp != (unsigned char*)io->readbuf.base) {
  80. memmove(io->readbuf.base, sp, remain);
  81. }
  82. if (io->readbuf.offset == io->readbuf.len) {
  83. if (io->readbuf.len >= setting->package_max_length) {
  84. hloge("recv package over %d bytes!", (int)setting->package_max_length);
  85. io->error = ERR_OVER_LIMIT;
  86. hio_close(io);
  87. return -1;
  88. }
  89. io->readbuf.len = MIN(io->readbuf.len * 2, setting->package_max_length);
  90. io->readbuf.base = (char*)safe_realloc(io->readbuf.base, io->readbuf.len, io->readbuf.offset);
  91. }
  92. }
  93. return handled;
  94. }
  95. int hio_unpack_by_length_field(hio_t* io, void* buf, int readbytes) {
  96. const unsigned char* sp = (const unsigned char*)io->readbuf.base;
  97. assert(buf == sp + io->readbuf.offset);
  98. const unsigned char* ep = sp + io->readbuf.offset + readbytes;
  99. unpack_setting_t* setting = io->unpack_setting;
  100. const unsigned char* p = sp;
  101. int remain = ep - p;
  102. int handled = 0;
  103. unsigned int head_len = setting->body_offset;
  104. unsigned int body_len = 0;
  105. unsigned int package_len = head_len + body_len;
  106. const unsigned char* lp = NULL;
  107. while (remain >= setting->body_offset) {
  108. body_len = 0;
  109. lp = p + setting->length_field_offset;
  110. if (setting->length_field_coding == BIG_ENDIAN) {
  111. for (int i = 0; i < setting->length_field_bytes; ++i) {
  112. body_len = (body_len << 8) | (unsigned int)*lp++;
  113. }
  114. }
  115. else if (setting->length_field_coding == LITTLE_ENDIAN) {
  116. for (int i = 0; i < setting->length_field_bytes; ++i) {
  117. body_len |= ((unsigned int)*lp++) << (i * 8);
  118. }
  119. }
  120. else if (setting->length_field_coding == ENCODE_BY_VARINT) {
  121. int varint_bytes = ep - lp;
  122. body_len = varint_decode(lp, &varint_bytes);
  123. if (varint_bytes == 0) break;
  124. if (varint_bytes == -1) {
  125. hloge("varint is too big!");
  126. io->error = ERR_OVER_LIMIT;
  127. hio_close(io);
  128. return -1;
  129. }
  130. head_len = setting->body_offset + varint_bytes - setting->length_field_bytes;
  131. }
  132. package_len = head_len + body_len;
  133. if (remain >= package_len) {
  134. hio_read_cb(io, (void*)p, package_len);
  135. handled += package_len;
  136. p += package_len;
  137. remain -= package_len;
  138. } else {
  139. break;
  140. }
  141. }
  142. io->readbuf.offset = remain;
  143. if (remain) {
  144. // [p, p+remain] => [base, base+remain]
  145. if (p != (unsigned char*)io->readbuf.base) {
  146. memmove(io->readbuf.base, p, remain);
  147. }
  148. if (package_len > io->readbuf.len) {
  149. if (package_len > setting->package_max_length) {
  150. hloge("package length over %d bytes!", (int)setting->package_max_length);
  151. io->error = ERR_OVER_LIMIT;
  152. hio_close(io);
  153. return -1;
  154. }
  155. io->readbuf.len *= 2;
  156. io->readbuf.len = LIMIT(package_len, io->readbuf.len, setting->package_max_length);
  157. io->readbuf.base = (char*)safe_realloc(io->readbuf.base, io->readbuf.len, io->readbuf.offset);
  158. }
  159. }
  160. return handled;
  161. }