public LinkerTask(Address local, Address target, string ct, string task_diff) { _local = local; _target = target; _ct = Connection.StringToMainType(ct); _task_diff = task_diff; }
/** * This method allows a user to add some state in the ConnectTo call (see SNCO). */ virtual protected Connector GetConnector(ISender sender, Address target, string ConnectionType, string token) { ConnectionType mt = Connection.StringToMainType(ConnectionType); /* * This is an anonymous delegate which is called before * the Connector starts. If it returns true, the Connector * will finish immediately without sending an ConnectToMessage */ Linker l = new Linker(_node, target, null, ConnectionType, _node.Address.ToString()); object link_task = l.Task; Connector.AbortCheck abort = delegate(Connector c) { bool stop = false; stop = _node.ConnectionTable.Contains(mt, target); if (!stop) { /* * Make a linker to get the task. We won't use * this linker. * No need in sending a ConnectToMessage if we * already have a linker going. */ stop = _node.TaskQueue.HasTask(link_task); } return(stop); }; ConnectToMessage ctm = GetConnectToMessage(ConnectionType, token); Connector con = new Connector(_node, sender, ctm, this, target); con.FinishEvent += ConnectorEndHandler; con.AbortIf = abort; return(con); }
/// <summary>Remove a specific address from being automatically connected /// to and close an existing managed connection if one exists.</summary> /// <param name="RemoteAddress">The address to get disconnected from and /// stop connecting to through the ManagedCO.</param> /// <returns>Should always be true, unless an unhandled exception /// occurs.</returns> public bool RemoveAddress(Address RemoteAddress) { lock (_sync) { if (!_connection_state.ContainsKey(RemoteAddress)) { return(true); } _connection_state.Remove(RemoteAddress); if (_connection_state.Count == 0) { Disable(); } } ConnectionType ct = Connection.StringToMainType(struc_managed); Connection c = _node.ConnectionTable.GetConnection(ct, RemoteAddress); if (c != null && c.ConType.Equals(struc_managed)) { _node.GracefullyClose(c.Edge, "RemoveAddress called from ManagedCO"); } return(true); }
/** * When the other node gives us an error code, this * method tells us what to do based on that. * We always finish, but our result is not * fixed */ protected Result GetResultForErrorCode(int c) { Result result = Result.ProtocolError; if (c == (int)ErrorMessage.ErrorCode.InProgress) { result = Result.RetryThisTA; } else if (c == (int)ErrorMessage.ErrorCode.AlreadyConnected) { /* * The other side thinks we are already connected. This is * odd, let's see if we agree */ Address target = _linker.Target; ConnectionTable tab = _node.ConnectionTable; if (target == null) { //This can happen with leaf connections. In this case, we //should move on to another TA. result = Result.MoveToNextTA; } else if (tab.Contains(Connection.StringToMainType(_contype), target)) { //This shouldn't happen result = Result.ProtocolError; if (ProtocolLog.LinkDebug.Enabled) { ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format( "Already connected: {0}, {1}", _contype, _target_lock)); } } else { //The other guy thinks we are connected, but we disagree, //let's retry. This can happen if we get disconnected //and reconnect, but the other node hasn't realized we //are disconnected. result = Result.RetryThisTA; } } else if (c == (int)ErrorMessage.ErrorCode.TargetMismatch) { /* * This could happen in some NAT cases, or perhaps due to * some other as of yet undiagnosed bug. * * Move to the next TA since this TA definitely connects to * the wrong guy. */ if (ProtocolLog.LinkDebug.Enabled) { ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format( "LPS: from {0} target mismatch: {1}", _e, _target_lock)); } result = Result.MoveToNextTA; } else if (c == (int)ErrorMessage.ErrorCode.ConnectToSelf) { /* * Somehow we connected to ourself, this TA is no good. */ result = Result.MoveToNextTA; } else if (c == (int)ErrorMessage.ErrorCode.Disconnecting) { /* The other node is going offline */ if (_linker.Target == null) { result = Result.MoveToNextTA; } else { result = Result.ProtocolError; //Give up now } } else { if (ProtocolLog.LinkDebug.Enabled) { ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format( "Unrecognized error code: {0}", c)); } } return(result); }
/////////////// /// /// Here is the constructor /// //////////////// /** * @param local the local Node to connect to the remote node * @param target the address of the node you are trying to connect * to. Set to null if you don't know * @param target_list an enumerable list of TransportAddress of the * Host we want to connect to * @param t ConnectionType string of the new connection * @token unique token to associate the different connection setup messages */ public Linker(Node local, Address target, ICollection target_list, string ct, string token) { _task = new LinkerTask(local.Address, target, ct); _local_n = local; _active_lps_count = 0; //this TaskQueue starts new tasks in the announce thread of the node. _task_queue = new NodeTaskQueue(local); _task_queue.EmptyEvent += this.FinishCheckHandler; _ta_queue = new BC.LockFreeQueue <TransportAddress>(); if (target_list != null) { int count = 0; Hashtable tas_in_queue = new Hashtable(_MAX_REMOTETAS); foreach (TransportAddress ta in target_list) { if (tas_in_queue.ContainsKey(ta)) { // Console.Error.WriteLine("TA: {0} appeared in list twice", ta); } else { _ta_queue.Enqueue(ta); tas_in_queue[ta] = null; //Remember that we've seen this one if (target != null) { /* * Make sure we don't go insane with TAs * we know who we want to try to connect to, * if it doesn't work after some number of * attempts, give up. Don't go arbitrarily * long */ count++; if (count >= _MAX_REMOTETAS) { break; } } } } } _added_cons = 0; //We have not added a connection yet _contype = ct; _maintype = Connection.StringToMainType(_contype); _target = target; _token = token; _ta_to_restart_state = new Hashtable(_MAX_REMOTETAS); _started = 0; _hold_fire = 1; _cph_transfer_requests = 0; #if LINK_DEBUG _lid = Interlocked.Increment(ref _last_lid); if (BU.ProtocolLog.LinkDebug.Enabled) { BU.ProtocolLog.Write(BU.ProtocolLog.LinkDebug, String.Format("{0}: Making {1}", _local_n.Address, this)); if (target_list != null) { BU.ProtocolLog.Write(BU.ProtocolLog.LinkDebug, String.Format("TAs:")); foreach (TransportAddress ta in target_list) { BU.ProtocolLog.Write(BU.ProtocolLog.LinkDebug, String.Format("{0}", ta)); } } } #endif }