1
0

websocket_parser.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. #include "websocket_parser.h"
  2. #include <assert.h>
  3. #include <string.h>
  4. #ifdef assert
  5. # define assertFalse(msg) assert(0 && msg)
  6. #else
  7. # define assertFalse(msg)
  8. #endif
  9. #define SET_STATE(V) parser->state = V
  10. #define HAS_DATA() (p < end )
  11. #define CC (*p)
  12. #define GET_NPARSED() ( (p == end) ? len : (p - data) )
  13. #define NOTIFY_CB(FOR) \
  14. do { \
  15. if (settings->on_##FOR) { \
  16. if (settings->on_##FOR(parser) != 0) { \
  17. return GET_NPARSED(); \
  18. } \
  19. } \
  20. } while (0)
  21. #define EMIT_DATA_CB(FOR, ptr, len) \
  22. do { \
  23. if (settings->on_##FOR) { \
  24. if (settings->on_##FOR(parser, ptr, len) != 0) { \
  25. return GET_NPARSED(); \
  26. } \
  27. } \
  28. } while (0)
  29. enum state {
  30. s_start,
  31. s_head,
  32. s_length,
  33. s_mask,
  34. s_body,
  35. };
  36. void websocket_parser_init(websocket_parser * parser) {
  37. void *data = parser->data; /* preserve application data */
  38. memset(parser, 0, sizeof(*parser));
  39. parser->data = data;
  40. parser->state = s_start;
  41. }
  42. void websocket_parser_settings_init(websocket_parser_settings *settings) {
  43. memset(settings, 0, sizeof(*settings));
  44. }
  45. size_t websocket_parser_execute(websocket_parser *parser, const websocket_parser_settings *settings, const char *data, size_t len) {
  46. const char * p;
  47. const char * end = data + len;
  48. size_t frame_offset = 0;
  49. for(p = data; p != end; p++) {
  50. switch(parser->state) {
  51. case s_start:
  52. parser->offset = 0;
  53. parser->length = 0;
  54. parser->mask_offset = 0;
  55. parser->flags = (websocket_flags) (CC & WS_OP_MASK);
  56. if(CC & (1<<7)) {
  57. parser->flags |= WS_FIN;
  58. }
  59. SET_STATE(s_head);
  60. frame_offset++;
  61. break;
  62. case s_head:
  63. parser->length = (size_t)CC & 0x7F;
  64. if(CC & 0x80) {
  65. parser->flags |= WS_HAS_MASK;
  66. }
  67. if(parser->length >= 126) {
  68. if(parser->length == 127) {
  69. parser->require = 8;
  70. } else {
  71. parser->require = 2;
  72. }
  73. parser->length = 0;
  74. SET_STATE(s_length);
  75. } else if (parser->flags & WS_HAS_MASK) {
  76. SET_STATE(s_mask);
  77. parser->require = 4;
  78. } else if (parser->length) {
  79. SET_STATE(s_body);
  80. parser->require = parser->length;
  81. NOTIFY_CB(frame_header);
  82. } else {
  83. SET_STATE(s_start);
  84. NOTIFY_CB(frame_header);
  85. NOTIFY_CB(frame_end);
  86. }
  87. frame_offset++;
  88. break;
  89. case s_length:
  90. while(HAS_DATA() && parser->require) {
  91. parser->length <<= 8;
  92. parser->length |= (unsigned char)CC;
  93. parser->require--;
  94. frame_offset++;
  95. p++;
  96. }
  97. p--;
  98. if(!parser->require) {
  99. if (parser->flags & WS_HAS_MASK) {
  100. SET_STATE(s_mask);
  101. parser->require = 4;
  102. } else if (parser->length) {
  103. SET_STATE(s_body);
  104. parser->require = parser->length;
  105. NOTIFY_CB(frame_header);
  106. } else {
  107. SET_STATE(s_start);
  108. NOTIFY_CB(frame_header);
  109. NOTIFY_CB(frame_end);
  110. }
  111. }
  112. break;
  113. case s_mask:
  114. while(HAS_DATA() && parser->require) {
  115. parser->mask[4 - parser->require--] = CC;
  116. frame_offset++;
  117. p++;
  118. }
  119. p--;
  120. if(!parser->require) {
  121. if(parser->length) {
  122. SET_STATE(s_body);
  123. parser->require = parser->length;
  124. NOTIFY_CB(frame_header);
  125. } else {
  126. SET_STATE(s_start);
  127. NOTIFY_CB(frame_header);
  128. NOTIFY_CB(frame_end);
  129. }
  130. }
  131. break;
  132. case s_body:
  133. if(parser->require) {
  134. if(p + parser->require <= end) {
  135. EMIT_DATA_CB(frame_body, p, parser->require);
  136. p += parser->require;
  137. parser->require = 0;
  138. frame_offset = p - data;
  139. } else {
  140. EMIT_DATA_CB(frame_body, p, end - p);
  141. parser->require -= end - p;
  142. p = end;
  143. parser->offset += p - data - frame_offset;
  144. frame_offset = 0;
  145. }
  146. p--;
  147. }
  148. if(!parser->require) {
  149. NOTIFY_CB(frame_end);
  150. SET_STATE(s_start);
  151. }
  152. break;
  153. default:
  154. assertFalse("Unreachable case");
  155. }
  156. }
  157. return GET_NPARSED();
  158. }
  159. void websocket_parser_decode(char * dst, const char * src, size_t len, websocket_parser * parser) {
  160. size_t i = 0;
  161. for(; i < len; i++) {
  162. dst[i] = src[i] ^ parser->mask[(i + parser->mask_offset) % 4];
  163. }
  164. parser->mask_offset = (uint8_t) ((i + parser->mask_offset) % 4);
  165. }
  166. uint8_t websocket_decode(char * dst, const char * src, size_t len, const char mask[4], uint8_t mask_offset) {
  167. size_t i = 0;
  168. for(; i < len; i++) {
  169. dst[i] = src[i] ^ mask[(i + mask_offset) % 4];
  170. }
  171. return (uint8_t) ((i + mask_offset) % 4);
  172. }
  173. size_t websocket_calc_frame_size(websocket_flags flags, size_t data_len) {
  174. size_t size = data_len + 2; // body + 2 bytes of head
  175. if(data_len >= 126) {
  176. if(data_len > 0xFFFF) {
  177. size += 8;
  178. } else {
  179. size += 2;
  180. }
  181. }
  182. if(flags & WS_HAS_MASK) {
  183. size += 4;
  184. }
  185. return size;
  186. }
  187. size_t websocket_build_frame(char * frame, websocket_flags flags, const char mask[4], const char * data, size_t data_len) {
  188. size_t body_offset = 0;
  189. frame[0] = 0;
  190. frame[1] = 0;
  191. if(flags & WS_FIN) {
  192. frame[0] = (char) (1 << 7);
  193. }
  194. frame[0] |= flags & WS_OP_MASK;
  195. if(flags & WS_HAS_MASK) {
  196. frame[1] = (char) (1 << 7);
  197. }
  198. if(data_len < 126) {
  199. frame[1] |= data_len;
  200. body_offset = 2;
  201. } else if(data_len <= 0xFFFF) {
  202. frame[1] |= 126;
  203. frame[2] = (char) (data_len >> 8);
  204. frame[3] = (char) (data_len & 0xFF);
  205. body_offset = 4;
  206. } else {
  207. frame[1] |= 127;
  208. frame[2] = (char) ((data_len >> 56) & 0xFF);
  209. frame[3] = (char) ((data_len >> 48) & 0xFF);
  210. frame[4] = (char) ((data_len >> 40) & 0xFF);
  211. frame[5] = (char) ((data_len >> 32) & 0xFF);
  212. frame[6] = (char) ((data_len >> 24) & 0xFF);
  213. frame[7] = (char) ((data_len >> 16) & 0xFF);
  214. frame[8] = (char) ((data_len >> 8) & 0xFF);
  215. frame[9] = (char) ((data_len) & 0xFF);
  216. body_offset = 10;
  217. }
  218. if(flags & WS_HAS_MASK) {
  219. if(mask != NULL) {
  220. memcpy(&frame[body_offset], mask, 4);
  221. }
  222. websocket_decode(&frame[body_offset + 4], data, data_len, &frame[body_offset], 0);
  223. body_offset += 4;
  224. } else {
  225. memcpy(&frame[body_offset], data, data_len);
  226. }
  227. return body_offset + data_len;
  228. }