示例#1
0
 public ConnectionState(Edge e, StatusMessage sm, LinkMessage lm, bool discon)
 {
     Edge            = e;
     PeerLinkMessage = lm;
     StatusMessage   = sm;
     Disconnected    = discon;
 }
示例#2
0
        /**
         * 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)
        {
            Address     local_add = _node.Address;
            LinkMessage lm        = cph.LM;

            err = null;
            if (lm.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));
            }
            return(err == null);
        }
示例#3
0
        /**
         * @return true if olm is equivalent to this
         */
        public override bool Equals(object olm)
        {
            LinkMessage lm = olm as LinkMessage;

            if (lm != null)
            {
                bool same = true;
                same &= (lm.Attributes.Count == Attributes.Count);
                same &= lm.ConTypeString == ConTypeString;
                same &= lm.Token.Equals(Token);
                if (same)
                {
                    //Make sure all the attributes match:
                    foreach (string key in lm.Attributes.Keys)
                    {
                        same &= lm.Attributes[key] == Attributes[key];
                    }
                }
                same &= lm.Local.Equals(_local_ni);
                same &= lm.Remote.Equals(_remote_ni);
                return(same);
            }
            else
            {
                return(false);
            }
        }
示例#4
0
        /**
         * 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);
        }
示例#5
0
    /**
     * Prefered constructor for a Connection
     */
    public Connection(Edge e, Address a,
		      string connectiontype,
		      StatusMessage sm, LinkMessage peerlm)
    {
      Address = a;
      ConType = String.Intern(connectiontype);
      CreationTime = DateTime.UtcNow;
      MainType = StringToMainType(ConType);
      //Mutable state:
      var cs = new ConnectionState(e, sm, peerlm, false);
      _state = new Mutable<ConnectionState>(cs);
    }
示例#6
0
        public void LMSerializationTest()
        {
            NodeInfo n1 = NodeInfo.CreateInstance(null, TransportAddressFactory.CreateInstance("brunet.tcp://127.0.0.1:45"));
            RandomNumberGenerator rng     = new RNGCryptoServiceProvider();
            AHAddress             tmp_add = new AHAddress(rng);
            LinkMessage           l1      = new LinkMessage(ConnectionType.Structured, n1,
                                                            NodeInfo.CreateInstance(new DirectionalAddress(DirectionalAddress.Direction.Left),
                                                                                    TransportAddressFactory.CreateInstance("brunet.tcp://127.0.0.1:837")), string.Empty,
                                                            tmp_add.ToString());

            RoundTripHT(l1);
        }
示例#7
0
 /**
  * Prefered constructor for a Connection
  */
 public Connection(Edge e, Address a,
                   string connectiontype,
                   StatusMessage sm, LinkMessage peerlm)
 {
     _e             = e;
     _a             = a;
     _ct            = String.Intern(connectiontype);
     _stat          = sm;
     _lm            = peerlm;
     _creation_time = DateTime.UtcNow;
     MainType       = StringToMainType(_ct);
     _as_dict       = new WriteOnce <ListDictionary>();
     _sub_type      = new WriteOnce <string>();
 }
示例#8
0
    /**
     * Prefered constructor for a Connection
     */
    public Connection(Edge e, Address a,
		      string connectiontype,
		      StatusMessage sm, LinkMessage peerlm)
    {
      _e = e;
      _a = a;
      _ct = String.Intern(connectiontype);
      _stat = sm;
      _lm = peerlm;
      _creation_time = DateTime.UtcNow;
      MainType = StringToMainType(_ct);
      _as_dict = new WriteOnce<ListDictionary>();
      _sub_type = new WriteOnce<string>();
    }
示例#9
0
        /**
         * @return true if olm is equivalent to this
         */
        public override bool Equals(object olm)
        {
            LinkMessage lm   = olm as LinkMessage;
            bool        same = false;

            if (lm != null)
            {
                same  = lm.ConTypeString.Equals(ConTypeString);
                same &= lm.Token.Equals(Token);
                same &= lm.Remote.Equals(Remote);
                same &= lm.Local.Equals(Local);
                same &= lm.Realm.Equals(Realm);
            }
            return(same);
        }
