private bool HandleUpdate(RequestEventArgs e, NetworkRequest req) { if (req.AuthKey == model.Network.Overlord.Secret) { model.Network.Overlord.LastUpdate = Environment.TickCount; var verb = new UpdateVerb(); verb.ProcessRequest(req); foreach (Node node in verb.Nodes) { Node search = model.Network.Nodes.Where(i => i.ID == node.ID).FirstOrDefault(); if (search == null) { //Dont allow partial updates to create clients. Only full updates should contain the online flag. if (node.ContainsKey("Online") && node.ContainsKey("Nickname") && node.ContainsKey("ID")) { model.Network.Nodes.Add(node); } } else { foreach (var param in node.Data) { search.SetData(param.Key, param.Value); } //Has the client disconnected? if (!search.Online) { model.Network.Nodes.Remove(node); logger.Trace("Client: Node offline update: " + node.ID); } } } SendOk(e); return(true); } return(false); }
/// <summary> /// Handle updates from local clients, external overlords and peers on external overlords from their overlord. /// </summary> /// <param name="e"></param> /// <param name="req"></param> /// <returns></returns> private bool HandleUpdate(RequestEventArgs e, NetworkRequest req) { try { var verb = new UpdateVerb(); verb.ProcessRequest(req); //Ignore updates about ourself if (verb.Nodes != null && verb.Nodes.Count == 1 && verb.Nodes[0].ID == serverNode.ID) { SendResponse(e, null); return(true); } //Is the call from a local client? ClientStream localClient = connectedClientNodes.ToList().Where( n => n.Node.ID == req.SourceID && n.Node.Secret == req.AuthKey && n.Node.NodeType != ClientType.Overlord).FirstOrDefault(); if (null != localClient) { //Only allow updates about itself Node client = verb.Nodes.Where(n => n.ID == localClient.Node.ID).FirstOrDefault(); if (null != client && verb.Nodes.Count == 1) { logger.Trace("Server got update from local client {0}", client.ID); lock (sync) { //Copy to local store foreach (var value in verb.Nodes[0].Data) { localClient.Node.SetData(value.Key, value.Value); } req.OverlordID = serverNode.ID; //Retransmit SendToOverlordClients(req); SendToStandardClients(req); //Has the client disconnected? if (!localClient.Node.Online) { localClient.Kill(); connectedClientNodes.Remove(localClient); } } SendResponse(e, null); return(true); } } else { //Is the update from an external overlord? Uplink overlord = extOverlordServers.ToList().Where( n => n.Destination.ID == req.OverlordID && n.Destination.Secret == req.AuthKey && n.Destination.NodeType == ClientType.Overlord).FirstOrDefault(); if (null != overlord) { logger.Trace("Server got update from external overlord {0}", overlord.Destination.ID); //Check each update var nverb = new UpdateVerb(); foreach (Node update in verb.Nodes) { if (!string.IsNullOrEmpty(update.ID)) { //Ignore updates about ourself if (update.ID == serverNode.ID) { continue; } lock (sync) { //Is the update about the overlord itself? Uplink osearch = extOverlordServers.Where( o => o.Destination.ID == update.ID && o.Destination.Secret == req.AuthKey). FirstOrDefault(); if (null != osearch) { logger.Trace("Server got update from external about itself: {0}", osearch.Destination.ID); //Copy to local store foreach (var value in update.Data) { osearch.Destination.SetData(value.Key, value.Value); } //Retransmit changes nverb.Nodes.Add(update); //Overlord going offline if (!osearch.Destination.Online) { osearch.OnDisconnect -= uplink_OnDisconnect; osearch.Kill(); //Remove associated external nodes foreach (Node enode in externalNodes.ToList()) { if (enode.OverlordID == osearch.Destination.OverlordID) { externalNodes.Remove(enode); //Only signal disconnect is the node isnt a local node //I.e. they connected locally without disconnecting externally. ClientStream search = connectedClientNodes.Where(n => n.Node.ID == enode.ID). FirstOrDefault(); if (null == search) { //The node isn't connected locally, is it connected elsewhere externally? Node bestExternal = externalNodes.ToList().Where(n => n.ID == enode.ID). OrderByDescending(n => n.LastUpdate).FirstOrDefault(); if (null != bestExternal) { //User has logged on elsewhere, update local clients of new details nverb.Nodes.Add(bestExternal); } else { nverb.Nodes.Add(new Node { ID = enode.ID, Online = false }); } } } } } } else { logger.Trace("Server got update from external server about : {0}", update.ID); //Check to see if the external node is connected locally, if so then dont retransmit changes but store changes under the relevant object ClientStream localNode = connectedClientNodes.Where(n => n.Node.ID == update.ID).FirstOrDefault(); //Update about an external node from an external overlord Node search = externalNodes.Where(n => n.ID == update.ID && n.OverlordID == req.OverlordID) .FirstOrDefault(); if (null == search) { if (!string.IsNullOrEmpty(update.ID)) { //New external node search = new Node(); //Copy to local store foreach (var value in update.Data) { search.SetData(value.Key, value.Value); } search.OverlordID = req.OverlordID; externalNodes.Add(search); //Dont retransmit external node as it is local if (null == localNode) { nverb.Nodes.Add(update); } } } else { //Copy to local store foreach (var value in update.Data) { search.SetData(value.Key, value.Value); } //Has the external node changed to a different overlord? if (search.OverlordID != req.OverlordID) { search.OverlordID = req.OverlordID; update.OverlordID = req.OverlordID; } //Dont retransmit external node as it is local if (null == localNode) { //Retransmit changes nverb.Nodes.Add(update); } } } } } } //Only transmit external node info to local clients if (nverb.Nodes.Count > 0) { NetworkRequest nreq = nverb.CreateRequest(); nreq.OverlordID = req.OverlordID; SendToStandardClients(nreq); } SendResponse(e, null); return(true); } } } catch { } logger.Debug("Server received an invalid update"); SendError(e); return(false); }