/// <summary> Globally calls an <see cref="RPCMessage"/>, as if the given client had sent it. </summary> /// <param name="client"> Client to simulate call of method for </param> /// <param name="callback"> Callback to call </param> /// <param name="stuff"> Parameters for call </param> public void Call(Client client, RPCMessage.Handler callback, params System.Object[] stuff) { string str = Client.FormatCall(callback, stuff); RPCMessage msg = RPCMessage.TCP(client, str); incoming.Enqueue(msg); }
/// <summary> Attempts to read data from a client and enqueue in <see cref="incoming"/> </summary> /// <param name="client"> Websocket client </param> /// <returns> Task that completes when the client is closed. </returns> public async Task RecieveDataWebsocket(Client client) { byte[] buffer = new byte[1024]; ArraySegment <byte> seg = new ArraySegment <byte>(buffer); var stupid = CancellationToken.None; while (!client.closed && (client.ws.State == WebSocketState.Open || client.ws.State == WebSocketState.Connecting)) { try { var result = await client.ws.ReceiveAsync(seg, stupid); if (result.MessageType == WebSocketMessageType.Close) { Log.Info($"Client {client.identity} got normal closure message."); Close(client); break; } else { string str = Encoding.UTF8.GetString(buffer, 0, result.Count); Log.Info($"Server.RecieveDataWebsocket(Client): Got message {result.Count} | {str}"); incoming.Enqueue(RPCMessage.TCP(client, str)); } } catch (Exception e) { Log.Error($"Server.RecieveDataWebsocket(Client): Error during read.", e); } } }
/// <summary> Attempts to read data from a client once </summary> /// <param name="client"> Client information to read data for </param> public void RecieveData(Client client) { // Helper method to handle reading Client.ReadState read(Client.ReadState state, int kind) { if (state.bytesRead > 0) { state.message = state.buffer.Chop(state.bytesRead); state.message = client.dec(state.message); string str = state.message.GetStringUTF8(); state.held += str; int index = state.held.IndexOf(RPCMessage.EOT); while (index >= 0) { string pulled = state.held.Substring(0, index); state.held = state.held.Remove(0, index + 1); index = state.held.IndexOf(RPCMessage.EOT); if (pulled.Length > 0) { RPCMessage msg = kind == UDP?RPCMessage.UDP(client, pulled) : RPCMessage.TCP(client, pulled); incoming.Enqueue(msg); } } } return(state); } if (client.udp != null) { try { bool canReadUDP = !client.closed && client.udp.Available > 0; EndPoint ep = client.remoteUdpHost; client.udpReadState.bytesRead = canReadUDP ? client.udp.ReceiveFrom(client.udpReadState.buffer, ref ep) : -1; client.udpReadState = read(client.udpReadState, UDP); if (canReadUDP && client.udpReadState.bytesRead > 0 && ep is IPEndPoint) { client.remoteUdpHost = (IPEndPoint)ep; Log.Info($"{client.identity} recieved from {client.remoteUdpHost}"); } } catch (Exception e) { Log.Warning($"Server.RecieveData(Client): {client.identity} Error during UDP read. {e.GetType()}. Will defer to TCP closure to disconnect.", e); } } try { client.tcpReadState.bytesRead = !client.closed && client.tcpStream.CanRead && client.tcpStream.DataAvailable ? client.tcpStream.Read(client.tcpReadState.buffer, 0, client.tcpReadState.buffer.Length) : -1; client.tcpReadState = read(client.tcpReadState, TCP); } catch (ObjectDisposedException e) { Log.Verbose($"Server.RecieveData(Client): {client.identity} Probably Disconnected. {e.GetType()}", e); Close(client); } catch (SocketException e) { Log.Verbose($"Server.RecieveData(Client): {client.identity} Probably Disconnected. {e.GetType()}", e); Close(client); } catch (IOException e) { Log.Verbose($"Server.RecieveData(Client): {client.identity} Probably timed out. {e.GetType()}", e); Close(client); } catch (InvalidOperationException e) { Log.Verbose($"Server.RecieveData(Client): {client.identity} Probably timed out. {e.GetType()}", e); Close(client); } catch (Exception e) { Log.Warning($"Server.RecieveData(Client): ", e); } }