WebSocketServer.cs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Runtime.InteropServices;
  6. using System.Security.Cryptography;
  7. namespace HPSocketCS
  8. {
  9. public class WebSocketServer : HttpServer
  10. {
  11. public event WebSocketEvent.OnWSMessageHeaderEventHandler OnWSMessageHeader;
  12. public event WebSocketEvent.OnWSMessageBodyEventHandler OnWSMessageBody;
  13. public event WebSocketEvent.OnPointerWSMessageBodyEventHandler OnPointerWSMessageBody;
  14. public event WebSocketEvent.OnWSMessageCompleteEventHandler OnWSMessageComplete;
  15. HttpSdk.OnWSMessageHeader _OnWSMessageHeader;
  16. HttpSdk.OnWSMessageBody _OnWSMessageBody;
  17. HttpSdk.OnWSMessageComplete _OnWSMessageComplete;
  18. protected override void SetCallback()
  19. {
  20. base.SetCallback();
  21. // 设置websocket的callback
  22. _OnWSMessageHeader = new HttpSdk.OnWSMessageHeader(SDK_OnWSMessageHeader);
  23. _OnWSMessageBody = new HttpSdk.OnWSMessageBody(SDK_OnWSMessageBody);
  24. _OnWSMessageComplete = new HttpSdk.OnWSMessageComplete(SDK_OnWSMessageComplete);
  25. HttpSdk.HP_Set_FN_HttpServer_OnWSMessageHeader(pListener, _OnWSMessageHeader);
  26. HttpSdk.HP_Set_FN_HttpServer_OnWSMessageBody(pListener, _OnWSMessageBody);
  27. HttpSdk.HP_Set_FN_HttpServer_OnWSMessageComplete(pListener, _OnWSMessageComplete);
  28. }
  29. protected virtual HandleResult SDK_OnWSMessageHeader(IntPtr pSender, IntPtr dwConnID, bool bFinal, byte iReserved, byte iOperationCode, byte[] lpszMask, ulong ullBodyLen)
  30. {
  31. if (OnWSMessageHeader != null)
  32. {
  33. return OnWSMessageHeader(dwConnID, bFinal, iReserved, iOperationCode, lpszMask, ullBodyLen);
  34. }
  35. return HandleResult.Ok;
  36. }
  37. protected virtual HandleResult SDK_OnWSMessageBody(IntPtr pSender, IntPtr dwConnID, IntPtr pData, int length)
  38. {
  39. if (OnPointerWSMessageBody != null)
  40. {
  41. return OnPointerWSMessageBody(dwConnID, pData, length);
  42. }
  43. else if (OnWSMessageBody != null)
  44. {
  45. byte[] bytes = new byte[length];
  46. Marshal.Copy(pData, bytes, 0, length);
  47. return OnWSMessageBody(dwConnID, bytes);
  48. }
  49. return HandleResult.Ok;
  50. }
  51. protected virtual HandleResult SDK_OnWSMessageComplete(IntPtr pSender, IntPtr connId)
  52. {
  53. if (OnWSMessageComplete != null)
  54. {
  55. return OnWSMessageComplete(connId);
  56. }
  57. return HandleResult.Ok;
  58. }
  59. protected override HttpParseResult SDK_OnUpgrade(IntPtr pSender, IntPtr connId, HttpUpgradeType upgradeType)
  60. {
  61. if (upgradeType == HttpUpgradeType.HttpTunnel)
  62. {
  63. SendResponse(connId, HttpStatusCode.Ok, "Connection Established", null, null, 0);
  64. }
  65. else if (upgradeType == HttpUpgradeType.WebSocket)
  66. {
  67. THeader[] headers =
  68. {
  69. new THeader() { Name= "Connection", Value = "Upgrade" },
  70. new THeader() { Name= "Upgrade", Value = "WebSocket" },
  71. new THeader(),
  72. new THeader(),
  73. };
  74. var keyName = "Sec-WebSocket-Key";
  75. var secWebSocketKey = GetHeader(connId, keyName);
  76. if (string.IsNullOrEmpty(secWebSocketKey))
  77. {
  78. return HttpParseResult.Error;
  79. }
  80. SHA1 sha1 = new SHA1CryptoServiceProvider();
  81. byte[] bytes_sha1_in = Encoding.UTF8.GetBytes(secWebSocketKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
  82. byte[] bytes_sha1_out = sha1.ComputeHash(bytes_sha1_in);
  83. string str_sha1_out = Convert.ToBase64String(bytes_sha1_out);
  84. headers[2].Name = "Sec-WebSocket-Accept";
  85. headers[2].Value = str_sha1_out;
  86. var secWebSocketProtocol = GetHeader(connId, "Sec-WebSocket-Protocol");
  87. if (!string.IsNullOrEmpty(secWebSocketProtocol))
  88. {
  89. var arr = secWebSocketProtocol.Split(new[] { ',', ' ' });
  90. if (arr.Length > 0)
  91. {
  92. headers[3].Name = "Sec-WebSocket-Protocol";
  93. headers[3].Value = arr[0];
  94. }
  95. }
  96. SendResponse(connId, HttpStatusCode.SwitchingProtocols, null, headers, null, 0);
  97. }
  98. return HttpParseResult.Ok;
  99. }
  100. public bool SendMessage(IntPtr connId, WSMessageState state, IntPtr pData, int length)
  101. {
  102. return HttpSdk.HP_HttpServer_SendWSMessage(pServer, connId, state.Final, state.Reserved, state.OperationCode, state.Mask, pData, length, 0);
  103. }
  104. public bool SendWSMessage(IntPtr connId, WSMessageState state, byte[] data)
  105. {
  106. state.Mask = null;
  107. int bodyLen = data == null ? 0 : data.Length;
  108. return HttpSdk.HP_HttpServer_SendWSMessage(pServer, connId, state.Final, state.Reserved, state.OperationCode, state.Mask, data, bodyLen, 0);
  109. }
  110. public WSMessageState GetWSMessageState(IntPtr connId)
  111. {
  112. bool final = false;
  113. WSReserved reserved = WSReserved.Off;
  114. WSOpcode operationCode = WSOpcode.Cont;
  115. IntPtr maskPtr = IntPtr.Zero;
  116. ulong bodyLen = 0;
  117. ulong bodyRemain = 0;
  118. bool ret = HttpSdk.HP_HttpServer_GetWSMessageState(pServer, connId, ref final, ref reserved, ref operationCode, ref maskPtr, ref bodyLen, ref bodyRemain);
  119. if (ret)
  120. {
  121. WSMessageState state = new WSMessageState()
  122. {
  123. Final = final,
  124. Reserved = reserved,
  125. OperationCode = operationCode,
  126. BodyLen = bodyLen,
  127. BodyRemain = bodyRemain,
  128. };
  129. if (maskPtr != IntPtr.Zero)
  130. {
  131. state.Mask = new byte[4];
  132. Marshal.Copy(maskPtr, state.Mask, 0, state.Mask.Length);
  133. }
  134. return state;
  135. }
  136. return null;
  137. }
  138. }
  139. }