/// <summary> /// Initializes a new instance of the <see cref="WebSocketHandler"/> class. /// </summary> /// <param name="webSocketConnectionManager">The web socket connection manager.</param> /// <param name="methodInvocationStrategy">The method invocation strategy used for incoming requests.</param> public WebSocketHandler(WebSocketConnectionManager webSocketConnectionManager, MethodInvocationStrategy methodInvocationStrategy) { _jsonSerializerSettings.Converters.Insert(0, new PrimitiveJsonConverter()); WebSocketConnectionManager = webSocketConnectionManager; MethodInvocationStrategy = methodInvocationStrategy; _pingTimer = new Timer(OnPingTimer, null, WebSocket.DefaultKeepAliveInterval, WebSocket.DefaultKeepAliveInterval); ulid = NUlid.Ulid.NewUlid().ToGuid().ToString(); }
private async Task StartClient(Uri uri, CancellationToken token, ReconnectionType type) { // also check if connection was lost, that's probably why we get called multiple times. if (_clientWebSocket == null || _clientWebSocket.State != WebSocketState.Open) { // create a new web-socket so the next connect call works. _clientWebSocket?.Dispose(); //var options = new ClientWebSocketOptions(); _clientWebSocket = new ClientWebSocket(); _clientWebSocket.Options.KeepAliveInterval = new TimeSpan(0, 0, 15, 0); if (!string.IsNullOrEmpty(_token)) { _clientWebSocket.Options.SetRequestHeader("Authorization", "Bearer " + _token); } } // don't do anything, we are already connected. else { return; } try { //await _clientWebSocket.ConnectAsync(uri, CancellationToken.None).ConfigureAwait(false); await _clientWebSocket.ConnectAsync(uri, token).ConfigureAwait(false); OnConnect?.Invoke(this, EventArgs.Empty); IsRunning = true; await Receive(_clientWebSocket, token, async (receivedMessage) => { JObject jObject = null; InvocationDescriptor invocationDescriptor = null; try { jObject = Newtonsoft.Json.JsonConvert.DeserializeObject <JObject>(receivedMessage); //invocationDescriptor = JsonConvert.DeserializeObject<InvocationDescriptor>(serializedMessage); invocationDescriptor = jObject.ToObject <InvocationDescriptor>(); //if (invocationDescriptor == null) return; } catch (Exception ex) { // ignore invalid data sent to the server. } if (jObject == null) { try { var obj = MethodInvocationStrategy.OnTextReceivedAsync("", receivedMessage); } catch (Exception ex) { } return; } if (invocationDescriptor != null && invocationDescriptor.Params != null) { if (invocationDescriptor.Id == 0) { // invoke the method only. try { await MethodInvocationStrategy.OnInvokeMethodReceivedAsync("", invocationDescriptor); } catch (Exception) { // we consume all exceptions. return; } } else { // invoke the method and get the result. InvocationResult invokeResult; try { // create an invocation result with the results. invokeResult = new InvocationResult() { Id = invocationDescriptor.Id, Result = await MethodInvocationStrategy.OnInvokeMethodReceivedAsync("", invocationDescriptor), Exception = null }; } // send the exception as the invocation result if there was one. catch (Exception ex) { invokeResult = new InvocationResult() { Id = invocationDescriptor.Id, Result = null, Exception = new RemoteException(ex) }; } // send a message to the server containing the result. var message = new Message() { MessageType = MessageType.MethodReturnValue, Data = JsonConvert.SerializeObject(invokeResult) }; //var bytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(message, _jsonSerializerSettings)); //var bytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(message.Data, _jsonSerializerSettings)); //await _clientWebSocket.SendAsync(new ArraySegment<byte>(bytes), WebSocketMessageType.Text, true, CancellationToken.None).ConfigureAwait(false); await Send(message.Data); } } else { try { var invocationResult = jObject.ToObject <InvocationResult>(); if ((invocationResult != null) && (invocationResult.Exception != null || invocationResult.Result != null)) { // find the completion source in the waiting list. if (_waitingRemoteInvocations.ContainsKey(invocationResult.Id)) { // set the result of the completion source so the invoke method continues executing. _waitingRemoteInvocations[invocationResult.Id].SetResult(invocationResult); // remove the completion source from the waiting list. _waitingRemoteInvocations.Remove(invocationResult.Id); } } } catch (Exception e) { var str = e.Message; } } }); ActivateLastChance(); } catch (Exception e) { Console.WriteLine($"{DateTime.Now} _clientWebSocket.ConnectAsync Exception: {e.Message}"); IsRunning = false; await Task.Delay(ErrorReconnectTimeoutMs, _cancelation.Token).ConfigureAwait(false); await Reconnect(ReconnectionType.Error).ConfigureAwait(false); } }
/// <summary> /// Initializes a new instance of the <see cref="Connection"/> class. /// </summary> /// <param name="methodInvocationStrategy">The method invocation strategy used for incoming requests.</param> public Connection(MethodInvocationStrategy methodInvocationStrategy) { MethodInvocationStrategy = methodInvocationStrategy; _jsonSerializerSettings.Converters.Insert(0, new PrimitiveJsonConverter()); }
public virtual async Task OnReceivedBinaryAsync(WebSocketConnection socket, byte[] receivedMessage) { InvocationDescriptor invocationDescriptor; InvocationResult invocationResult; var timer = new Stopwatch(); timer.Start(); try { invocationResult = MessagePackSerializer.Deserialize <InvocationResult>(receivedMessage); if ((invocationResult != null) && (invocationResult.Exception != null || invocationResult.Result != null)) { await PreRpcResponse(socket, invocationResult).ConfigureAwait(false); await OnPeerResponseAsync(socket, invocationResult); await PostRpcResponse(socket, invocationResult).ConfigureAwait(false); return; } } catch (Exception e) { // Ignore if is not msgrpc result } try { invocationDescriptor = MessagePackSerializer.Deserialize <InvocationDescriptor>(receivedMessage); if (invocationDescriptor == null) { return; } await PreRpcRequest(socket, invocationDescriptor).ConfigureAwait(false); // retrieve the method invocation request. // if the unique identifier hasn't been set then the client doesn't want a return value. if (invocationDescriptor.Id == 0) { // invoke the method only. try { var result = await MethodInvocationStrategy.OnInvokeMethodReceivedAsync(socket, invocationDescriptor); timer.Stop(); await PostRpcRequest(socket, invocationDescriptor, timer.ElapsedMilliseconds).ConfigureAwait(false); } catch (Exception e) { // we consume all exceptions. } } else { try { var invokeResult = await MethodInvocationStrategy.OnInvokeMethodReceivedAsync(socket, invocationDescriptor); if (invokeResult is InvocationResult) { invocationResult = (InvocationResult)invokeResult; } if (invokeResult != null) { MessagePackSerializerOptions options; byte[] bytes = MessagePackSerializer.Serialize(invokeResult); var message = new Message() { MessageType = MessageType.Binary, Bytes = bytes }; await SendMessageAsync(socket, message).ConfigureAwait(false); timer.Stop(); await PostRpcRequest(socket, invocationDescriptor, timer.ElapsedMilliseconds); } } catch (Exception e) { throw; } } } catch (Exception e) { //throw; } timer.Stop(); await Task.CompletedTask; }
public virtual async Task OnReceivedTextAsync(WebSocketConnection socket, string serializedMessage) { var timer = new Stopwatch(); JObject jObject = null; InvocationDescriptor invocationDescriptor = null; InvocationResult invocationResult = null; timer.Start(); try { jObject = JsonConvert.DeserializeObject <JObject>(serializedMessage); } catch (Exception e) { // ignore invalid data sent to the server. //socket.WebSocket.CloseOutputAsync(); return; } try { invocationResult = jObject.ToObject <InvocationResult>(); if ((invocationResult != null) && (invocationResult.Exception != null || invocationResult.Result != null)) { await PreRpcResponse(socket, invocationResult).ConfigureAwait(false); await OnPeerResponseAsync(socket, invocationResult); await PostRpcResponse(socket, invocationResult).ConfigureAwait(false); return; } } catch (Exception e) { // Ignore if is not jsonrpc result } try { invocationDescriptor = jObject.ToObject <InvocationDescriptor>(); } catch (Exception e) { // Not jsonrpc request //return; } // method invocation request. if (invocationDescriptor != null) { await PreRpcRequest(socket, invocationDescriptor).ConfigureAwait(false); // retrieve the method invocation request. // if the unique identifier hasn't been set then the client doesn't want a return value. if (invocationDescriptor.Id == 0) { // invoke the method only. try { var result = await MethodInvocationStrategy.OnInvokeMethodReceivedAsync(socket, invocationDescriptor); timer.Stop(); await PostRpcRequest(socket, invocationDescriptor, timer.ElapsedMilliseconds).ConfigureAwait(false); } catch (Exception e) { // we consume all exceptions. } timer.Start(); } else { try { var invokeResult = await MethodInvocationStrategy.OnInvokeMethodReceivedAsync(socket, invocationDescriptor); if (invokeResult != null) { string json = JsonConvert.SerializeObject(invokeResult); // send a message to the client containing the result. var message = new Message() { MessageType = MessageType.MethodReturnValue, Data = json //Data = JsonConvert.SerializeObject(invokeResult, _jsonSerializerSettings) }; await SendMessageAsync(socket, message).ConfigureAwait(false); timer.Stop(); await PostRpcRequest(socket, invocationDescriptor, timer.ElapsedMilliseconds); } } catch (Exception e) { throw; } } } else { await OnUnknownAsync(socket, jObject); } }
/// <summary> /// Initializes a new instance of the <see cref="WebSocketHandler"/> class. /// </summary> /// <param name="webSocketConnectionManager">The web socket connection manager.</param> /// <param name="methodInvocationStrategy">The method invocation strategy used for incoming requests.</param> public WebSocketHandler(WebSocketConnectionManager webSocketConnectionManager, MethodInvocationStrategy methodInvocationStrategy) { _jsonSerializerSettings.Converters.Insert(0, new PrimitiveJsonConverter()); WebSocketConnectionManager = webSocketConnectionManager; MethodInvocationStrategy = methodInvocationStrategy; }