示例#10
0
        /**
         * Prefered constructor for a Connection
         */
        public Connection(Edge e, Address a,
                          string connectiontype,
                          StatusMessage sm, LinkMessage peerlm)
        {
            if (null == a)
            {
                throw new System.ArgumentNullException(
                          String.Format("Address cannot be null in Connection: Edge: {0} contype: {1}", e, connectiontype));
            }
            Address      = a;
            ConType      = String.Intern(connectiontype);
            CreationTime = DateTime.UtcNow;
            MainType     = StringToMainType(ConType);
            //Mutable state:
            var cs = new ConnectionState(e, sm, peerlm, false);

            _state = new Mutable <ConnectionState>(cs);
        }
示例#11
0
        public void LMSerializationTest()
        {
            NodeInfo n1 = NodeInfo.CreateInstance(null, TransportAddressFactory.CreateInstance("brunet.tcp://127.0.0.1:45"));
            RandomNumberGenerator rng     = new RNGCryptoServiceProvider();
            AHAddress             tmp_add = new AHAddress(rng);
            LinkMessage           l1      = new LinkMessage(ConnectionType.Structured, n1,
                                                            NodeInfo.CreateInstance(new DirectionalAddress(DirectionalAddress.Direction.Left),
                                                                                    TransportAddressFactory.CreateInstance("brunet.tcp://127.0.0.1:837")), tmp_add.ToString());

            RoundTripHT(l1);
            StringDictionary attrs = new StringDictionary();

            attrs["realm"] = "test_realm";
            attrs["type"]  = "structured.near";
            LinkMessage l3 = new LinkMessage(attrs, n1, n1, tmp_add.ToString());

            RoundTripHT(l3);
        }
示例#12
0
        /** return the old state, and new state
         */
        public Pair <ConnectionState, ConnectionState> SetEdge(Edge e, LinkMessage lm)
        {
            var res = _state.Update(delegate(ConnectionState old_state) {
                if (old_state.Disconnected)
                {
                    throw new Exception(String.Format("Connection: {0} is disconnected", this));
                }
                var new_state = new ConnectionState(e, old_state.StatusMessage, lm, false);
                return(new_state);
            });

            ProtocolLog.WriteIf(ProtocolLog.Connections, String.Format(
                                    "SetEdge called on {0}, old Edge: {1}", this, res.First.Edge));
            var ev = StateChangeEvent;

            if (null != ev)
            {
                ev(this, res);
            }
            return(res);
        }
示例#13
0
        /**
         * When we get a response to the sys:link method, this handled
         * is called
         */
        protected void LinkCloseHandler(object q, EventArgs args)
        {
            try {
                Channel resq = (Channel)q;
                //If the Channel is empty this will throw an exception:
                RpcResult res = (RpcResult)resq.Dequeue();
                /* Here's the LinkMessage response */
                LinkMessage lm = new LinkMessage((IDictionary)res.Result);

                /**
                 * This will set our LinkMessageReply variable.  It can
                 * only be set once, so all future sets will fail.  It
                 * will also make sure we have the lock on the target.
                 * If we don't, that will throw an exception
                 */
                SetAndCheckLinkReply(lm);
                //If we got here, we have our response and the Lock on _target_address
                StatusMessage sm = _node.GetStatus(_contype, lm.Local.Address);
                /* Make the call */
                Channel results = new Channel();
                results.CloseAfterEnqueue();
                results.CloseEvent += this.StatusCloseHandler;
                RpcManager rpc = _node.Rpc;
                if (ProtocolLog.LinkDebug.Enabled)
                {
                    ProtocolLog.Write(ProtocolLog.LinkDebug,
                                      String.Format(
                                          "LPS target: {0} Invoking GetStatus() over edge: {1}",
                                          _linker.Target, _e));
                }

                /*
                 * This could throw an exception if the Edge is closed
                 */
                rpc.Invoke(_e, results, "sys:link.GetStatus", sm.ToDictionary());
            }
            catch (AdrException x) {
                /*
                 * This happens when the RPC call has some kind of issue,
                 * first we check for common error conditions:
                 */
                _x.Value = x;
                Finish(GetResultForErrorCode(x.Code));
            }
            catch (ConnectionExistsException x) {
                /* We already have a connection */
                _x.Value = x;
                Finish(Result.ProtocolError);
            }
            catch (CTLockException x) {
                //This is thrown when ConnectionTable cannot lock.  Lets try again:
                _x.Value = x;
                Finish(Result.RetryThisTA);
            }
            catch (LinkException x) {
                _x.Value = x;
                if (x.IsCritical)
                {
                    Finish(Result.MoveToNextTA);
                }
                else
                {
                    Finish(Result.RetryThisTA);
                }
            }
            catch (InvalidOperationException) {
                //The queue never got anything
                Finish(Result.MoveToNextTA);
            }
            catch (EdgeException) {
                //The Edge is goofy, let's move on:
                Finish(Result.MoveToNextTA);
            }
            catch (Exception x) {
                //The protocol was not followed correctly by the other node, fail
                _x.Value = x;
                Finish(Result.RetryThisTA);
            }
        }
