Example #1
0
 public void Call(DiscoNode node)
 {
     if (callback != null)
     {
         callback(manager, node, state);
     }
 }
Example #2
0
        private void GotItems(object sender, IQ iq, object onode)
        {
            DiscoNode dn = onode as DiscoNode;

            Debug.Assert(dn != null);

            if (iq.Type != IQType.result)
            {
                // protocol error
                dn.AddItems(this, null);
                return;
            }

            DiscoItems items = iq.Query as DiscoItems;

            if (items == null)
            {
                // protocol error
                dn.AddItems(this, null);
                return;
            }

            dn.AddItems(this, items.GetItems());

            // automatically info everything we get an item for.
            foreach (DiscoNode n in dn.Children)
            {
                if (n.Features == null)
                {
                    RequestInfo(n);
                }
            }
        }
Example #3
0
 /// <summary>
 /// Deletes the cache.
 /// </summary>
 public void Clear()
 {
     lock (m_items)
     {
         m_root = null;
         m_items.Clear();
     }
 }
Example #4
0
 public void GotRootItems(DiscoManager manager, DiscoNode node, object state)
 {
     m_outstanding = node.Children.Count;
     foreach (DiscoNode n in node.Children)
     {
         manager.BeginGetFeatures(n, new DiscoNodeHandler(GotFeatures), state);
     }
 }
Example #5
0
        internal DiscoNode AddItem(DiscoManager manager, DiscoItem di)
        {
            DiscoNode dn = manager.GetNode(di.Jid, di.Node);

            if ((di.Named != null) && (di.Named != ""))
            {
                dn.Name = di.Named;
            }
            Children.Add(dn);
            return(dn);
        }
Example #6
0
        /// <summary>
        /// Retrieves the child items associated with this node,
        /// and then calls back on the handler.
        /// If the information is in the cache, handler gets
        /// called right now.
        /// </summary>
        /// <param name="node">Disco node to search.</param>
        /// <param name="handler">Callback that gets called with the items.</param>
        /// <param name="state">Context to pass back to caller when complete</param>
        public void BeginGetItems(DiscoNode node, DiscoNodeHandler handler, object state)
        {
            if (node == null)
            {
                node = Root;
            }

            if (node.AddItemsCallback(this, handler, state))
            {
                RequestItems(node);
            }
        }
Example #7
0
        /// <summary>
        /// Retrieves the features associated with this node and
        /// then calls back on the handler.
        /// If the information is in the cache, handler gets called right now.
        /// </summary>
        /// <param name="node">Node to look for.</param>
        /// <param name="handler">Callback to use afterwards.</param>
        /// <param name="state">Context to pass back to caller when complete</param>
        public void BeginGetFeatures(DiscoNode node, DiscoNodeHandler handler, object state)
        {
            if (node == null)
            {
                node = Root;
            }

            if (node.AddFeatureCallback(this, handler, state))
            {
                RequestInfo(node);
            }
        }
Example #8
0
        /// <summary>
        /// Create a CapsManager from an existing Disco Node.  Pass in null
        /// to use a placeholder.
        /// </summary>
        /// <param name="node"></param>
        public CapsManager(DiscoNode node)
        {
            this.OnStreamChanged += new bedrock.ObjectHandler(CapsManager_OnStreamChanged);

            if (node == null)
            {
                m_disco = new DiscoNode(new JID(null, "placeholder", null), null);
            }
            else
            {
                m_disco = node;
            }
        }
Example #9
0
 /// <summary>
 /// Creates nodes and ensure that they are cached.
 /// </summary>
 /// <param name="jid">JID associated with DiscoNode.</param>
 /// <param name="node">Node associated with DiscoNode.</param>
 /// <returns>
 /// If DiscoNode exists, returns the found node.
 /// Otherwise it creates the node and return it.
 /// </returns>
 public DiscoNode GetNode(JID jid, string node)
 {
     lock (m_items)
     {
         string    key = DiscoNode.GetKey(jid, node);
         DiscoNode n   = (DiscoNode)m_items[key];
         if (n == null)
         {
             n = new DiscoNode(jid, node);
             m_items.Add(key, n);
         }
         return(n);
     }
 }
Example #10
0
 private void RequestItems(DiscoNode node)
 {
     lock (node)
     {
         if (!node.PendingItems)
         {
             IQ iq = node.ItemsIQ(m_stream.Document);
             jabber.server.JabberService js = m_stream as jabber.server.JabberService;
             if (js != null)
             {
                 iq.From = js.ComponentID;
             }
             BeginIQ(iq, new jabber.connection.IqCB(GotItems), node);
         }
     }
 }
