Exemplo n.º 1
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);
        }
Exemplo n.º 2
0
        /**
         * When an Edge closes, we must remove it from out
         * Hashtable.
         * @param edge the Edge that closed
         */
        public void CloseHandler(object edge, EventArgs args)
        {
            CphState cphstate = null;

            lock (_sync) {
                cphstate = (CphState)_edge_to_cphstate[edge];
                if (cphstate != null)
                {
                    _edge_to_cphstate.Remove(edge);
                }
            }
        }
Exemplo n.º 3
0
        /**
         * When an Edge closes, we must remove it from out
         * Hashtable.
         * @param edge the Edge that closed
         */
        public void CloseHandler(object edge, EventArgs args)
        {
            CphState cphstate = null;

            lock (_sync) {
                cphstate = (CphState)_edge_to_cphstate[edge];
                if (cphstate != null)
                {
                    _edge_to_cphstate.Remove(edge);
                }
            }
            if (cphstate != null)
            {
                ConnectionTable tab = _node.ConnectionTable;
                tab.Unlock(cphstate.LM.ConTypeString, cphstate);
            }
        }
    /**
     * 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 );
    }
    /**
     * 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 = RpcManager.GetInstance(_node);
            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();
    }
Exemplo n.º 6
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);
        }
Exemplo n.º 7
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());
        }
Exemplo n.º 8
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());
        }
Exemplo n.º 9
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());
        }