示例#14
0
    /**
     * Prefered constructor for a Connection
     */
    public Connection(Edge e, Address a,
		      string connectiontype,
		      StatusMessage sm, LinkMessage peerlm)
    {
      if( null == a ) {
        throw new System.ArgumentNullException(
                    String.Format("Address cannot be null in Connection: Edge: {0} contype: {1}", e, connectiontype));
      }
      Address = a;
      ConType = String.Intern(connectiontype);
      CreationTime = DateTime.UtcNow;
      MainType = StringToMainType(ConType);
      //Mutable state:
      var cs = new ConnectionState(e, sm, peerlm, false);
      _state = new Mutable<ConnectionState>(cs);
    }
示例#15
0
 public ConnectionState(Edge e, StatusMessage sm, LinkMessage lm, bool discon) {
   Edge = e;
   PeerLinkMessage = lm;
   StatusMessage = sm;
   Disconnected = discon;
 }
示例#16
0
 /** return the old state, and new state
  */
 public Pair<ConnectionState,ConnectionState> SetEdge(Edge e, LinkMessage lm) {
   var res = _state.Update(delegate(ConnectionState old_state) {
     if( old_state.Disconnected ) {
       throw new Exception(String.Format("Connection: {0} is disconnected",this));
     }
     var new_state = new ConnectionState(e, old_state.StatusMessage, lm, false);
     return new_state;
   });
   var ev = StateChangeEvent;
   if( null != ev ) {
     ev(this, res);
   }
   return res;
 }
示例#17
0
    /**
     * When we get a response to the sys:link method, this handled
     * is called
     */
    protected void LinkCloseHandler(object q, EventArgs args) {
      try {
        Channel resq = (Channel)q;
        //If the Channel is empty this will throw an exception:
        RpcResult res = (RpcResult)resq.Dequeue();
        /* Here's the LinkMessage response */
        LinkMessage lm = new LinkMessage( (IDictionary)res.Result );
        /**
         * This will set our LinkMessageReply variable.  It can
         * only be set once, so all future sets will fail.  It
         * will also make sure we have the lock on the target.
         * If we don't, that will throw an exception
         */
        SetAndCheckLinkReply(lm);
        //If we got here, we have our response and the Lock on _target_address
        StatusMessage sm = _node.GetStatus(_contype, lm.Local.Address);
        /* Make the call */
        Channel results = new Channel();
        results.CloseAfterEnqueue();
        results.CloseEvent += this.StatusCloseHandler;
        RpcManager rpc = _node.Rpc;
	if (ProtocolLog.LinkDebug.Enabled) {
	      ProtocolLog.Write(ProtocolLog.LinkDebug, 
                String.Format(
                  "LPS target: {0} Invoking GetStatus() over edge: {1}",
                  _linker.Target, _e));
	}
        /*
         * This could throw an exception if the Edge is closed
         */
        rpc.Invoke(_e, results, "sys:link.GetStatus", sm.ToDictionary() );
      }
      catch(AdrException x) {
        /*
         * This happens when the RPC call has some kind of issue,
         * first we check for common error conditions:
         */
        _x.Value = x;
        Finish( GetResultForErrorCode(x.Code) );
      }
      catch(ConnectionExistsException x) {
        /* We already have a connection */
        _x.Value = x;
        Finish( Result.ProtocolError );
      }
      catch(CTLockException x) {
        //This is thrown when ConnectionTable cannot lock.  Lets try again:
        _x.Value = x;
        Finish( Result.RetryThisTA );
      }
      catch(LinkException x) {
        _x.Value = x;
        if( x.IsCritical ) { Finish( Result.MoveToNextTA ); }
        else { Finish( Result.RetryThisTA ); }
      }
      catch(InvalidOperationException) {
        //The queue never got anything
        Finish(Result.MoveToNextTA);
      }
      catch(EdgeException) {
        //The Edge is goofy, let's move on:
        Finish(Result.MoveToNextTA);
      }
      catch(Exception x) {
        //The protocol was not followed correctly by the other node, fail
        _x.Value = x;
        Finish( Result.RetryThisTA );
      } 
    }
