1
0

unpack.c 5.7 KB

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