123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading;
- using System.Threading.Tasks;
- using InABox.Clients;
- using InABox.Core;
- using WebSocketSharp;
- using ErrorEventArgs = WebSocketSharp.ErrorEventArgs;
- namespace InABox.Rpc
- {
- public class RpcClientSocketTransport : RpcClientTransport, IDisposable
- {
- private WebSocket? _socket;
-
- private string[] _urls;
- public RpcClientSocketTransport(string[] urls)
- {
- _urls = urls;
- }
-
- private void Socket_OnOpen(object? sender, EventArgs e)
- {
- DoOpen();
- }
-
- private void Socket_OnMessage(object? sender, MessageEventArgs e)
- {
- RpcMessage? message = null;
- if (e.IsBinary && (e.RawData != null))
- message = Serialization.ReadBinary<RpcMessage>(e.RawData, BinarySerializationSettings.Latest);
- else if (e.IsText && !string.IsNullOrWhiteSpace(e.Data))
- message = Serialization.Deserialize<RpcMessage>(e.Data);
-
- Accept(message);
- }
- private void Socket_OnClose(object? sender, CloseEventArgs e)
- {
- DoClose(RpcTransportCloseEventType.Closed);
- }
- private void Socket_OnError(object? sender, ErrorEventArgs e)
- {
- DoException(e.Exception);
- }
-
- private WebSocket? CreateSocket(string url, bool secure)
- {
- WebSocket socket = null;
- var address = $"{(secure ? "wss" : "ws")}://{url}";
- try
- {
- socket = new WebSocket(address);
- }
- catch (Exception e)
- {
- return null;
- }
-
- // Time to wait before disconnect - the default meant that the client disconnected during debugging, since the ping would fail
- socket.WaitTime = TimeSpan.FromSeconds(20);
- socket.OnOpen -= Socket_OnOpen;
- socket.OnError -= Socket_OnError;
- socket.OnClose -= Socket_OnClose;
- socket.OnMessage -= Socket_OnMessage;
- socket.Connect();
- if (socket.ReadyState == WebSocketState.Open)
- {
- DoOpen();
- socket.OnOpen += Socket_OnOpen;
- socket.OnError += Socket_OnError;
- socket.OnClose += Socket_OnClose;
- socket.OnMessage += Socket_OnMessage;
- return socket;
- }
- return null;
- }
- public override void Connect()
- {
- List<Task<WebSocket>> tasks = new List<Task<WebSocket>>();
- foreach (var url in _urls)
- {
- tasks.Add(Task<WebSocket>.Run(() => CreateSocket(url, true)));
- tasks.Add(Task<WebSocket>.Run(() => CreateSocket(url, false)));
- }
- while (tasks.Count > 0)
- {
- var result = Task.WhenAny(tasks).Result;
- if (result.Result == null)
- tasks.Remove(result);
- else
- {
- _socket = result.Result;
- return;
- }
- }
- }
- public override bool IsConnected() => _socket?.ReadyState == WebSocketState.Open;
- public override bool IsSecure() => _socket?.IsSecure == true;
-
- public override void Disconnect()
- {
- _socket?.Close(CloseStatusCode.Normal);
- }
- public override void Send(RpcMessage message)
- {
- var buffer = message.WriteBinary(BinarySerializationSettings.Latest);
- _socket?.Send(buffer);
- }
- protected override RpcClientTransport Clone() => new RpcClientSocketTransport(_urls);
- public void Dispose()
- {
- if (IsConnected())
- Disconnect();
- }
- }
- }
|