public async Task ProcessMessage(InternalHubNetworkClient sender, InternalMessage msg) { if (msg == null) { return; } msg.Sender = sender.Name; switch (msg.Type) { case InternalMessageType.Direct: await SendDirect(sender, msg); break; case InternalMessageType.Broadcast: await SendBroadcast(sender, msg); break; case InternalMessageType.Random: await SendRandom(sender, msg); break; case InternalMessageType.RoundRobin: await SendRoundRobin(sender, msg); break; } }
private async Task SendRoundRobin(InternalHubNetworkClient sender, InternalMessage msg) { if (!msg.NoAck) { await Ack(msg.CorrelationId, sender); } while (_clients.Count > 0) { try { InternalHubNetworkClient socket = null; lock (_roundRobinLock) { _roundRobinIndex++; if (_roundRobinIndex >= _clients.Count) { _roundRobinIndex = 0; } socket = _clients.Values.ElementAt(_roundRobinIndex); } await SendAsync(socket, msg); break; } catch (ArgumentOutOfRangeException) { continue; } } }
private async Task SendBroadcast(InternalHubNetworkClient sender, InternalMessage msg) { if (!msg.NoAck) { await Ack(msg.CorrelationId, sender); } await Task.WhenAll(_clients.Values.Where(c => c.Name != sender.Name).Select(c => SendAsync(c, msg))); }
private async Task Ack(string id, InternalHubNetworkClient client) { await SendAsync(client, new InternalMessage { CorrelationId = id, Type = InternalMessageType.Ack }); }
public HubNetworkClient(string name, string network, IPEndPoint ep, ClientSocketOptions opts, Logger logger = null) { Name = name; _logger = logger ?? LogManager.GetLogger("HubNetwork.Client"); _client = new InternalHubNetworkClient(name, network, ep, opts, _logger); _opts = opts; _client.OnConnected += () => OnConnected?.Invoke(); _client.OnDisconnected += () => OnDisconnected?.Invoke(); _client.OnMessage += (s, m) => OnInternalMessage(m); }
private async Task SendAsync(InternalHubNetworkClient client, InternalMessage msg) { try { msg.Reciever = client.Name; _logger.Trace("[{0}] Send message from client {1} to client {2} with id {3} with type {4}", _networkName, msg.Sender, msg.Reciever, msg.CorrelationId, msg.Type); await client.SendAsync(msg); } catch (Exception) { _clients.TryRemove(client.Name, out var _); } }
private async Task SendRandom(InternalHubNetworkClient sender, InternalMessage msg) { if (!msg.NoAck) { await Ack(msg.CorrelationId, sender); } while (_clients.Count > 0) { var index = _rnd.Next(0, _clients.Count); try { await SendAsync(_clients.Values.ElementAt(index), msg); break; } catch (ArgumentOutOfRangeException) { continue; } } }
private async Task SendDirect(InternalHubNetworkClient sender, InternalMessage msg) { if (String.IsNullOrEmpty(msg.Reciever) || !_clients.TryGetValue(msg.Reciever, out var peer)) { _logger.Trace("[{0}] No reciever {1} for message with id {2} from client {3}", _networkName, msg.Reciever, msg.CorrelationId, sender.Name); await SendAsync(sender, new InternalMessage { Reciever = sender.Name, Type = InternalMessageType.Error, CorrelationId = msg.CorrelationId, Payload = Encoding.UTF8.GetBytes($"No reciever '{msg.Reciever}'"), }); return; } if (!msg.NoAck) { await Ack(msg.CorrelationId, sender); } await SendAsync(peer, msg); }
private async Task Listen() { _server.Start(); while (!_cts.IsCancellationRequested) { try { var client = await _server.AcceptTcpClientAsync(); _logger.Info($"New connection from {client.Client.RemoteEndPoint}"); var clientSocket = new InternalHubNetworkClient("", "", new Client.TcpClient(client), new ClientSocketOptions { AutoReconnect = false, Heartbeat = false }, _clientLogger); clientSocket.SetConnected(); var m = await clientSocket.ReadAsync(); if (m.Type != InternalMessageType.Init) { throw new Exception($"Invalid init message from client {client.Client.RemoteEndPoint}"); } clientSocket.Name = m.Reciever; _logger.Info($"New connection {client.Client.RemoteEndPoint} identified as {clientSocket.Name}"); var networkName = Encoding.UTF8.GetString(m.Payload); var network = _networks.GetOrAdd(networkName, n => new Network(networkName)); clientSocket.OnMessage += async(s, msg) => { await _serveMessages.SendAsync(new NetworkMessage { Message = msg, Network = networkName, Socket = clientSocket }); }; clientSocket.StartRecieve(); try { if (network.AddClient(clientSocket)) { await clientSocket.SendAsync(new InternalMessage() { CorrelationId = m.CorrelationId }); } else { await clientSocket.SendAsync(new InternalMessage { Type = InternalMessageType.Error, CorrelationId = m.CorrelationId, Payload = Encoding.UTF8.GetBytes($"Client with name {clientSocket.Name} already connected") }); continue; } } catch (Exception) { continue; } } catch (Exception e) { _logger.Error(e, $"Error occured in listener thread"); } } }
public bool AddClient(InternalHubNetworkClient client) { client.OnDisconnected += () => _clients.TryRemove(client.Name, out var _); return(_clients.TryAdd(client.Name, client)); }