1
0

WebSocketChannel.cpp 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. #include "WebSocketChannel.h"
  2. namespace hv {
  3. int WebSocketChannel::send(const char* buf, int len, enum ws_opcode opcode /* = WS_OPCODE_BINARY */, bool fin /* = true */) {
  4. int fragment = 0xFFFF; // 65535
  5. if (len > fragment) {
  6. return send(buf, len, fragment, opcode);
  7. }
  8. std::lock_guard<std::mutex> locker(mutex_);
  9. return sendFrame(buf, len, opcode, fin);
  10. }
  11. /*
  12. * websocket fragment
  13. * lock ->
  14. * sendFrame(p, fragment, opcode, false) ->
  15. * sendFrame(p, fragment, WS_OPCODE_CONTINUE, false) ->
  16. * ... ->
  17. * sendFrame(p, remain, WS_OPCODE_CONTINUE, true)
  18. * unlock
  19. *
  20. */
  21. int WebSocketChannel::send(const char* buf, int len, int fragment, enum ws_opcode opcode /* = WS_OPCODE_BINARY */) {
  22. std::lock_guard<std::mutex> locker(mutex_);
  23. if (len <= fragment) {
  24. return sendFrame(buf, len, opcode, true);
  25. }
  26. // first fragment
  27. int nsend = sendFrame(buf, fragment, opcode, false);
  28. if (nsend < 0) return nsend;
  29. const char* p = buf + fragment;
  30. int remain = len - fragment;
  31. while (remain > fragment) {
  32. nsend = sendFrame(p, fragment, WS_OPCODE_CONTINUE, false);
  33. if (nsend < 0) return nsend;
  34. p += fragment;
  35. remain -= fragment;
  36. }
  37. // last fragment
  38. nsend = sendFrame(p, remain, WS_OPCODE_CONTINUE, true);
  39. if (nsend < 0) return nsend;
  40. return len;
  41. }
  42. int WebSocketChannel::sendPing() {
  43. std::lock_guard<std::mutex> locker(mutex_);
  44. if (type == WS_CLIENT) {
  45. return write(WS_CLIENT_PING_FRAME, WS_CLIENT_MIN_FRAME_SIZE);
  46. }
  47. return write(WS_SERVER_PING_FRAME, WS_SERVER_MIN_FRAME_SIZE);
  48. }
  49. int WebSocketChannel::sendPong() {
  50. std::lock_guard<std::mutex> locker(mutex_);
  51. if (type == WS_CLIENT) {
  52. return write(WS_CLIENT_PONG_FRAME, WS_CLIENT_MIN_FRAME_SIZE);
  53. }
  54. return write(WS_SERVER_PONG_FRAME, WS_SERVER_MIN_FRAME_SIZE);
  55. }
  56. int WebSocketChannel::sendFrame(const char* buf, int len, enum ws_opcode opcode /* = WS_OPCODE_BINARY */, bool fin /* = true */) {
  57. bool has_mask = false;
  58. char mask[4] = {0};
  59. if (type == WS_CLIENT) {
  60. *(int*)mask = rand();
  61. has_mask = true;
  62. }
  63. int frame_size = ws_calc_frame_size(len, has_mask);
  64. if (sendbuf_.len < (size_t)frame_size) {
  65. sendbuf_.resize(ceil2e(frame_size));
  66. }
  67. ws_build_frame(sendbuf_.base, buf, len, mask, has_mask, opcode, fin);
  68. return write(sendbuf_.base, frame_size);
  69. }
  70. }