Example #11
0
            public void GotFeatures(DiscoManager manager, DiscoNode node, object state)
            {
                // yes, yes, this may call the handler more than once in multi-threaded world.  Punt for now.
                if (m_handler != null)
                {
                    if (node.HasFeature(m_URI))
                    {
                        m_handler(manager, node, state);
                        m_handler = null;
                    }
                }

                if (Interlocked.Decrement(ref m_outstanding) == 0)
                {
                    if (m_handler != null)
                    {
                        m_handler(manager, null, state);
                    }
                }
            }
Example #12
0
        private void GotInfo(object sender, IQ iq, object onode)
        {
            DiscoNode dn = onode as DiscoNode;

            Debug.Assert(dn != null);

            if (iq.Type == IQType.error)
            {
                if (dn == m_root)
                {
                    // root node.
                    // Try agents.
                    Error err = iq.Error;
                    if (err != null)
                    {
                        string cond = err.Condition;
                        if ((cond == Error.FEATURE_NOT_IMPLEMENTED) ||
                            (cond == Error.SERVICE_UNAVAILABLE))
                        {
                            IQ aiq = new AgentsIQ(m_stream.Document);
                            BeginIQ(aiq, new jabber.connection.IqCB(GotAgents), m_root);
                            return;
                        }
                    }
                }
            }
            if (iq.Type != IQType.result)
            {
                // protocol error
                dn.AddInfo(null);
                return;
            }

            dn.AddInfo(iq.Query as DiscoInfo);

            if (dn == m_root)
            {
                RequestItems(m_root);
            }
        }
Example #13
0
        private void GotCaps(DiscoManager m, DiscoNode node, object state)
        {
            // timeout
            if (node == null)
            {
                return;
            }

            string ver  = (string)state;
            string calc = CalculateVer(node);

            if (ver != calc)
            {
                Debug.WriteLine("WARNING: invalid caps ver hash: '" + ver + "' != '" + calc + "'");
                if (node.Info != null)
                {
                    Debug.WriteLine(node.Info.OuterXml);
                }
                return;
            }
            m_cache[ver] = node.Info;
        }
Example #14
0
        private string CalculateVer(DiscoNode n)
        {
            if (m_hash == null)
            {
                return(null);
            }

            // 1. Initialize an empty string S.
            StringBuilder S = new StringBuilder();

            // 2. Sort the service discovery identities [16] by category and then by type
            // (if it exists) and then by xml:lang (if it exists), formatted as
            // CATEGORY '/' [TYPE] '/' [LANG] '/' [NAME]. Note that each slash is
            // included even if the TYPE, LANG, or NAME is not included.
            Ident[] ids = n.GetIdentities();
            Array.Sort(ids);

            // 3. For each identity, append the 'category/type/lang/name' to S, followed by
            // the '<' character.
            foreach (Ident id in ids)
            {
                S.Append(id.Key);
                S.Append(SEP);
            }

            // 4. Sort the supported service discovery features.
            string[] features = n.FeatureNames;
            Array.Sort(features);

            // 5. For each feature, append the feature to S, followed by the '<' character.
            foreach (string feature in features)
            {
                S.Append(feature);
                S.Append(SEP);
            }

            // 6. If the service discovery information response includes XEP-0128 data forms,
            // sort the forms by the FORM_TYPE (i.e., by the XML character
            // data of the <value/> element).
            Data[] ext = n.Extensions;
            if (ext != null)
            {
                Array.Sort(ext, new FormTypeComparer());
                foreach (Data x in ext)
                {
                    // For each extended service discovery information form:

                    // 1. Append the XML character data of the FORM_TYPE field's <value/>
                    // element, followed by the '<' character.
                    S.Append(x.FormType);
                    S.Append(SEP);

                    // 2. Sort the fields by the value of the "var" attribute.
                    bedrock.collections.Tree fields = new bedrock.collections.Tree();
                    foreach (Field f in x.GetFields())
                    {
                        fields[f.Var] = f;
                    }

                    // 3. For each field:
                    foreach (System.Collections.DictionaryEntry entry in fields)
                    {
                        Field f = (Field)entry.Value;
                        if (f.Var == "FORM_TYPE")
                        {
                            continue;
                        }

                        // 1. Append the value of the "var" attribute, followed by the '<' character.
                        S.Append(f.Var);
                        S.Append(SEP);

                        // 2. Sort values by the XML character data of the <value/> element.
                        string[] values = f.Vals;
                        Array.Sort(values);
                        foreach (string v in values)
                        {
                            // 3. For each <value/> element, append the XML character data, followed by the '<' character.
                            S.Append(v);
                            S.Append(SEP);
                        }
                    }
                }
            }

            // Ensure that S is encoded according to the UTF-8 encoding (RFC 3269 [16]).
            byte[] input = Encoding.UTF8.GetBytes(S.ToString());

            // Compute the verification string by hashing S using the algorithm specified
            // in the 'hash' attribute (e.g., SHA-1 as defined in RFC 3174 [17]). The hashed
            // data MUST be generated with binary output and encoded using Base64 as specified
            // in Section 4 of RFC 4648 [18] (note: the Base64 output MUST NOT include
            // whitespace and MUST set padding bits to zero). [19]
            HashAlgorithm hasher = GetHasher(m_hash);

            byte[] hash = hasher.ComputeHash(input, 0, input.Length);
            return(Convert.ToBase64String(hash));
        }
