//This method is used to send a message to THIS node public void SendMessage(MSG message) { if (message is DATA_MSG) { DATA_MSG msgCopy = new DATA_MSG(); msgCopy.raw_bytes = ((DATA_MSG)message).raw_bytes; dataInputBuffer.Add(msgCopy); } else { ROUTE_MSG msgCopy = new ROUTE_MSG(); msgCopy.raw_bytes = ((ROUTE_MSG)message).raw_bytes; routeBuffer.Add(msgCopy); } }
private void LookFor(byte reference, byte neighborInterested, byte rootInterested, byte distance) //RootInterested represent the first interesed, who start the interrogation { //This occur when many neighbors ask for the same node if (LookTable.ContainsKey(reference)) { return; } //This check prevents a node with no neighbors store a search in lookTable if (neighborInterested == 0 || NeighborsTable.Count > 1) { LookTable.Add(reference, new byte[] { neighborInterested, 0, (byte)(distance - 1) }); //Send RouteAnswer to everyone in NeighborsTable != neighborInterested lock (NeighborsTable) { foreach (byte neigborAddress in NeighborsTable) { if (neigborAddress != neighborInterested) { NodeuC neigbor = Program.GetNode(neigborAddress); ROUTE_MSG routeAnswer = new ROUTE_MSG(); routeAnswer.header_distance = distance; routeAnswer.header_restype = 1; //ANSWER routeAnswer.header_type = 0; //ROUTE routeAnswer.from = rootInterested; routeAnswer.to = neigborAddress; routeAnswer.parent = NodeAddress; routeAnswer.reference = reference; neigbor.SendMessage(routeAnswer); } } } } }
private void loop() { TimeSpan iterationTime = new TimeSpan(DateTime.Now.Ticks); refreshNeigbors(); if (routeBuffer.Count > 0) //check the outstanding route messages { ROUTE_MSG message = routeBuffer[0]; if (message.header_restype == 1) //Route Answer { bool isNeighbor = NeighborsTable.Contains(message.reference); //Check if the first variable returns true, because in this case the second search is not needed if (isNeighbor || RouteTable.ContainsKey(message.reference)) { ROUTE_MSG routeResponse = new ROUTE_MSG(); if (isNeighbor) { routeResponse.header_distance = 1; } else { routeResponse.header_distance = (byte)(RouteTable[message.reference][1] + 1); } routeResponse.header_restype = 0; //RESPONSE routeResponse.header_type = 0; //ROUTE routeResponse.header_ok = 1; routeResponse.from = NodeAddress; routeResponse.to = message.from; routeResponse.parent = NodeAddress; routeResponse.reference = message.reference; NodeuC Dest = Program.GetNode(message.parent); Dest.SendMessage(routeResponse); //TODO: Notify the node sought to avoid a possible subsequent search in the opposite routeResponse.header_distance = (byte)(message.header_distance + 1); routeResponse.from = NodeAddress; routeResponse.to = message.reference; routeResponse.parent = NodeAddress; routeResponse.reference = message.from; Dest = Program.GetNode(isNeighbor ? message.reference : RouteTable[message.reference][0]); Dest.SendMessage(routeResponse); addToRouteTable(message.from, message.parent, message.header_distance); } else { LookFor(message.reference, message.parent, message.from, (byte)(message.header_distance + 1)); } Color = Color.Yellow; } else //Route Response { if (message.header_ok > 0) { addToRouteTable(message.reference, message.parent, message.header_distance); if (LookTable.ContainsKey(message.reference)) { byte interested = LookTable[message.reference][0]; if (interested != 0) { ROUTE_MSG routeResponse = new ROUTE_MSG(); routeResponse.header_distance = (byte)(message.header_distance + 1); routeResponse.header_restype = 0; //RESPONSE routeResponse.header_type = 0; //ROUTE routeResponse.header_ok = 1; routeResponse.from = message.from; routeResponse.to = message.to; routeResponse.parent = NodeAddress; routeResponse.reference = message.reference; NodeuC Dest = Program.GetNode(interested); Dest.SendMessage(routeResponse); //Store the way back if distance > 0 (message.to is not a neighbor) byte distance = LookTable[message.reference][2]; if (distance > 0) { addToRouteTable(message.to, interested, distance); } } LookTable.Remove(message.reference); Color = Color.Purple; } } //This case is given when it tried to route a message from a node that is no longer able to reach the recipient. else if (RouteTable.ContainsKey(message.reference) && RouteTable[message.reference][0] == message.parent) { RouteTable.Remove(message.reference); //Notify the neighbors that I can't reach the intended recipient foreach (var neighborAddress in NeighborsTable) { if (message.parent != neighborAddress) { ROUTE_MSG routeResponse = new ROUTE_MSG(); routeResponse.header_restype = 0; //RESPONSE routeResponse.header_type = 0; //ROUTE routeResponse.header_ok = 0; //FAIL routeResponse.header_distance = message.header_distance; routeResponse.from = NodeAddress; routeResponse.to = message.to; routeResponse.parent = NodeAddress; routeResponse.reference = message.reference; NodeuC Dest = Program.GetNode(neighborAddress); Dest.SendMessage(routeResponse); } } //TODO: If there are pending messages for this node, try to trace a new route if (message.to == NodeAddress) { Program.MessageBoxCustom("Ha cambiado la topología de la red. Reenviar", "MESSAGE " + message.header_distance + " FROM " + NodeAddress + " TO " + message.reference + " "); } } } routeBuffer.Remove(message); } if (dataInputBuffer.Count > 0)//Data messages to read { Color = Color.YellowGreen; DATA_MSG message = dataInputBuffer[0]; bool isNeighbor; if (message.to == NodeAddress) //it's to me? { Color = Color.Magenta; message.data += NodeAddress; Program.MessageBoxCustom(message.data, "MESSAGE " + message.header_id + " FROM " + message.from + " TO " + message.to + " BY " + message.parent + " "); } else if ((isNeighbor = NeighborsTable.Contains(message.to)) || RouteTable.ContainsKey(message.to)) { message.parent = NodeAddress; message.data += NodeAddress + " -> "; NodeuC Dest = Program.GetNode(isNeighbor ? message.to : RouteTable[message.to][0]); Dest.SendMessage(message); } else { ROUTE_MSG routeResponse = new ROUTE_MSG(); routeResponse.header_restype = 0; //RESPONSE routeResponse.header_type = 0; //ROUTE routeResponse.header_ok = 0; //FAIL routeResponse.header_distance = message.header_id; //Use the length field to store the id of the failed message routeResponse.from = NodeAddress; routeResponse.to = message.from; routeResponse.parent = NodeAddress; routeResponse.reference = message.to; NodeuC Dest = Program.GetNode(message.parent); Dest.SendMessage(routeResponse); } dataInputBuffer.Remove(message); } if (dataOutputBuffer.Count > 0)//Messages to send { List <DATA_MSG> items = dataOutputBuffer.ToList(); foreach (var message in items) { if (!LookTable.ContainsKey(message.to))//Look finished { transmitRF(message); dataOutputBuffer.Remove(message); } else if (LookTable[message.to][1] >= TIMEOUT) { Program.MessageBoxCustom("Timeout superado", "MESSAGE FROM " + message.from + " TO " + message.to + " "); dataOutputBuffer.Remove(message); LookTable.Remove(message.to); } } } int diff = (int)(iterationTime - lastLookTableUpdate).TotalMilliseconds; if (diff > 1000 && LookTable.Count > 0) //Check the pending searches every second { foreach (var item in LookTable.ToList()) { byte reference = item.Key; byte counter = item.Value[1]; if (counter < TIMEOUT) { LookTable[reference][1]++; } else { LookTable.Remove(reference); //TIMEOUT limit exceeded } } lastLookTableUpdate = iterationTime; } }
private void loop() { TimeSpan iterationTime = new TimeSpan(DateTime.Now.Ticks); refreshNeigbors(); if (routeBuffer.Count > 0) //check the outstanding route messages { ROUTE_MSG message = routeBuffer[0]; if (message.header_restype == 1) //Route Answer { bool isNeighbor = NeighborsTable.Contains(message.reference); //Check if the first variable returns true, because in this case the second search is not needed if (isNeighbor || RouteTable.ContainsKey(message.reference)) { ROUTE_MSG routeResponse = new ROUTE_MSG(); if (isNeighbor) routeResponse.header_distance = 1; else routeResponse.header_distance = (byte)(RouteTable[message.reference][1] + 1); routeResponse.header_restype = 0;//RESPONSE routeResponse.header_type = 0;//ROUTE routeResponse.header_ok = 1; routeResponse.from = NodeAddress; routeResponse.to = message.from; routeResponse.parent = NodeAddress; routeResponse.reference = message.reference; NodeuC Dest = Program.GetNode(message.parent); Dest.SendMessage(routeResponse); //TODO: Notify the node sought to avoid a possible subsequent search in the opposite routeResponse.header_distance = (byte)(message.header_distance + 1); routeResponse.from = NodeAddress; routeResponse.to = message.reference; routeResponse.parent = NodeAddress; routeResponse.reference = message.from; Dest = Program.GetNode(isNeighbor ? message.reference : RouteTable[message.reference][0]); Dest.SendMessage(routeResponse); addToRouteTable(message.from, message.parent, message.header_distance); } else { LookFor(message.reference, message.parent, message.from, (byte)(message.header_distance + 1)); } Color = Color.Yellow; } else //Route Response { if (message.header_ok > 0) { addToRouteTable(message.reference, message.parent, message.header_distance); if (LookTable.ContainsKey(message.reference)) { byte interested = LookTable[message.reference][0]; if (interested != 0) { ROUTE_MSG routeResponse = new ROUTE_MSG(); routeResponse.header_distance = (byte)(message.header_distance + 1); routeResponse.header_restype = 0;//RESPONSE routeResponse.header_type = 0;//ROUTE routeResponse.header_ok = 1; routeResponse.from = message.from; routeResponse.to = message.to; routeResponse.parent = NodeAddress; routeResponse.reference = message.reference; NodeuC Dest = Program.GetNode(interested); Dest.SendMessage(routeResponse); //Store the way back if distance > 0 (message.to is not a neighbor) byte distance = LookTable[message.reference][2]; if(distance > 0) addToRouteTable(message.to, interested, distance); } LookTable.Remove(message.reference); Color = Color.Purple; } } //This case is given when it tried to route a message from a node that is no longer able to reach the recipient. else if (RouteTable.ContainsKey(message.reference) && RouteTable[message.reference][0] == message.parent) { RouteTable.Remove(message.reference); //Notify the neighbors that I can't reach the intended recipient foreach (var neighborAddress in NeighborsTable) { if (message.parent != neighborAddress) { ROUTE_MSG routeResponse = new ROUTE_MSG(); routeResponse.header_restype = 0;//RESPONSE routeResponse.header_type = 0;//ROUTE routeResponse.header_ok = 0;//FAIL routeResponse.header_distance = message.header_distance; routeResponse.from = NodeAddress; routeResponse.to = message.to; routeResponse.parent = NodeAddress; routeResponse.reference = message.reference; NodeuC Dest = Program.GetNode(neighborAddress); Dest.SendMessage(routeResponse); } } //TODO: If there are pending messages for this node, try to trace a new route if (message.to == NodeAddress) { Program.MessageBoxCustom("Ha cambiado la topología de la red. Reenviar", "MESSAGE "+message.header_distance+ " FROM " + NodeAddress + " TO " + message.reference + " "); } } } routeBuffer.Remove(message); } if (dataInputBuffer.Count > 0)//Data messages to read { Color = Color.YellowGreen; DATA_MSG message = dataInputBuffer[0]; bool isNeighbor; if (message.to == NodeAddress) //it's to me? { Color = Color.Magenta; message.data += NodeAddress; Program.MessageBoxCustom(message.data, "MESSAGE " + message.header_id + " FROM " + message.from + " TO " + message.to + " BY " + message.parent + " "); } else if ((isNeighbor = NeighborsTable.Contains(message.to)) || RouteTable.ContainsKey(message.to)) { message.parent = NodeAddress; message.data += NodeAddress + " -> "; NodeuC Dest = Program.GetNode(isNeighbor ? message.to : RouteTable[message.to][0]); Dest.SendMessage(message); } else { ROUTE_MSG routeResponse = new ROUTE_MSG(); routeResponse.header_restype = 0;//RESPONSE routeResponse.header_type = 0;//ROUTE routeResponse.header_ok = 0;//FAIL routeResponse.header_distance = message.header_id;//Use the length field to store the id of the failed message routeResponse.from = NodeAddress; routeResponse.to = message.from; routeResponse.parent = NodeAddress; routeResponse.reference = message.to; NodeuC Dest = Program.GetNode(message.parent); Dest.SendMessage(routeResponse); } dataInputBuffer.Remove(message); } if (dataOutputBuffer.Count > 0)//Messages to send { List<DATA_MSG> items = dataOutputBuffer.ToList(); foreach (var message in items) { if (!LookTable.ContainsKey(message.to))//Look finished { transmitRF(message); dataOutputBuffer.Remove(message); } else if (LookTable[message.to][1] >= TIMEOUT) { Program.MessageBoxCustom("Timeout superado", "MESSAGE FROM " + message.from + " TO " + message.to + " "); dataOutputBuffer.Remove(message); LookTable.Remove(message.to); } } } int diff = (int)(iterationTime - lastLookTableUpdate).TotalMilliseconds; if (diff > 1000 && LookTable.Count > 0) //Check the pending searches every second { foreach (var item in LookTable.ToList()) { byte reference = item.Key; byte counter = item.Value[1]; if (counter < TIMEOUT) LookTable[reference][1]++; else LookTable.Remove(reference); //TIMEOUT limit exceeded } lastLookTableUpdate = iterationTime; } }
//RootInterested represent the first interesed, who start the interrogation private void LookFor(byte reference, byte neighborInterested, byte rootInterested, byte distance) { //This occur when many neighbors ask for the same node if (LookTable.ContainsKey(reference)) return; //This check prevents a node with no neighbors store a search in lookTable if (neighborInterested== 0 || NeighborsTable.Count > 1) { LookTable.Add(reference, new byte[] { neighborInterested, 0, (byte)(distance - 1) }); //Send RouteAnswer to everyone in NeighborsTable != neighborInterested lock (NeighborsTable) { foreach (byte neigborAddress in NeighborsTable) { if (neigborAddress != neighborInterested) { NodeuC neigbor = Program.GetNode(neigborAddress); ROUTE_MSG routeAnswer = new ROUTE_MSG(); routeAnswer.header_distance = distance; routeAnswer.header_restype = 1;//ANSWER routeAnswer.header_type = 0;//ROUTE routeAnswer.from = rootInterested; routeAnswer.to = neigborAddress; routeAnswer.parent = NodeAddress; routeAnswer.reference = reference; neigbor.SendMessage(routeAnswer); } } } } }