示例#18
0
        /**
         * This starts a linking operation on the given edge
         */
        public IDictionary Start(IDictionary link_message, ISender edge)
        {
            if (ProtocolLog.LinkDebug.Enabled)
            {
                ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format(
                                      "{0} -start- sys:link.Start", _node.Address));
            }

            Edge        from = GetEdge(edge);
            LinkMessage lm   = new LinkMessage(link_message);

            if (ProtocolLog.LinkDebug.Enabled)
            {
                ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format(
                                      "{0} -args- sys:link.Start({1},{2})", _node.Address, lm, from));
            }

            CphState cph = new CphState(from, lm);

            lock ( _sync ) {
                if (!_edge_to_cphstate.ContainsKey(from))
                {
                    _edge_to_cphstate[from] = cph;
                }
                else
                {
                    throw new AdrException((int)ErrorMessage.ErrorCode.InProgress,
                                           "Already have a link in progress on this edge");
                }
            }
            ErrorMessage err = null;

            if (CanConnect(cph, out err))
            {
                try {
                    //If the CloseEvent was already called, this throws an exception
                    from.CloseEvent += this.CloseHandler;
                }
                catch {
                    CloseHandler(from, null);
                    throw new AdrException((int)ErrorMessage.ErrorCode.EdgeClosed,
                                           "Edge Closed after receiving message");
                }
            }
            else
            {
                lock ( _sync ) {
                    _edge_to_cphstate.Remove(from);
                }
            }
            //Now we prepare our response
            LinkMessage lm_resp = null;

            if (err == null)
            {
                //We send a response:
                NodeInfo n_info      = NodeInfo.CreateInstance(_node.Address, from.LocalTA);
                NodeInfo remote_info = NodeInfo.CreateInstance(null, from.RemoteTA);
                lm_resp = new LinkMessage(lm.ConTypeString, n_info, remote_info, _node.Realm, lm.Token);
            }
            else
            {
                throw new AdrException((int)err.Ec, err.Message);
            }
            if (ProtocolLog.LinkDebug.Enabled)
            {
                ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format(
                                      "{0} -end- sys:link.Start()->{1}", _node.Address, lm_resp));
            }
            return(lm_resp.ToDictionary());
        }
示例#19
0
        /**
         * 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);
        }
示例#20
0
        /**
         * This starts a linking operation on the given edge
         */
        public IDictionary Start(IDictionary link_message, ISender edge)
        {
            if (ProtocolLog.LinkDebug.Enabled)
            {
                ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format(
                                      "{0} -start- sys:link.Start", _node.Address));
            }

            Edge        from = GetEdge(edge);
            LinkMessage lm   = new LinkMessage(link_message);

            if (ProtocolLog.LinkDebug.Enabled)
            {
                ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format(
                                      "{0} -args- sys:link.Start({1},{2})", _node.Address, lm, from));
            }

            CphState cph = new CphState(from, lm);

            lock ( _sync ) {
                if (!_edge_to_cphstate.ContainsKey(from))
                {
                    _edge_to_cphstate[from] = cph;
                }
                else
                {
                    throw new AdrException((int)ErrorMessage.ErrorCode.InProgress,
                                           "Already have a link in progress on this edge");
                }
            }
            ErrorMessage err = null;

            if (CanConnect(cph, out err))
            {
                try {
                    //If the CloseEvent was already called, this throws an exception
                    from.CloseEvent += this.CloseHandler;
                }
                catch {
                    CloseHandler(from, null);
                    throw new AdrException((int)ErrorMessage.ErrorCode.EdgeClosed,
                                           "Edge Closed after receiving message");
                }
            }
            else
            {
                lock ( _sync ) {
                    _edge_to_cphstate.Remove(from);
                }
            }
            //Now we prepare our response
            LinkMessage lm_resp = null;

            if (err == null)
            {
                //We send a response:
                NodeInfo n_info      = NodeInfo.CreateInstance(_node.Address, from.LocalTA);
                NodeInfo remote_info = NodeInfo.CreateInstance(null, from.RemoteTA);
                System.Collections.Specialized.StringDictionary attrs =
                    new System.Collections.Specialized.StringDictionary();
                attrs["type"]  = String.Intern(lm.ConTypeString);
                attrs["realm"] = String.Intern(_node.Realm);
                lm_resp        = new LinkMessage(attrs, n_info, remote_info, lm.Token);
            }
            else
            {
                if (err.Ec == ErrorMessage.ErrorCode.AlreadyConnected)
                {
                    /**
                     * When we send the ErrorCode.AlreadyConnected,
                     * we could have a stale connection, lets try pinging
                     * the other node, if they are there, but have lost
                     * the Edge, this may trigger the edge to close, causing
                     * us to remove the Connection.
                     * @todo consider putting this address on a "fast track"
                     * to removal if we don't hear from it soon
                     */
                    ConnectionTable tab = _node.ConnectionTable;
                    Connection      c   = tab.GetConnection(lm.ConnectionType,
                                                            lm.Local.Address);
                    if (c != null)
                    {
                        RpcManager rpc = _node.Rpc;
                        rpc.Invoke(c.Edge, null, "sys:link.Ping", String.Empty);
                    }
                }
            }
            if (err != null)
            {
                throw new AdrException((int)err.Ec, err.Message);
            }
            if (ProtocolLog.LinkDebug.Enabled)
            {
                ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format(
                                      "{0} -end- sys:link.Start()->{1}", _node.Address, lm_resp));
            }
            return(lm_resp.ToDictionary());
        }
