public NodeRecvModule() { var config = Node.config; //var adjNodes = new ArraySegment<string>(args, 2, args.Length - 2); Get("/{msg}", x => { lock (Node.nodeLock) { Message msg = new Message(x.msg); List <Message> msgsToSend = new List <Message>(); // Print received message Console.WriteLine(string.Format("... {0} {1} < {2} {3} {4} {5}", msg.time, Node.nodeId, msg.from, msg.to, (byte)msg.token, msg.payload)); // Terminate condition if (Node.nodeId == "1" && msg.token == TokenType.Return) { Console.WriteLine(string.Format("... {0} {1} > {2} {3} {4} {5}", msg.time, "1", "1", "0", (byte)msg.token, msg.payload + 1)); } // Mark incoming link as father if this is the first time we've received a token if (msg.token != TokenType.Vis && !Node.hasHadToken && msg.from != Node.netNodeId) { Node.links[msg.from].marker = MarkerType.Father; } // Handle receiving forward token if we've already had one if (msg.token == TokenType.Forward && Node.hasHadToken) { Node.links[msg.from].marker = MarkerType.Visited; } // Handle receiving visited token bool skipSendVisit = false; if (msg.token == TokenType.Vis && msg.from != Node.netNodeId) { Node.links[msg.from].marker = MarkerType.Visited; // Regerate last token / message conditions if we sent a forward token to a visited node if (msg.from == Node.lastNodeSentTokenTo) { msg = Node.savedMessage; Node.hasHadToken = false; skipSendVisit = true; } } // Handle receiving forward token if ((msg.token == TokenType.Forward && !Node.hasHadToken) || msg.token == TokenType.Return) { bool foundUnvisited = false; var nodeIds = new List <string>(Node.links.Keys); var fatherNodeId = ""; foreach (string nodeId in nodeIds) { // Find father node if (fatherNodeId == "" && Node.links[nodeId].marker == MarkerType.Father) { fatherNodeId = nodeId; } if (Node.links[nodeId].marker == MarkerType.Unvisited) { // Find first unvisited node if (!foundUnvisited) { // If we found one, then send a forward token and mark the link as a son foundUnvisited = true; msgsToSend.Add(new Message(msg.time, Node.nodeId, nodeId, TokenType.Forward, msg.payload)); Node.links[nodeId].marker = MarkerType.Son; // Save the forward token / messge in case we need to regenerate it later Node.savedMessage = msg; Node.lastNodeSentTokenTo = nodeId; } // Send vis token on all other unvisited nodes. // Skip this if token is a return token else if (msg.token != TokenType.Return && !skipSendVisit) { msgsToSend.Add(new Message(msg.time, Node.nodeId, nodeId, TokenType.Vis, 0)); } } // Send visited token over all visited links to inform neighbors that they should mark this node visited if (Node.links[nodeId].marker == MarkerType.Visited && msg.token != TokenType.Return && !skipSendVisit) { msgsToSend.Add(new Message(msg.time, Node.nodeId, nodeId, TokenType.Vis, 0)); } } // If we have no unvisited nodes, then send a return token on the father link if (!foundUnvisited && fatherNodeId != "") { msgsToSend.Add(new Message(msg.time, Node.nodeId, fatherNodeId, TokenType.Return, msg.payload + 1)); } // Print sent messages foreach (Message msgToSend in msgsToSend) { Console.WriteLine(string.Format("... {0} {1} > {2} {3} {4} {5}", msg.time, Node.nodeId, msgToSend.from, msgToSend.to, (byte)msgToSend.token, msgToSend.payload)); } // Record that we have seen the token already in case it gets returned to us Node.hasHadToken = true; // Send messages as bundle to net node if (msgsToSend.Count > 0) { var msgBundle = new MsgBundle(msgsToSend); var bundleClient = new WebClient(); bundleClient.DownloadStringAsync(new Uri("http://localhost:" + Node.netNodePort + "/" + msgBundle.Serialize())); } } } return(""); }); }
public NetRecvModule() { Get("/{msg}", x => { var msgBundle = new MsgBundle(x.msg); // Add messages to queue along with their time-to-send foreach (var msg in msgBundle.msgList) { // Print received messages Console.WriteLine(string.Format("... {0} {1} < {2} {3} {4} {5}", Net.time, Net.nodeId, msg.from, msg.to, (byte)msg.token, msg.payload)); // Get message delay var delayConfigKey = msg.from + "-" + msg.to; uint delay; if (Net.config.ContainsKey(delayConfigKey)) { delay = UInt32.Parse(Net.config[delayConfigKey]); } else { delay = UInt32.Parse(Net.config["-"]); } var timeToSend = Net.time + delay; // Add message to queue and sort Net.msgSendQueue.Enqueue(Tuple.Create(msg, timeToSend)); Net.msgSendQueue = new Queue <Tuple <Message, uint> >(Net.msgSendQueue.OrderBy(elem => elem.Item2)); } // Until we've sent a forward or return token, or the queue is empty bool shouldStopSending = false; var msgsToSend = new List <Message>(); while (Net.msgSendQueue.Count > 0 && !shouldStopSending) { // Update current time from top of message queue Net.time = Net.msgSendQueue.Peek().Item2; // Pop all messages to be sent at this timepoint while (Net.msgSendQueue.Count > 0 && Net.msgSendQueue.Peek().Item2 == Net.time) { var msgTimePair = Net.msgSendQueue.Dequeue(); var msgToSend = msgTimePair.Item1; msgToSend.time = msgTimePair.Item2; msgsToSend.Add(msgToSend); // Check if we should stop sending messages and wait for new messages to arrive if (msgToSend.token == TokenType.Forward || msgToSend.token == TokenType.Return) { // flush queue if we're returning the token back to the initiator (hard coded to id 1) if (msgToSend.to == "1") { shouldStopSending = false; } else { shouldStopSending = true; // Need to handle case where a node has sent a token to a node that should have been marked as visited by the sender. // But due to network delays, the node is still marked as unvisited by the sending node. // Search for matching visited token in the queue going in reverse direction to the main token. foreach (var queuedMsgTimePair in Net.msgSendQueue) { var queuedMsg = queuedMsgTimePair.Item1; if (queuedMsg.token == TokenType.Vis && queuedMsg.from == msgToSend.to && queuedMsg.to == msgToSend.from) { shouldStopSending = false; } } } } // Print sent messages Console.WriteLine(string.Format("... {0} {1} > {2} {3} {4} {5}", Net.time, Net.nodeId, msgToSend.from, msgToSend.to, (byte)msgToSend.token, msgToSend.payload)); // Terminate condition if (msgToSend.to == "1" && msgToSend.token == TokenType.Return) { Console.WriteLine(string.Format("... {0} {1} < {2} {3} {4} {5}", msgToSend.time, "0", "1", "0", (byte)msgToSend.token, msgToSend.payload + 1)); } } } // Send after popping from queue to avoid ping back forward tokens potentially concurrently modifying the queue foreach (var msgToSend in msgsToSend) { var sendPort = Net.config[msgToSend.to]; var sendClient = new WebClient(); sendClient.DownloadStringAsync(new Uri("http://localhost:" + sendPort + "/" + msgToSend.Serialize())); } return(""); }); }