/** * Checks that everything matches up and the protocol * can continue, throws and exception if anything is * not okay */ protected void SetAndCheckLinkReply(LinkMessage lm) { /* Check that the everything matches up * Make sure the link message is Kosher. * This are critical errors. This Link fails if these occur */ if (lm.Local == null) { throw new LinkException("Bad response"); } if (_node.Address.Equals(lm.Local.Address)) { //Somehow, we got a response from someone claiming to be us. throw new LinkException("Got a LinkMessage response from our address"); } if (lm.ConTypeString != _contype) { throw new LinkException("Link type mismatch: " + _contype + " != " + lm.ConTypeString); } if (!lm.Realm.Equals(_node.Realm)) { throw new LinkException("Realm mismatch: " + _node.Realm + " != " + lm.Realm); } if (lm.Local.Address == null) { throw new LinkException("LinkMessage response has null Address"); } if ((_linker.Target != null) && (!lm.Local.Address.Equals(_linker.Target))) { /* * This is super goofy. Somehow we got a response from some node * we didn't mean to connect to. * This can happen in some cases with NATs since nodes behind NATs are * guessing which ports are correct, their guess may be incorrect, and * the NAT may send the packet to a different node. * In this case, we have a critical error, this TA is not correct, we * must move on to the next TA. */ throw new LinkException(String.Format("Target mismatch: {0} != {1}", _linker.Target, lm.Local.Address), true, null); } /* * Okay, this lm looks good, we'll accept it. This can only be done * once, and once it happens a future attempt will throw an exception */ _lm_reply.Value = lm; ConnectionTable tab = _node.ConnectionTable; /* * This throws an exception if: * 0) we can't get the lock. * 1) we already have set _target_lock to something else */ tab.Lock(lm.Local.Address, _contype, this); }
/** * Set the _target_lock member variable and check for sanity * We only set the target if we can get a lock on the address * We can call this method more than once as long as we always * call it with the same value for target * If target is null we just return * * @throws LinkException if the target is already * set to a different address * @throws System.InvalidOperationException if we cannot get the lock */ protected void SetTarget() { if (_target == null) { return; } if (_target.Equals(LocalNode.Address)) { throw new LinkException("cannot connect to self"); } ConnectionTable tab = LocalNode.ConnectionTable; /* * This throws an exception if: * 0) we can't get the lock. * 1) we already have set _target_lock to something else */ tab.Lock(_target, _contype, this); }
/** * When we get a new link message from an edge, we must * check several conditions to see if we can proceed with * the Link protocol. * This function checks those conditions and returns true * if we can proceed. * If we cannot proceed, it gives an ErrorMessage to send * back to the other side. * @param cph The CphState * @param err ErrorMessage to return. Is null if there is no error * @return true if we can connect, if false, err != null */ protected bool CanConnect(CphState cph, out ErrorMessage err) { ConnectionTable tab = _node.ConnectionTable; Address local_add = _node.Address; LinkMessage lm = cph.LM; err = null; /* We lock the connection table so it doesn't change between * the call to Contains and the call to Lock */ if (lm.Attributes["realm"] != _node.Realm) { err = new ErrorMessage(ErrorMessage.ErrorCode.RealmMismatch, "We are not in the same realm"); } else if ((lm.Remote.Address != null) && !local_add.Equals(lm.Remote.Address)) { /* * They are trying to reach a specific node, but it's not * us */ err = new ErrorMessage(ErrorMessage.ErrorCode.TargetMismatch, String.Format("target is {0}, but reached {1}", lm.Remote.Address, local_add)); } else if (lm.Local.Address.Equals(local_add)) { //You are me!!! err = new ErrorMessage(ErrorMessage.ErrorCode.ConnectToSelf, "You are me: "); } else if (1 == _disconnecting) { err = new ErrorMessage(ErrorMessage.ErrorCode.Disconnecting, String.Format("I am disconnecting. local: {0}", local_add)); } else { /* * Now we go to the ConnectionTable and try to * get a lock on the address so we can go forward * with the linking */ try { if (ProtocolLog.LinkDebug.Enabled) { ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format( "ConnectionPacketHandler - Trying to lock connection table: {0},{1}", lm.Local.Address, lm.ConTypeString)); } tab.Lock(lm.Local.Address, lm.ConTypeString, cph); if (ProtocolLog.LinkDebug.Enabled) { ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format( "ConnectionPacketHandler - Successfully locked connection table: {0},{1}", lm.Local.Address, lm.ConTypeString)); } } catch (ConnectionExistsException) { //We already have a connection of this type to this address err = new ErrorMessage(ErrorMessage.ErrorCode.AlreadyConnected, String.Format("We are already connected: {0}", local_add)); } catch (CTLockException) { if (ProtocolLog.LinkDebug.Enabled) { ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format( "ConnectionPacketHandler - Cannot lock connection table: {0},{1}", lm.Local.Address, lm.ConTypeString)); } //Lock can throw this type of exception err = new ErrorMessage(ErrorMessage.ErrorCode.InProgress, "Address: " + lm.Local.Address.ToString() + " is locked"); } } return(err == null); }