/// <summary>Where data packets prepended with a tunnel come. Here we /// receive data as well as create new TunnelEdges.</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); TunnelEdge te = null; // No locally assigned ID, so we'll create a new TunnelEdge 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 TunnelEdge(this, (TunnelTransportAddress) _local_tas[0], new TunnelTransportAddress(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 TunnelEdge 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); }
/// <summary>Common code to Create an outgoing edge.</summary> protected void CreateEdge(TunnelEdgeCallbackAction teca, List<Connection> overlap) { if(_connections.Contains(teca.TunnelTA.Target)) { FailedEdgeCreate(teca); return; } TunnelEdge te = null; while(true) { te = new TunnelEdge(this, (TunnelTransportAddress) _local_tas[0], teca.TunnelTA, _iasf.GetForwarderSelector(), overlap); lock(_sync) { if(!_id_to_tunnel.ContainsKey(te.LocalID)) { _id_to_tunnel[te.LocalID] = te; break; } } // Arriving here, implies another TunnelEdge will be created and this // one needs to be closed te.Close(); } te.CloseEvent += CloseHandler; teca.Success.Value = true; teca.Exception.Value = null; teca.Edge.Value = te; _node.EnqueueAction(teca); }