1
0

unpack.c 6.1 KB

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