/** * return the list of TAs that should be tried */ override public IList TargetTAs(IEnumerable hist) { /* * The trick here is, for a cone nat, we should only report * the most recently used ip/port pair. * For safety, we return the most recent two */ ArrayList tas = new ArrayList(); foreach (NatDataPoint p in hist) { TransportAddress last_reported = p.PeerViewOfLocalTA; if (last_reported != null) { if (tas.Count == 0 || !last_reported.Equals(tas[0])) { tas.Add(last_reported); } if (tas.Count == 2) { return(tas); } } } return(tas); }
/** * We learn RemotaTAs in case we need to get connected again in the * future. These are TransportAddress objects that should be good * at some point in the future. * @param list the list of TransportAddress objects to update * @param e the new Edge * @param ta the TransportAddress the remote end of the * edge according to our peer */ public virtual void UpdateRemoteTAs(IList list, Edge e, TransportAddress ta) { if (e.TAType == this.TAType) { if (e.RemoteTANotEphemeral) { //There is some chance this will be good again in the future //But, we only keep non-natted TAs, since NAT mappings change //so frequently, a NATed TA will probably be bad in the future if (ta.Equals(e.RemoteTA)) { //This node is not behind a NAT. int idx = list.IndexOf(ta); if (idx >= 0) { list.Remove(ta); } //Now put the i list.Insert(0, ta); } } } }
protected static TransportAddress CacheInstance(TransportAddress ta) { var ta_cache = Interlocked.Exchange <WeakValueTable <string, TransportAddress> >(ref _ta_cache, null); if (ta_cache != null) { try { var ta2 = ta_cache.GetValue(ta.ToString()); if (ta.Equals(ta2)) { ta = ta2; } else { ta_cache.Replace(ta.ToString(), ta); } } finally { Interlocked.Exchange <WeakValueTable <string, TransportAddress> >(ref _ta_cache, ta_cache); } } return(ta); }
/** * This handles lightweight control messages that may be sent * by UDP */ protected void HandleControlPacket(int remoteid, int n_localid, MemBlock buffer, object state) { int local_id = ~n_localid; UdpEdge e = _id_ht[local_id] as UdpEdge; if (e == null) { return; } if (e.RemoteID == 0) { try { e.RemoteID = remoteid; } catch { return; } } if (e.RemoteID != remoteid) { return; } try { ControlCode code = (ControlCode)NumberSerializer.ReadInt(buffer, 0); if (ProtocolLog.UdpEdge.Enabled) { ProtocolLog.Write(ProtocolLog.UdpEdge, String.Format( "Got control {1} from: {0}", e, code)); } if (code == ControlCode.EdgeClosed) { //The edge has been closed on the other side RequestClose(e); CloseHandler(e, null); } else if (code == ControlCode.EdgeDataAnnounce) { //our NAT mapping may have changed: IDictionary info = (IDictionary)AdrConverter.Deserialize(buffer.Slice(4)); string our_local_ta = (string)info["RemoteTA"]; //his remote is our local if (our_local_ta != null) { //Update our list: TransportAddress new_ta = TransportAddressFactory.CreateInstance(our_local_ta); TransportAddress old_ta = e.PeerViewOfLocalTA; if (!new_ta.Equals(old_ta)) { if (ProtocolLog.UdpEdge.Enabled) { ProtocolLog.Write(ProtocolLog.UdpEdge, String.Format( "Local NAT Mapping changed on Edge: {0}\n{1} => {2}", e, old_ta, new_ta)); } //Looks like matters have changed: this.UpdateLocalTAs(e, new_ta); /** * @todo, maybe we should ping the other edges sharing this * EndPoint, but we need to be careful not to do some O(E^2) * operation, which could easily happen if each EdgeDataAnnounce * triggered E packets to be sent */ } } } else if (code == ControlCode.Null) { //Do nothing in this case } } catch (Exception x) { //This could happen if this is some control message we don't understand if (ProtocolLog.Exceptions.Enabled) { ProtocolLog.Write(ProtocolLog.Exceptions, x.ToString()); } } }
protected static TransportAddress CacheInstance(TransportAddress ta) { var ta_cache = Interlocked.Exchange<WeakValueTable<string, TransportAddress>>(ref _ta_cache, null); if( ta_cache != null ) { try { var ta2 = ta_cache.GetValue(ta.ToString()); if(ta.Equals(ta2)) { ta = ta2; } else { ta_cache.Replace(ta.ToString(), ta); } } finally { Interlocked.Exchange<WeakValueTable<string, TransportAddress>>(ref _ta_cache, ta_cache); } } return ta; }