/// <summary> /// Event handler that occurs whenever we recieve a response from the host. /// Executes the associated callback if nessesary. /// </summary> private void ReceivedResponse(CommunicationMessage message) { if (!IsMe(message.To)) { DebugMessage?.Invoke($"Received an invalid response: addressed to someone other than me - to: {message.To.Name}, {message.Type}, from {message.From.Name})"); return; } CurrentStatus.LastResponseReceived = DateTime.UtcNow; var responseData = message.GetValue <ResponseMessage>(); DebugMessage?.Invoke($"{message.To.Name} << Received ({message.Type}) from {message.From.Name}: {responseData.ResponseText}"); switch (message.From.Role) { case IdentityRole.Host: if (responseData.Clients.Any()) { UpdateClientList(responseData); } break; case IdentityRole.Client: RequestClientListFromHost(); break; } FireCallbacks(message, responseData); }
private void SendBroadcastInternal(CommunicationMessage message, Action <CallbackArgs> responseHandler) { foreach (var client in Clients) { SendMessage(message, client.Identity, responseHandler); } }
/// <summary> /// Actually send a message. /// </summary> private void SendMessageInternal(CommunicationMessage message, Identity to = null) { try { var senderId = message.From.Equals(ClientDevice.Identity) ? message.From : _hostId; var receiverId = to ?? _hostId; //var uri = to?.Role == IdentityRole.Client && !to.Equals(HostDevice.Identity) ? HostDevice.GetUri(to) : HostDevice.Uri; var uri = to?.Address ?? HostDevice.Uri; var binding = HostDevice.CreateBinding(); var proxy = ChannelFactory <ITransmissionService> .CreateChannel(binding, new EndpointAddress(uri)); message.Sent = DateTime.UtcNow; message.To = receiverId; Task.Run(() => { DebugMessage?.Invoke($"{senderId.Name} >> Sending {message.Name} ({message.Type}) to {receiverId.Name}"); CurrentStatus.LastSendTime = DateTime.UtcNow; try { proxy.SendData(TransmissionService.PrepareMessage(message)); } //catch (EndpointNotFoundException ex) catch (Exception ex) { DebugMessage?.Invoke($"Exception: {ex.GetType().Name} {ex.Message}"); } }); } catch (Exception ex) { DebugMessage?.Invoke($"Exception: {ex.GetType().Name} {ex.Message}"); } }
/// <summary> /// Keep track of who sent a message /// </summary> private void UpdateHostClientList(Identity id, CommunicationMessage message = null) { var found = false; foreach (var client in _hostClientsList.ToList()) { if (client.Identity.Equals(id)) { found = true; client.State = ClientState.Active; client.LastMessage = message; } else if (DateTime.UtcNow.Subtract(client.LastMessage.Received) > ClientExpiryTime) { _hostClientsList.Remove(client); } else if (DateTime.UtcNow.Subtract(client.LastMessage.Received) > ClientInactiveTime) { client.State = ClientState.Inactive; } } if (!found) { DebugMessage?.Invoke($"{_hostId.Name}: Adding new client information - {id}"); _hostClientsList.Add(new RemoteClient(id, message)); } }
/// <summary> /// Send message to all clients. /// </summary> public void SendMessage(CommunicationMessage message, Action <CallbackArgs> responseHandler = null) { if (TryValidateConnection(message, null, args => SendBroadcastInternal(message, responseHandler))) { return; } SendBroadcastInternal(message, responseHandler); }
/// <summary> /// Send a message to a specific client. /// </summary> public void SendMessage(CommunicationMessage message, Identity to, Action <CallbackArgs> responseHandler = null) { if (TryValidateConnection(message, to, responseHandler)) { return; } AddCallback(message, responseHandler); SendMessageInternal(message, to); }
/// <summary> /// Send a message on the host channel to see if we get a response. /// </summary> public void Ping() { var msg = new CommunicationMessage { Name = "Ping", From = _clientId }; AddCallback(msg, HandlePingSuccess); SendMessageInternal(msg); DebugMessage?.Invoke($"Ping..."); }
private void ServiceOnDataReceived(CommunicationMessage message) { switch (message.Type) { case MessageType.Response: ResponseReceived?.Invoke(message); break; default: MessageReceived?.Invoke(message); break; } }
private void FireCallbacks(CommunicationMessage message, ResponseMessage responseData) { if (_callbacks.ContainsKey(message.CallbackId)) { var args = new CallbackArgs { OriginalMessage = message, Response = responseData }; _callbacks[message.CallbackId]?.Callback.Invoke(args); _callbacks.Remove(message.CallbackId); } }
/// <summary> /// Prepare a function and identify it with an ID in the message, /// so that it can be executed later when the host responds. /// </summary> private void AddCallback(CommunicationMessage message, Action <CallbackArgs> responseHandler) { if (responseHandler != null && message != null) { var pid = Guid.NewGuid(); _callbacks.Add(pid, new PendingCallback { Guid = pid, Created = DateTime.UtcNow, Callback = responseHandler }); message.CallbackId = pid; } }
private bool TryValidateConnection(CommunicationMessage message, Identity to, Action <CallbackArgs> action) { if (DateTime.UtcNow.Subtract(CurrentStatus.LastResponseReceived) > SyncInterval) { if (to != null) { _actionQueue.Enqueue(new QueuedAction(args => SendMessage(message, to, action))); } else if (action != null) { _actionQueue.Enqueue(new QueuedAction(action)); } Sync(); return(true); } return(false); }
private void SendResponse(Identity from, CommunicationMessage message, List <RemoteClient> clientList = null) { var msg = new CommunicationMessage { From = from, CallbackId = message.CallbackId, Type = MessageType.Response }; msg.SetValue(new ResponseMessage { From = _clientId, Clients = clientList ?? new List <RemoteClient>(), ResponseText = "Acknowledged", Result = true }); SendMessageInternal(msg, message.From); }
private void ReceivedMessage(CommunicationMessage message) { if (!IsMe(message.To)) { DebugMessage?.Invoke($"Received an invalid message: addressed to someone other than me - to: {message.To.Name}, {message.Type}, from {message.From.Name})"); return; } DebugMessage?.Invoke($"{message.To.Name} << Received ({message.Type}) from {message.From.Name}"); if (message.To.Role == IdentityRole.Host && !message.From.Equals(_hostId)) { UpdateHostClientList(message.From, message); } else { RequestClientListFromHost(); } SendResponse(message.To, message, _hostClientsList); }
public static byte[] PrepareMessage(CommunicationMessage msg) => GetBytes(msg.Serialize());
public static CommunicationMessage GetMessage(byte[] bytes) => CommunicationMessage.Deserialize(GetString(bytes));
public RemoteClient(Identity identity, CommunicationMessage message = null) { Identity = identity; LastMessage = message; }