/// <summary> /// "SuperUser DO"; debug-only message used to forcefully set attributes of a connected ship. /// </summary> public void OnSudo(NetPeer peer, Messages.Sudo data) { Console.WriteLine("Sudo: {0}", data.Json.ToString()); LocalSpaceship ship = null; if (data.Json.ContainsKey("token")) { var token = (string)data.Json["token"]; ship = QuadTreeNode.ShipsByToken.GetValueOrDefault(token, null); if (ship == null) { return; } } foreach (var kv in data.Json) { if (kv.Key == "token") { continue; } AttributeSetter setter = SUDO_SETTER_MAP.GetValueOrDefault(kv.Key, null); if (setter == null) { Console.Error.WriteLine("Sudo: Unrecognized attribute `" + kv.Key + "`"); return; } try { setter.Invoke(this, ship, kv.Value); } catch (Exception exc) { Console.Error.WriteLine("Sudo: Failed to set attribute `" + kv.Key + "`: " + exc.ToString()); return; } } // Send the same sudo back to the arbiter as ACK Bus.SendMessage(data, ArbiterPeer, LiteNetLib.DeliveryMethod.ReliableOrdered); }
public async Task Sudo(ApiResponse response, ApiData data) { var message = new Messages.Sudo() { Json = data.Json }; if (data.Json.ContainsKey("token")) { var shipToken = (string)data.Json["token"]; var shipNode = RoutingTable.NodeWithShip(shipToken); if (shipNode == null) { response.Data["error"] = $"No ship with token: {shipToken}"; await response.Send(500); return; } RoutingTable.BusMaster.SendMessage(message, shipNode.Peer, LiteNetLib.DeliveryMethod.ReliableOrdered); // Wait for the sudo to bounce back from the node await new MessageWaiter <Messages.Sudo>(RoutingTable.BusMaster, shipNode.Peer, (sudo) => sudo.Json.Equals(message.Json)).Wait; } else { RoutingTable.BusMaster.BroadcastMessage(message); // Wait for ALL nodes to ACK sudo... var waiters = RoutingTable.BusMaster.Host.ConnectedPeerList .Select((peer) => new MessageWaiter <Messages.Sudo>(RoutingTable.BusMaster, peer, (sudo) => sudo.Json.Equals(message.Json)).Wait) .ToArray(); Task.WaitAll(waiters); } await response.Send(200); }