public void Send(ICopyable data) { ConnectionList cl = Node.ConnectionTable.GetConnections(ConnectionType.Structured); // We start with the node immediately after the starting index int start = cl.IndexOf(From); if (start < 0) { start = ~start; } // We end with the node immediately before the end index int end = cl.IndexOf(To); if (end < 0) { end = ~end; } // If start >= end, because From < To or because this is a terminal // node and there are no other entities to forward it to. So the // second test ensures that the first entity is actually inside the // range to forward it to. AHAddress start_addr = cl[start].Address as AHAddress; if (start >= end && start_addr.IsBetweenFromLeft(From, To)) { end += cl.Count; } List <Connection> cons = SortByDistance(cl, start, end, Forwarders); for (int i = 0; i < cons.Count; i++) { Connection con = cons[i]; int next = i + 1; AHAddress nfrom = con.Address as AHAddress; Address nto = To; if (next < cons.Count) { nto = GetLeftNearTarget(cons[next].Address as AHAddress); } con.Edge.Send(new CopyList(PType, Source.ToMemBlock(), nfrom.ToMemBlock(), nto.ToMemBlock(), _forwarders, _hops, data)); } _sent_to = cons.Count; }
/// <summary>Performs the bounded broadcast using recursion.</summary> public int BoundedBroadcast(AHAddress caller, AHAddress from, AHAddress to) { GraphNode node = _addr_to_node[from]; ConnectionList cl = node.ConnectionTable.GetConnections(ConnectionType.Structured); // We start with the node immediately after the starting index int start = cl.IndexOf(from); if (start < 0) { start = ~start; } // We end with the node immediately before the end index int end = cl.IndexOf(to); if (end < 0) { end = ~end; } // Ensure we wrap around as necessary if (start > end && GetNearTarget(from).IsBetweenFromRight(to, from)) { end += cl.Count; } int max_delay = 0; for (int i = start; i < end; i++) { AHAddress nfrom = cl[i].Address as AHAddress; AHAddress nto = GetLeftNearTarget(cl[i + 1].Address as AHAddress); // If this is the last one, just have him query to 'to' if (i == end - 1) { nto = to; } // recursion, yuck int delay = BoundedBroadcast(from, nfrom, nto); // We send a message and potentially the peer does as well max_delay = delay > max_delay ? delay : max_delay; } // Return our delay and the bytes cost for sending to us return(max_delay + SendPacket(caller, from)[0].Delay); }
protected Connection GetConnection(Address addr) { ConnectionList cons = _node.ConnectionTable.GetConnections(ConnectionType.Structured); int index = cons.IndexOf(addr); if (index < 0) { return(null); } return(cons[index]); }
public override Pair <Connection, bool> NextConnection(Edge from, AHHeader head) { Address dest = head.Destination; int d_idx = _structs.IndexOf(dest); Connection next_con; if (d_idx >= 0) { //We have a direct connection: next_con = _structs[d_idx]; } else { //We have to check the right and the left: var ah_dest = (AHAddress)dest; int left_idx = ~d_idx; Connection l_c = _structs[left_idx]; int right_idx = left_idx - 1; Connection r_c = _structs[right_idx]; if (ah_dest.IsCloserToFirst((AHAddress)l_c.Address, (AHAddress)r_c.Address)) { next_con = l_c; } else { next_con = r_c; } /* * Note, DO NOT DO COMPARISONS WITH INDEX VALUES!!!!! * do the the wrap around, _structs[x] == _structs[y] * when x = y + k * _structs.Count for all k, so equality * of Connection is not the same as equality of index */ if (head.Hops >= head.Ttl) { //Only deliver if we are the closest or last mode: bool local = next_con == _local_con || head.Opts == AHHeader.Options.Last; if (local) { return(_LOCAL); } else { return(_NO_ONE); } } } return(next_con == _local_con ? _LOCAL : new Pair <Connection, bool>(next_con, false)); }
/// <summary>Performs a broadcast to the entire overlay.</summary> public int Broadcast(AHAddress from) { GraphNode node = _addr_to_node[from]; ConnectionList cl = node.ConnectionTable.GetConnections(ConnectionType.Structured); int index = cl.IndexOf(from); if (index < 0) { index = ~index; } AHAddress start = cl[index].Address as AHAddress; return(BoundedBroadcast(from, start, GetLeftNearTarget(from))); }
/// <summary>First we try to find a third party we can connect with for /// overlap, if that is successful, we attempt to connect to him, if that /// is successful, we create a new tunnel edge.</summary> protected void AttemptToCreateOverlap(RelayEdgeCallbackAction teca) { WaitCallback create_connection = delegate(object o) { Address target = o as Address; if (o == null) { FailedEdgeCreate(teca); return; } ConnectionList cons = _connections; int index = cons.IndexOf(target); if (index < 0) { FailedEdgeCreate(teca); return; } List <Connection> overlap = new List <Connection>(1); overlap.Add(cons[index]); CreateEdge(teca, overlap); }; Channel chan = new Channel(1); chan.CloseEvent += delegate(object o, EventArgs ea) { Address target = null; try { IDictionary msg = (chan.Dequeue() as RpcResult).Result as IDictionary; target = _ito.EvaluatePotentialOverlap(msg); } catch { } if (target == null) { FailedEdgeCreate(teca); } else { _oco.ConnectTo(target, create_connection); } }; ISender s = new AHExactSender(_node, teca.RelayTA.Target); try { _node.Rpc.Invoke(s, chan, "tunnel.RequestSync"); } catch { chan.Close(); } }
protected void FindOverlapWorker(Node node1, Node node2) { ConnectionList cl = node1.ConnectionTable.GetConnections(ConnectionType.Structured); IEnumerable ov = node1.ConnectionTable.GetConnections(Relay.OverlapConnectionOverlord.STRUC_OVERLAP); foreach (Connection ov_con in ov) { int index = cl.IndexOf(ov_con.Address); if (index < 0) { Console.WriteLine("No matching pair for overlap..."); continue; } Connection con = cl[index]; int delay = (ov_con.State.Edge as SimulationEdge).Delay + (con.State.Edge as SimulationEdge).Delay; Console.WriteLine("Delay: " + delay); } }
/// <summary>Returns a Tunnel Sync message containing up to 40 addresses /// first starting with previous overlap followed by new potential /// connections for overlap.</summary> public virtual IDictionary GetSyncMessage(IList <Connection> current_overlap, Address local_addr, ConnectionList cons) { Hashtable ht = new Hashtable(); DateTime now = DateTime.UtcNow; if (current_overlap != null) { foreach (Connection con in current_overlap) { Hashtable info = new Hashtable(2); info["ta"] = TransportAddress.TATypeToString(con.Edge.TAType); info["ct"] = (int)(now - con.CreationTime).TotalMilliseconds; ht[con.Address.ToMemBlock()] = info; } } int idx = cons.IndexOf(local_addr); if (idx < 0) { idx = ~idx; } int max = cons.Count < 16 ? cons.Count : 16; int start = idx - max / 2; int end = idx + max / 2; for (int i = start; i < end; i++) { Connection con = cons[i]; MemBlock key = con.Address.ToMemBlock(); if (ht.Contains(key)) { continue; } Hashtable info = new Hashtable(); info["ta"] = TransportAddress.TATypeToString(con.Edge.TAType); info["ct"] = (int)(now - con.CreationTime).TotalMilliseconds; ht[key] = info; } return(ht); }
public DirectionalRouting(AHAddress local, ConnectionList structs) { _NULL_TRUE = new Pair <Connection, bool>(null, true); _NULL_FALSE = new Pair <Connection, bool>(null, false); Connection left_c = null; Connection right_c = null; if (structs.Count > 0) { int local_idx = ~structs.IndexOf(local); int left_idx = local_idx; int right_idx = left_idx - 1; left_c = structs[left_idx]; right_c = structs[right_idx]; } _LEFT_FALSE = new Pair <Connection, bool>(left_c, false); _RIGHT_FALSE = new Pair <Connection, bool>(right_c, false); _LEFT_TRUE = new Pair <Connection, bool>(left_c, true); _RIGHT_TRUE = new Pair <Connection, bool>(right_c, true); }
/// <summary>Returns the oldest 4 addresses in the overlap.</summary> public virtual List <Connection> EvaluateOverlap(ConnectionList cons, IDictionary msg) { List <Connection> overlap = new List <Connection>(); foreach (DictionaryEntry de in msg) { MemBlock key = de.Key as MemBlock; if (key == null) { key = MemBlock.Reference((byte[])de.Key); } Address addr = new AHAddress(key); int index = cons.IndexOf(addr); if (index < 0) { continue; } Connection con = cons[index]; // Since there are no guarantees about routing over two tunnels, we do // not consider cases where we are connected to the overlapping tunnels // peers via tunnels if (con.Edge.TAType.Equals(TransportAddress.TAType.Tunnel)) { Hashtable values = de.Value as Hashtable; TransportAddress.TAType tatype = TransportAddressFactory.StringToType(values["ta"] as string); if (tatype.Equals(TransportAddress.TAType.Tunnel)) { continue; } } overlap.Add(con); } return(GetOldest(overlap)); }
/// <summary> /// changes the index of currently selected RDPConnection in list /// </summary> /// <param name="steps">steps to move index</param> private void MoveItemInConnectionlist(int steps) { int currentIndex = ConnectionList.IndexOf(SelectedRDPConnection); int newIndex = currentIndex + steps; if (newIndex < 0) { newIndex = 0; } else { int lastIndex = ConnectionList.IndexOf(ConnectionList.Last()); if (newIndex > lastIndex) { newIndex = lastIndex; } } if (currentIndex != newIndex) { ConnectionList.Move(currentIndex, newIndex); NotifyPropertyChanged("ConnectionList"); } }
/// <summary>Returns the four fastest in the overlap.</summary> public override List<Connection> EvaluateOverlap(ConnectionList cons, IDictionary msg) { List<Connection> overlap = new List<Connection>(); foreach(DictionaryEntry de in msg) { MemBlock key = de.Key as MemBlock; if(key == null) { key = MemBlock.Reference((byte[]) de.Key); } Address addr = new AHAddress(key); int index = cons.IndexOf(addr); if(index < 0) { continue; } Connection con = cons[index]; // Since there are no guarantees about routing over two tunnels, we do // not consider cases where we are connected to the overlapping tunnels // peers via tunnels if(con.Edge.TAType.Equals(TransportAddress.TAType.Tunnel)) { Hashtable values = de.Value as Hashtable; TransportAddress.TAType tatype = TransportAddressFactory.StringToType(values["ta"] as string); if(tatype.Equals(TransportAddress.TAType.Tunnel)) { continue; } } overlap.Add(con); } return GetClosest(overlap); }
public DirectionalRouting(AHAddress local, ConnectionList structs) { _NULL_TRUE = new Pair<Connection, bool>(null, true); _NULL_FALSE = new Pair<Connection, bool>(null, false); Connection left_c = null; Connection right_c = null; if( structs.Count > 0) { int local_idx = ~structs.IndexOf(local); int left_idx = local_idx; int right_idx = left_idx - 1; left_c = structs[left_idx]; right_c = structs[right_idx]; } _LEFT_FALSE = new Pair<Connection, bool>(left_c, false); _RIGHT_FALSE = new Pair<Connection, bool>(right_c, false); _LEFT_TRUE = new Pair<Connection, bool>(left_c, true); _RIGHT_TRUE = new Pair<Connection, bool>(right_c, true); }
/// <summary>Returns a Relay Sync message containing up to 40 addresses /// first starting with previous overlap followed by new potential /// connections for overlap.</summary> public virtual IDictionary GetSyncMessage(IList<Connection> current_overlap, Address local_addr, ConnectionList cons) { Hashtable ht = new Hashtable(); DateTime now = DateTime.UtcNow; if(current_overlap != null) { foreach(Connection con in current_overlap) { Hashtable info = new Hashtable(2); info["ta"] = TransportAddress.TATypeToString(con.State.Edge.TAType); info["ct"] = (int) (now - con.CreationTime).TotalMilliseconds; ht[con.Address.ToMemBlock()] = info; } } int idx = cons.IndexOf(local_addr); if(idx < 0) { idx = ~idx; } int max = cons.Count < 16 ? cons.Count : 16; int start = idx - max / 2; int end = idx + max / 2; for(int i = start; i < end; i++) { Connection con = cons[i]; MemBlock key = con.Address.ToMemBlock(); if(ht.Contains(key)) { continue; } Hashtable info = new Hashtable(); info["ta"] = TransportAddress.TATypeToString(con.State.Edge.TAType); info["ct"] = (int) (now - con.CreationTime).TotalMilliseconds; ht[key] = info; } return ht; }
/** * Generates tree for bounded broadcast. Algorithm works as follows: * The goal is to broadcast to all nodes in range [local_address, end). * Given a range [local_address, b), determine all connections that belong to this range. * Let the connections be b_1, b_2, ..... b_n. * To connection bi assign the range [b_i, b_{i+1}). * To the connection bn assign range [b_n, end).] */ public override void GenerateTree(Channel q, MapReduceArgs mr_args) { object gen_arg = mr_args.GenArg; string end_range = gen_arg as string; Log("generating child tree, range end: {0}.", end_range); AHAddress end_addr = (AHAddress)AddressParser.Parse(end_range); AHAddress start_addr = _node.Address as AHAddress; //we are at the start node, here we go: ConnectionTable tab = _node.ConnectionTable; ConnectionList structs = tab.GetConnections(ConnectionType.Structured); ArrayList retval = new ArrayList(); if (structs.Count > 0) { Connection curr_con = structs.GetLeftNeighborOf(_node.Address); int curr_idx = structs.IndexOf(curr_con.Address); //keep going until we leave the range int count = 0; ArrayList con_list = new ArrayList(); while (count++ < structs.Count && ((AHAddress)curr_con.Address).IsBetweenFromLeft(start_addr, end_addr)) { con_list.Add(curr_con); //Log("adding connection: {0} to list.", curr_con.Address); curr_idx = (curr_idx + 1) % structs.Count; curr_con = structs[curr_idx]; } Log("{0}: {1}, number of child connections: {2}", this.TaskName, _node.Address, con_list.Count); for (int i = 0; i < con_list.Count; i++) { MapReduceInfo mr_info = null; ISender sender = null; Connection con = (Connection)con_list[i]; sender = (ISender)con.Edge; //check if last connection if (i == con_list.Count - 1) { mr_info = new MapReduceInfo((ISender)sender, new MapReduceArgs(this.TaskName, mr_args.MapArg, //map argument end_range, //generate argument mr_args.ReduceArg //reduce argument )); Log("{0}: {1}, adding address: {2} to sender list, range end: {3}", this.TaskName, _node.Address, con.Address, end_range); retval.Add(mr_info); } else { string child_end = ((Connection)con_list[i + 1]).Address.ToString(); mr_info = new MapReduceInfo(sender, new MapReduceArgs(this.TaskName, mr_args.MapArg, child_end, mr_args.ReduceArg)); Log("{0}: {1}, adding address: {2} to sender list, range end: {3}", this.TaskName, _node.Address, con.Address, child_end); retval.Add(mr_info); } } } q.Enqueue(retval.ToArray(typeof(MapReduceInfo))); }
/// <summary>Make sure there are no entries in the Dht, who we should be /// connected to, but aren't.</summary> protected void CheckAndUpdateRemoteTAs(List <TransportAddress> tas) { AHAddress right = null, left = null; BigInteger right_dist = null, left_dist = null; AHAddress addr = _node.Address as AHAddress; // Find the closest left and right nodes foreach (TransportAddress ta in tas) { AHAddress target = (ta as SubringTransportAddress).Target; if (target.Equals(addr)) { continue; } BigInteger ldist = addr.LeftDistanceTo(target); BigInteger rdist = addr.RightDistanceTo(target); if (left_dist == null || ldist < left_dist) { left_dist = ldist; left = target; } if (right_dist == null || rdist < right_dist) { right_dist = rdist; right = target; } } ConnectionList cl = _node.ConnectionTable.GetConnections(ConnectionType.Structured); int local_idx = ~cl.IndexOf(_node.Address); if (left != null) { int remote_idx = ~cl.IndexOf(left); // If we're not connected to the left closest and its closer than any // of our current peers, let's connect to it if (remote_idx > 0 && Math.Abs(local_idx - remote_idx) < 2) { List <TransportAddress> tmp_tas = new List <TransportAddress>(1); tmp_tas.Add(new SubringTransportAddress(left, _shared_namespace)); Linker linker = new Linker(_node, null, tmp_tas, "leaf", addr.ToString()); linker.Start(); } } if (right != null && right != left) { int remote_idx = ~cl.IndexOf(right); // If we're not connected to the right closest and its closer than any // of our current peers, let's connect to it if (remote_idx > 0 && Math.Abs(local_idx - remote_idx) < 2) { List <TransportAddress> tmp_tas = new List <TransportAddress>(1); tas.Add(new SubringTransportAddress(right, _shared_namespace)); Linker linker = new Linker(_node, null, tmp_tas, "leaf", addr.ToString()); linker.Start(); } } UpdateRemoteTAs(tas); }
/// <summary>Where data packets prepended with a tunnel come. Here we /// receive data as well as create new RelayEdges.</summary> public void HandleData(MemBlock data, ISender return_path, object state) { AHSender ah_from = return_path as AHSender; ForwardingSender fs_from = return_path as ForwardingSender; AHAddress target = null; if (ah_from == null) { if (fs_from == null) { return; } target = (AHAddress)fs_from.Destination; } else { target = (AHAddress)ah_from.Destination; } int remote_id = NumberSerializer.ReadInt(data, 0); int local_id = NumberSerializer.ReadInt(data, 4); RelayEdge te = null; // No locally assigned ID, so we'll create a new RelayEdge and assign it one. // This could be hit many times by the same RemoteID, but it is safe since // we'll attempt Linkers on all of them and he'll only respond to the first // one he receives back. if (local_id == -1) { if (fs_from == null) { throw new Exception("No LocalID assigned but not from a useful sender!"); } ConnectionList cons = _connections; int index = cons.IndexOf(fs_from.Forwarder); if (index < 0) { return; } List <Connection> overlap_addrs = new List <Connection>(); overlap_addrs.Add(cons[index]); while (true) { te = new RelayEdge(this, (RelayTransportAddress)_local_tas[0], new RelayTransportAddress(target, overlap_addrs), _iasf.GetForwarderSelector(), overlap_addrs, remote_id); lock (_sync) { if (!_id_to_tunnel.ContainsKey(te.LocalID)) { _id_to_tunnel[te.LocalID] = te; break; } } // Arriving here, implies another RelayEdge will be created and this // one needs to be closed te.Close(); } local_id = te.LocalID; te.CloseEvent += CloseHandler; SendEdgeEvent(te); } if (!_id_to_tunnel.TryGetValue(local_id, out te)) { // Maybe we closed this edge // throw new Exception("No such edge"); // Old behavior would ignore these packets... return; } else if (te.RemoteID == -1) { // We created this, but we haven't received a packet yet te.RemoteID = remote_id; } else if (te.RemoteID != remote_id) { // Either we closed this edge and it was reallocated or something is up! // throw new Exception("Receiving imposter packet..."); // Old behavior would ignore these packets... return; } if (te.IsClosed) { throw new Exception("Edge is closed..."); } // Chop off the Ids data = data.Slice(8); te.ReceivedPacketEvent(data); }
/** * On every activation, the ChotaConnectionOverlord trims any connections * that are unused, and also creates any new connections of needed */ override public void Activate() { if (!_active) { return; } ConnectionList cons = _node.ConnectionTable.GetConnections(Connection.StringToMainType(struc_chota)); // Trim and add OUTSIDE of the lock! List <Edge> to_trim = new List <Edge>(); List <Address> to_add = new List <Address>(); lock (_sync) { _node_rank_list.Sort(_cmp); // Find the guys to trim.... for (int i = _node_rank_list.Count - 1; i >= MAX_CHOTA && i > 0; i--) { NodeRankInformation node_rank = (NodeRankInformation)_node_rank_list[i]; // Must remove from _dest_to_node_rank to prevent memory leak _dest_to_node_rank.Remove(node_rank.Addr); // Now check to see if ChotaCO owns this connections and add to_trim if it does int idx = cons.IndexOf(node_rank.Addr); if (idx >= 0 && cons[idx].ConType.Equals(struc_chota)) { to_trim.Add(cons[idx].Edge); } } // Don't keep around stale state if (_node_rank_list.Count > MAX_CHOTA) { _node_rank_list.RemoveRange(MAX_CHOTA, _node_rank_list.Count - MAX_CHOTA); } // Find guys to connect to! for (int i = 0; i < _node_rank_list.Count && i < MAX_CHOTA; i++) { //we are traversing the list in descending order of NodeRankInformation node_rank = (NodeRankInformation)_node_rank_list[i]; if (node_rank.Count < MIN_SCORE_THRESHOLD) { //too low score to create a connection continue; } else if (cons.IndexOf(node_rank.Addr) >= 0) { // already have a connection to that node! continue; } to_add.Add(node_rank.Addr); } } foreach (Edge e in to_trim) { _node.GracefullyClose(e, "From Chota, low score trim."); } foreach (Address addr in to_add) { ConnectTo(addr, struc_chota); } }
public override Pair <Connection, bool> NextConnection(Edge from, AHHeader head) { Address dest = head.Destination; int d_idx = _structs.IndexOf(dest); if (d_idx >= 0) { //We have a direct connection: Connection next = _structs[d_idx]; if (next != _local_con) { return(new Pair <Connection, bool>(next, false)); } else { return(new Pair <Connection, bool>(null, true)); } } else { var ah_dest = (AHAddress)dest; int left_idx = ~d_idx; Connection l_c = _structs[left_idx]; int right_idx = left_idx - 1; Connection r_c = _structs[right_idx]; Connection next_con; Connection other_con; if (ah_dest.IsCloserToFirst((AHAddress)l_c.Address, (AHAddress)r_c.Address)) { next_con = l_c; other_con = r_c; } else { next_con = r_c; other_con = l_c; } //See if we need to get it: /* everyone gets "path" packets, * if it's exact, only the destination gets it, handled above * otherwise, only the two nodes on either side of the destination get * it */ bool local = head.Opts == AHHeader.Options.Path || ((next_con == _local_con || other_con == _local_con) && head.Opts != AHHeader.Options.Exact); Connection to_send; //Check not to send it back the way it came: if (from == null) { /* * This packet is from us, so just send it to the closest * node, other than us. */ to_send = _local_con != next_con ? next_con : other_con; } else if (next_con.Edge == from) { //Don't send it back the way it came: to_send = other_con; } else { //Great, the closest has not yet been visited: to_send = next_con; } //Now, make sure not to send it to ourselves: to_send = to_send == _local_con ? null : to_send; return(new Pair <Connection, bool>(to_send, local)); } }