Example #15
0
        /// <summary>
        /// Retrieves the child items associated with this node,
        /// and then calls back on the handler.
        ///
        /// If caching is specified, items already in the cache call the handler
        /// immediately.
        /// </summary>
        /// <param name="jid">JID of Service to query.</param>
        /// <param name="node">Node on the service to interact with.</param>
        /// <param name="handler">Callback that gets called with the items.</param>
        /// <param name="state">Context to pass back to caller when complete</param>
        /// <param name="cache">Should caching be performed on this request?</param>
        public void BeginGetItems(JID jid, string node, DiscoNodeHandler handler, object state, bool cache)
        {
            DiscoNode dn = cache ? GetNode(jid, node) : new DiscoNode(jid, node);

            BeginGetItems(dn, handler, state);
        }
Example #16
0
        private void GotAgents(object sender, IQ iq, object onode)
        {
            DiscoNode dn = onode as DiscoNode;

            Debug.Assert(dn != null);

            if (iq.Type != IQType.result)
            {
                dn.AddItems(this, null);
                return;
            }

            AgentsQuery aq = iq.Query as AgentsQuery;

            if (aq == null)
            {
                dn.AddItems(this, null);
                return;
            }

            if (dn.Children == null)
            {
                dn.Children = new Set();
            }

            foreach (Agent agent in aq.GetAgents())
            {
                DiscoItem di = new DiscoItem(m_stream.Document);
                di.Jid   = agent.JID;
                di.Named = agent.AgentName;

                DiscoNode child = dn.AddItem(this, di);
                if (child.Features == null)
                {
                    child.Features = new StringSet();
                }
                if (child.Identity == null)
                {
                    child.Identity = new Set();
                }

                Ident id = new Ident();
                id.Name = agent.Description;
                switch (agent.Service)
                {
                case "groupchat":
                    id.Category = "conference";
                    id.Type     = "text";
                    child.Identity.Add(id);
                    break;

                case "jud":
                    id.Category = "directory";
                    id.Type     = "user";
                    child.Identity.Add(id);
                    break;

                case null:
                case "":
                    break;

                default:
                    // guess this is a transport
                    id.Category = "gateway";
                    id.Type     = agent.Service;
                    child.Identity.Add(id);
                    break;
                }

                if (agent.Register)
                {
                    child.Features.Add(URI.REGISTER);
                }
                if (agent.Search)
                {
                    child.Features.Add(URI.SEARCH);
                }
                if (agent.Groupchat)
                {
                    child.Features.Add(URI.MUC);
                }
                if (agent.Transport)
                {
                    if (id.Category != "gateway")
                    {
                        Ident tid = new Ident();
                        tid.Name     = id.Name;
                        tid.Category = "gateway";
                        child.Identity.Add(tid);
                    }
                }

                foreach (XmlElement ns in agent.GetElementsByTagName("ns"))
                {
                    child.Features.Add(ns.InnerText);
                }
                child.AddItems(this, null);
                child.AddIdentities(null);
                child.AddFeatures((StringSet)null);
            }
            dn.AddItems(this, null);
            dn.AddIdentities(null);
            dn.AddFeatures((StringSet)null);
        }