//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); } }
public void Transmit(byte to, string message) { DATA_MSG data_msg = new DATA_MSG(); data_msg.header_type = 1; data_msg.header_reserved = 0; data_msg.header_id = counterId++; data_msg.from = NodeAddress; data_msg.to = to; data_msg.parent = NodeAddress; data_msg.data = message; if (NeighborsTable.Contains(to) || RouteTable.ContainsKey(to)) { transmitRF(data_msg); } else { LookFor(to, 0, NodeAddress, 0); dataOutputBuffer.Add(data_msg); } }
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; } }