示例#21
0
    /**
     * This starts a linking operation on the given edge
     */
    public IDictionary Start(IDictionary link_message, ISender edge) {
      if(ProtocolLog.LinkDebug.Enabled)
        ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format(
          "{0} -start- sys:link.Start", _node.Address));

      Edge from = GetEdge(edge);
      LinkMessage lm = new LinkMessage(link_message);
      if(ProtocolLog.LinkDebug.Enabled)
        ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format(
          "{0} -args- sys:link.Start({1},{2})", _node.Address,lm,from));

      CphState cph = new CphState(from,lm);
      lock( _sync ) {
        if( !_edge_to_cphstate.ContainsKey( from ) ) {
          _edge_to_cphstate[from] = cph;
        }
        else {
          throw new AdrException((int)ErrorMessage.ErrorCode.InProgress,
                                 "Already have a link in progress on this edge");
        }
      }
      ErrorMessage err = null;
      if( CanConnect(cph, out err) ) {
        try {
          //If the CloseEvent was already called, this throws an exception
          from.CloseEvent += this.CloseHandler;
        }
        catch {
          CloseHandler(from, null);
          throw new AdrException((int)ErrorMessage.ErrorCode.EdgeClosed,
                                      "Edge Closed after receiving message");
        }
      }
      else {
        lock( _sync ) {
          _edge_to_cphstate.Remove(from);
        }
      }
      //Now we prepare our response
      LinkMessage lm_resp = null;
      if( err == null ) {
        //We send a response:
        NodeInfo n_info = NodeInfo.CreateInstance( _node.Address, from.LocalTA );
        NodeInfo remote_info = NodeInfo.CreateInstance( null, from.RemoteTA );
        System.Collections.Specialized.StringDictionary attrs =
                new System.Collections.Specialized.StringDictionary();
        attrs["type"] = String.Intern( lm.ConTypeString );
        attrs["realm"] = String.Intern( _node.Realm );
        lm_resp = new LinkMessage( attrs, n_info, remote_info , lm.Token);
      }
      else {
        if( err.Ec == ErrorMessage.ErrorCode.AlreadyConnected ) {
          /**
           * When we send the ErrorCode.AlreadyConnected,
           * we could have a stale connection, lets try pinging
           * the other node, if they are there, but have lost
           * the Edge, this may trigger the edge to close, causing
           * us to remove the Connection.
           * @todo consider putting this address on a "fast track"
           * to removal if we don't hear from it soon
           */
          ConnectionTable tab = _node.ConnectionTable;
          Connection c = tab.GetConnection( lm.ConnectionType,
                                             lm.Local.Address );
          if( c != null ) {
            RpcManager rpc = _node.Rpc;
            rpc.Invoke(c.Edge, null, "sys:link.Ping", String.Empty);
          }
        }
      }
      if( err != null ) {
        throw new AdrException((int)err.Ec, err.Message);
      }
      if(ProtocolLog.LinkDebug.Enabled)
        ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format(
          "{0} -end- sys:link.Start()->{1}", _node.Address,lm_resp));
      return lm_resp.ToDictionary();
    }
