SimpleVoiceChatServerModule.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. using System.Collections.Concurrent;
  2. using System.Net;
  3. using System.Net.WebSockets;
  4. using System.Text;
  5. namespace SimpleWebChat.ConHost
  6. {
  7. public static class SimpleVoiceChatServerModule
  8. {
  9. public class VoiceSession
  10. {
  11. public WebSocket Host { get; set; }
  12. public WebSocket Guest { get; set; }
  13. }
  14. private static readonly ConcurrentDictionary<string, VoiceSession> VoiceChatSessions = new();
  15. public static void ProcessRequest(HttpListenerContext context, int currentSessionId)
  16. {
  17. WebSocket sck = null;
  18. string num = null;
  19. var isHost = false;
  20. VoiceSession pair = null;
  21. try
  22. {
  23. sck = context.AcceptWebSocketAsync("svcp").Result.WebSocket;
  24. Console.WriteLine($"Request #{currentSessionId:00000} VoiceChat WebSocket Session Start");
  25. var buffer = new byte[16384];
  26. var r = sck.ReceiveAsync(buffer, default).Result;
  27. num = Encoding.UTF8.GetString(buffer, 0, r.Count);
  28. if (VoiceChatSessions.TryGetValue(num, out pair))
  29. {
  30. RunAsGuest(pair, sck, buffer);
  31. }
  32. else
  33. {
  34. pair = RunAsHost(num, sck, buffer);
  35. isHost = true;
  36. }
  37. }
  38. catch (Exception)
  39. {
  40. try
  41. {
  42. if (sck != null && sck.State != WebSocketState.Aborted)
  43. {
  44. sck.CloseAsync(WebSocketCloseStatus.InternalServerError, "Error", default).Wait();
  45. }
  46. }
  47. catch (Exception e)
  48. {
  49. Console.WriteLine(e);
  50. }
  51. }
  52. if (pair != null)
  53. {
  54. if (isHost)
  55. {
  56. VoiceChatSessions.TryRemove(num, out _);
  57. pair.Host = null;
  58. }
  59. else pair.Guest = null;
  60. }
  61. }
  62. private static VoiceSession RunAsHost(string num, WebSocket sck, byte[] buffer)
  63. {
  64. var pair = VoiceChatSessions[num] = new VoiceSession { Host = sck };
  65. sck.Send("CONNECTED AS HOST");
  66. while (true)
  67. {
  68. var r = sck.ReceiveAsync(buffer, default).Result;
  69. if (r.Count == 0) break;
  70. if (pair.Guest != null && pair.Guest.State == WebSocketState.Open)
  71. {
  72. pair.Guest
  73. .SendAsync(new ArraySegment<byte>(buffer, 0, r.Count), WebSocketMessageType.Binary, WebSocketMessageFlags.EndOfMessage, default)
  74. .AsTask().Wait();
  75. }
  76. }
  77. return pair;
  78. }
  79. private static void RunAsGuest(VoiceSession pair, WebSocket sck, byte[] buffer)
  80. {
  81. if (pair.Guest != null) { sck.Send("BUSY"); return; }
  82. pair.Guest = sck;
  83. var host = pair.Host;
  84. sck.Send("CONNECTED AS GUEST");
  85. host.Send("GUEST CONNECTED");
  86. while (true)
  87. {
  88. var r = sck.ReceiveAsync(buffer, default).Result;
  89. if (r.Count == 0) break;
  90. if (host.State == WebSocketState.Open)
  91. {
  92. host.Send(buffer, 0, r.Count);
  93. }
  94. else
  95. {
  96. sck.Send("HOST DISCONNECTED");
  97. return;
  98. }
  99. }
  100. host.Send("GUEST DISCONNECTED");
  101. }
  102. private static void Send(this WebSocket sck, string text) => sck.SendAsync(Encoding.UTF8.GetBytes(text), WebSocketMessageType.Text, true, default).Wait();
  103. private static void Send(this WebSocket sck, byte[] bin) => sck.SendAsync(bin, WebSocketMessageType.Binary, true, default).Wait();
  104. private static void Send(this WebSocket sck, byte[] bin, int offset, int count) => sck.SendAsync(new ArraySegment<byte>(bin, offset, count), WebSocketMessageType.Binary, true, default).Wait();
  105. }
  106. }