诸暨麻将添加redis
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

205 lines
7.2 KiB

  1. #include "stdafx.h"
  2. #include <stdint.h>
  3. #include "WebSocket.h"
  4. #include "utility/SHA1.h"
  5. #include "utility/Base64.h"
  6. //#include "Logger.h"
  7. namespace zl {
  8. namespace net {
  9. namespace ws {
  10. uint16_t ntoh16(uint16_t x) {
  11. return ((x & 0x00ff) << 8) | ((x & 0xff00) >> 8);
  12. }
  13. uint16_t hton16(uint16_t x) {
  14. return ((x & 0x00ff) << 8) | ((x & 0xff00) >> 8);
  15. }
  16. uint64_t ntoh64(uint64_t x) {
  17. return (x >> 56) |
  18. ((x << 40) & 0x00ff000000000000LL) |
  19. ((x << 24) & 0x0000ff0000000000LL) |
  20. ((x << 8) & 0x000000ff00000000LL) |
  21. ((x >> 8) & 0x00000000ff000000LL) |
  22. ((x >> 24) & 0x0000000000ff0000LL) |
  23. ((x >> 40) & 0x000000000000ff00LL) |
  24. (x << 56);
  25. }
  26. uint64_t hton64(uint64_t x) {
  27. return (x >> 56) |
  28. ((x << 40) & 0x00ff000000000000LL) |
  29. ((x << 24) & 0x0000ff0000000000LL) |
  30. ((x << 8) & 0x000000ff00000000LL) |
  31. ((x >> 8) & 0x00000000ff000000LL) |
  32. ((x >> 24) & 0x0000000000ff0000LL) |
  33. ((x >> 40) & 0x000000000000ff00LL) |
  34. (x << 56);
  35. }
  36. std::string makeHandshakeResponse(const char* seckey, std::string protocol) {
  37. std::string answer("");
  38. answer += "HTTP/1.1 101 Switching Protocols\r\n";
  39. answer += "Upgrade: WebSocket\r\n";
  40. answer += "Connection: Upgrade\r\n";
  41. //answer += "Sec-WebSocket-Version: 13\r\n";
  42. answer += "Sec-WebSocket-Protocol:" + protocol + "\r\n";
  43. if (seckey) {
  44. std::string key(seckey);
  45. key += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
  46. char shakey[20] = { 0 };
  47. zl::util::SHA1 sha1;
  48. sha1.update(key);
  49. sha1.final(shakey);
  50. //LOG_WARN("get SHA1 : %s, %s", key.c_str(), shakey);
  51. key = zl::util::base64Encode(shakey, 20);
  52. //LOG_WARN("get base64 : %s", key.c_str());
  53. answer += ("Sec-WebSocket-Accept: " + key + "\r\n");
  54. }
  55. answer += "\r\n";
  56. return answer;
  57. }
  58. /*
  59. 0 1 2 3
  60. 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  61. +-+-+-+-+-------+-+-------------+-------------------------------+
  62. |F|R|R|R| opcode|M| Payload len | Extended payload length |
  63. |I|S|S|S| (4) |A| (7) | (16/64) |
  64. |N|V|V|V| |S| | (if payload len==126/127) |
  65. | |1|2|3| |K| | |
  66. +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
  67. | Extended payload length continued, if payload len == 127 |
  68. + - - - - - - - - - - - - - - - +-------------------------------+
  69. | |Masking-key, if MASK set to 1 |
  70. +-------------------------------+-------------------------------+
  71. | Masking-key (continued) | Payload Data |
  72. +-------------------------------- - - - - - - - - - - - - - - - +
  73. : Payload Data continued ... :
  74. + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
  75. | Payload Data continued ... |
  76. +---------------------------------------------------------------+
  77. opcode:
  78. * %x0 denotes a continuation frame
  79. * %x1 denotes a text frame
  80. * %x2 denotes a binary frame
  81. * %x3-7 are reserved for further non-control frames
  82. * %x8 denotes a connection close
  83. * %x9 denotes a ping
  84. * %xA denotes a pong
  85. * %xB-F are reserved for further control frames
  86. Payload length: 7 bits, 7+16 bits, or 7+64 bits
  87. Masking-key: 0 or 4 bytes
  88. */
  89. WsFrameType decodeFrame(const char* inbuf, int inlength, char* outbuf, int* outlen, int* frameSize) {
  90. if (inlength < 3) return WS_INCOMPLETE_FRAME;
  91. const unsigned char* inp = (const unsigned char*)(inbuf);
  92. unsigned char msg_opcode = inp[0] & 0x0F;
  93. unsigned char msg_fin = (inp[0] >> 7) & 0x01;
  94. unsigned char msg_masked = (inp[1] >> 7) & 0x01;
  95. if (msg_fin == 0) {
  96. return WS_ERROR_FRAME;
  97. }
  98. int payload_length = 0;
  99. int pos = 2;
  100. int length_field = inp[1] & (~0x80);
  101. unsigned int mask = 0;
  102. if (length_field <= PAYLOAD_SIZE_BASIC) {
  103. payload_length = length_field;
  104. }
  105. else if (length_field == 126) { //msglen is 16bit!
  106. uint16_t tmp16 = 0;
  107. memcpy(&tmp16, inp + 2, 2);
  108. payload_length = ntoh16(tmp16);
  109. //payload_length = inp[2] + (inp[3] << 8);
  110. pos += 2;
  111. }
  112. else if (length_field == 127) { //msglen is 64bit!
  113. uint64_t tmp64 = 0;
  114. memcpy(&tmp64, inp + 2, 8);
  115. payload_length = ntoh64(tmp64);
  116. //payload_length = inp[2] + (inp[3] << 8);
  117. pos += 8;
  118. }
  119. int frameLength = payload_length + pos;
  120. if (msg_masked == true) {
  121. frameLength += 4;
  122. }
  123. if (inlength < frameLength) {
  124. //printf("warn: inlengh<frameLength\n");
  125. return WS_INCOMPLETE_FRAME;
  126. }
  127. else if (inlength>frameLength) {
  128. //printf("warn: inlengh>frameLength:%d>%d\n", inlength, frameLength);
  129. }
  130. //else if (payload_length >(int)outbuf->size())
  131. //{
  132. // outbuf->resize(payload_length);
  133. //}
  134. if (msg_masked&&payload_length>0) {
  135. mask = *((unsigned int*)(inp + pos));
  136. pos += 4;
  137. memcpy(outbuf, (void*)(inp + pos), payload_length);
  138. // unmask data:
  139. char* c = outbuf;
  140. for (int i = 0; i < payload_length; i++) {
  141. c[i] = c[i] ^ ((unsigned char*)(&mask))[i % 4];
  142. }
  143. }
  144. *frameSize = frameLength;
  145. *outlen = payload_length;
  146. // (*outbuf)[payload_length] = 0;
  147. if (msg_opcode == 0x0) return (msg_fin) ? WS_TEXT_FRAME : WS_INCOMPLETE_TEXT_FRAME; // continuation frame ?
  148. if (msg_opcode == 0x1) return (msg_fin) ? WS_TEXT_FRAME : WS_INCOMPLETE_TEXT_FRAME;
  149. if (msg_opcode == 0x2) return (msg_fin) ? WS_BINARY_FRAME : WS_INCOMPLETE_BINARY_FRAME;
  150. if (msg_opcode == 0x8) return WS_CLOSE_FRAME;
  151. if (msg_opcode == 0x9) return WS_PING_FRAME;
  152. if (msg_opcode == 0xA) return WS_PONG_FRAME;
  153. return WS_ERROR_FRAME;
  154. }
  155. int encodeFrame(WsFrameType frame_type, const char* msg, int msg_length, char* outbuf, int bufsize) {
  156. //std::cout << "makeFrame : " << frame_type << "\t" << msg << "\t" << msg_length << "\n";
  157. int pos = 0;
  158. int size = msg_length;
  159. outbuf[pos++] = (unsigned char)frame_type; // text frame
  160. if (size <= PAYLOAD_SIZE_BASIC) { // 125
  161. outbuf[pos++] = size;
  162. }
  163. else if (size <= PAYLOAD_SIZE_EXTENDED) { // 65535
  164. outbuf[pos++] = 126; //16 bit length
  165. outbuf[pos++] = (size >> 8) & 0xFF; // rightmost first
  166. outbuf[pos++] = size & 0xFF;
  167. }
  168. else { // >2^16-1
  169. outbuf[pos++] = 127; //64 bit length
  170. // write 8 bytes length (significant first)
  171. // since msg_length is int it can be no longer than 4 bytes = 2^32-1
  172. // padd zeroes for the first 4 bytes
  173. for (int i = 3; i >= 0; i--) {
  174. outbuf[pos++] = 0;
  175. }
  176. // write the actual 32bit msg_length in the next 4 bytes
  177. for (int i = 3; i >= 0; i--) {
  178. outbuf[pos++] = ((size >> 8 * i) & 0xFF);
  179. }
  180. }
  181. //fix by xujialong Êý¾Ý³¤¶È¼ì²é
  182. if (size > 0 && (size + pos)<bufsize) {
  183. memcpy((void*)(outbuf + pos), msg, size);
  184. }
  185. return (size + pos);
  186. }
  187. } // namespace zl { namespace net { namespace ws {
  188. }
  189. }