示例#22
0
        public void RoundTripHT(LinkMessage lm)
        {
            LinkMessage lm2 = new LinkMessage(lm.ToDictionary());

            Assert.AreEqual(lm, lm2, "LinkMessage HT Roundtrip");
        }
示例#23
0
 public CphState(Edge e, LinkMessage lm) {
   Edge = e;
   LM = lm;
 }
示例#24
0
 public void RoundTripHT(LinkMessage lm) {
   LinkMessage lm2 = new LinkMessage( lm.ToDictionary() );
   Assert.AreEqual( lm, lm2, "LinkMessage HT Roundtrip" );
 }
示例#25
0
        /**
         * Get a StatusMessage for this node
         */
        public IDictionary GetStatus(IDictionary status_message, ISender edge)
        {
            //we just got s status request
            if (1 == _disconnecting)
            {
                throw new AdrException((int)ErrorMessage.ErrorCode.Disconnecting, "disconnecting");
            }

            StatusMessage sm   = new StatusMessage(status_message);
            Edge          from = GetEdge(edge);

            if (ProtocolLog.LinkDebug.Enabled)
            {
                ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format(
                                      "{0} -start- sys:link.GetStatus({1},{2})", _node.Address, sm, edge));
            }

            CphState cphstate = null;

            if (from != null)
            {
                cphstate = _edge_to_cphstate[from] as CphState;
            }

            /**
             * StatusMessage objects are used to verify the completion
             * of the Link protocol.  If we receive a StatusMessage request
             * after we send a LinkMessage response, we know the other
             * Node got our LinkMessage response, and the connection
             * is active
             */
            StatusMessage   response = null;
            ConnectionTable tab      = _node.ConnectionTable;

            if (cphstate != null)
            {
                try {
                    LinkMessage lm_to_add = cphstate.LM;
                    //This is part of connection process:
                    response = _node.GetStatus(sm.NeighborType, lm_to_add.Local.Address);
                    Connection con = new Connection(from,
                                                    lm_to_add.Local.Address,
                                                    lm_to_add.ConTypeString,
                                                    sm,
                                                    lm_to_add);
                    tab.Add(con);
                }
                finally {
                    from.CloseEvent -= this.CloseHandler;
                    CloseHandler(from, null);
                }
            }
            else
            {
                //This is just a "regular" status request
                //update our table:
                Address    fadd = null;
                Connection c    = tab.GetConnection(from);
                if (c != null)
                {
                    fadd = c.Address;
                    tab.UpdateStatus(c, sm);
                }
                response = _node.GetStatus(sm.NeighborType, fadd);
            }

            if (ProtocolLog.LinkDebug.Enabled)
            {
                ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format(
                                      "{0} -end- sys:link.GetStatus()->{1}", _node.Address, response));
            }

            return(response.ToDictionary());
        }
示例#26
0
    public void LMSerializationTest()
    {
      NodeInfo n1 = NodeInfo.CreateInstance(null, TransportAddressFactory.CreateInstance("brunet.tcp://127.0.0.1:45"));
      RandomNumberGenerator rng = new RNGCryptoServiceProvider();      
      AHAddress tmp_add = new AHAddress(rng);
      LinkMessage l1 = new LinkMessage(ConnectionType.Structured, n1,
				       NodeInfo.CreateInstance(new DirectionalAddress(DirectionalAddress.Direction.Left),
				       TransportAddressFactory.CreateInstance("brunet.tcp://127.0.0.1:837")), tmp_add.ToString() );
      RoundTripHT(l1);
      StringDictionary attrs = new StringDictionary();
      attrs["realm"] = "test_realm";
      attrs["type"] = "structured.near";
      LinkMessage l3 = new LinkMessage(attrs, n1, n1, tmp_add.ToString());
      RoundTripHT(l3);
    }
示例#27
0
 public CphState(Edge e, LinkMessage lm)
 {
     Edge = e;
     LM   = lm;
 }
示例#28
0
 /**
  * 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.Attributes["realm"].Equals( _node.Realm ) ) {
     throw new LinkException("Realm mismatch: " +
                             _node.Realm + " != " + lm.Attributes["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 );
 }