private void SendOfflineMessages(XmppSession session)
        {
            if (!session.IsSignalRFake)
            {
                var domain = session.Stream.Domain;
                foreach (var m in offlineStore.GetOfflineMessages(session.Jid))
                {
                    var delay = new Element("delay");
                    delay.SetNamespace("urn:xmpp:delay");
                    delay.SetAttribute("From", domain);
                    delay.SetAttribute("stamp", Time.Date(m.XDelay.Stamp));
                    delay.Value = "Offline Storage";
                    m.AddChild(delay);

                    m.XDelay.From  = new Jid(domain);
                    m.XDelay.Value = "Offline Storage";

                    sender.SendTo(session, m);
                }
                if (session.Jid.Resource != "TMTalk")
                {
                    offlineStore.RemoveAllOfflineMessages(session.Jid);
                }
            }
        }
        private void IQLost(object sender, TimeoutEventArgs e)
        {
            var iq      = (IQ)e.Data;
            var session = sessionManager.GetSession(iq.From);

            if (session != null)
            {
                // iChat bug
                if (iq.Id == null || iq.Id.IndexOf("ichat", StringComparison.OrdinalIgnoreCase) < 0)
                {
                    xmppSender.SendTo(session, XmppStanzaError.ToServiceUnavailable(iq));
                }
                else
                {
                    xmppSender.SendTo(session, ToResult(iq));
                }
            }
        }
示例#3
0
        private void IQLost(object sender, TimeoutEventArgs e)
        {
            var iq      = (IQ)e.Data;
            var session = sessionManager.GetSession(iq.From);

            if (session != null)
            {
                xmppSender.SendTo(session, XmppStanzaError.ToServiceUnavailable(iq));
            }
        }
示例#4
0
        public void ProcessStreamElement(Node node, XmppStream stream)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }

            try
            {
                var address = new Jid(stream.Domain);

                foreach (var handler in HandlerStorage.GetStreamHandlers(address, node.GetType()))
                {
                    handler.ElementHandle(stream, (Element)node.Clone(), context);
                }

                if (node is Stanza)
                {
                    var stanza = (Stanza)node;

                    if (!validator.ValidateStanza(stanza, stream, context))
                    {
                        return;
                    }

                    if (stanza.HasTo)
                    {
                        address = stanza.To;
                    }

                    var handlres = HandlerStorage.GetStanzaHandlers(address, GetStanzaType(stanza));
                    if (handlres.Count == 0)
                    {
                        if (stanza is IQ)
                        {
                            var iq = (IQ)stanza;
                            if ((iq.Type == IqType.error || iq.Type == IqType.result) && iq.HasTo && iq.To.HasUser)
                            {
                                //result and error retranslate to user
                                var session = context.SessionManager.GetSession(iq.To);
                                if (session != null)
                                {
                                    sender.SendTo(session, iq);
                                    return;
                                }
                            }
                            //result and error ignored by server
                        }
                        sender.SendTo(stream, XmppStanzaError.ToServiceUnavailable(stanza));
                        log.DebugFormat("Stanza handler not found for address '{0}'", address);
                        return;
                    }

                    bool      iqHandled = true;
                    Stopwatch stopwatch = null;

                    foreach (var handler in handlres)
                    {
                        if (log.IsDebugEnabled)
                        {
                            stopwatch = Stopwatch.StartNew();
                        }

                        if (stanza is IQ)
                        {
                            var answer = handler.HandleIQ(stream, (IQ)stanza.Clone(), context);
                            if (answer != null)
                            {
                                sender.SendTo(stream, answer);
                                iqHandled = answer.Id == stanza.Id;
                            }
                        }
                        else if (stanza is Message)
                        {
                            handler.HandleMessage(stream, (Message)stanza.Clone(), context);
                        }
                        else if (stanza is Presence)
                        {
                            handler.HandlePresence(stream, (Presence)stanza.Clone(), context);
                        }
                        else
                        {
                            sender.SendTo(stream, XmppStanzaError.ToNotAcceptable(stanza));
                            return;
                        }

                        if (log.IsDebugEnabled)
                        {
                            stopwatch.Stop();
                            log.DebugFormat("Process stanza handler '{1}' on address '{0}', time: {2}ms", address, handler.GetType().FullName, stopwatch.Elapsed.TotalMilliseconds);
                        }
                    }
                    if (!iqHandled)
                    {
                        sender.SendTo(stream, XmppStanzaError.ToServiceUnavailable(stanza));
                        return;
                    }
                }
            }
            catch (Exception ex)
            {
                ProcessException(ex, node, stream);
            }
        }
示例#5
0
 public void Send(Stanza stanza)
 {
     stanza.To = RealJid;
     sender.SendTo(Stream, stanza);
 }
示例#6
0
        private void HandlePresence(Presence presence, XmppSession session)
        {
            var toRosterItem   = GetUserRosterItem(presence.From, presence.To);
            var fromRosterItem = GetUserRosterItem(presence.To, presence.From);

            var stateOut = GetState(fromRosterItem, toRosterItem);
            var stateIn  = GetState(toRosterItem, fromRosterItem);

            bool bRoute          = false;
            bool bAutoReply      = false;
            bool bMutualCreating =
                (fromRosterItem.Subscribtion == SubscriptionType.to && toRosterItem.Subscribtion == SubscriptionType.from) ||
                (fromRosterItem.Subscribtion == SubscriptionType.from && toRosterItem.Subscribtion == SubscriptionType.to);

            var newType = presence.Type;

            if (newType == PresenceType.subscribe)
            {
                if (bMutualCreating)
                {
                    if (toRosterItem.Subscribtion == SubscriptionType.from && toRosterItem.Ask == AskType.NONE)
                    {
                        //Push roster with ASK=subscribe
                        toRosterItem.Ask = AskType.subscribe;
                        UpdateItems(presence, ref fromRosterItem, ref toRosterItem);
                        //Push
                        sender.Broadcast(
                            sessionManager.GetBareJidSessions(presence.From),
                            toRosterItem.GetRosterIq(presence.From)
                            );
                        //Forward
                        presence.To = new Jid(presence.To.Bare);
                        bool sended = sender.Broadcast(sessionManager.GetBareJidSessions(presence.To), presence);

                        if (!sended)
                        {
                            StoreOffline(presence);
                        }
                    }
                }
                else
                {
                    //it's inbound for user 'to'
                    ChangeInboundPresence(stateIn, toRosterItem, fromRosterItem, newType, out bRoute, out bAutoReply);
                    if (bAutoReply)
                    {
                        //Reply with 'subscribed'
                        var autoPresence = new Presence();
                        autoPresence.To   = presence.From;
                        autoPresence.From = presence.To;
                        autoPresence.Type = PresenceType.subscribed;
                        sender.Broadcast(sessionManager.GetBareJidSessions(autoPresence.To), autoPresence);
                    }
                    else
                    {
                        if (bRoute)
                        {
                            //Send to 'to' user
                            presence.To = new Jid(presence.To.Bare);
                            bool sended = sender.Broadcast(sessionManager.GetBareJidSessions(presence.To), presence);
                            if (!sended)
                            {
                                StoreOffline(presence);
                            }

                            //State is changed init roster push
                            UpdateItems(presence, ref fromRosterItem, ref toRosterItem);
                            sender.Broadcast(
                                sessionManager.GetBareJidSessions(presence.From),
                                toRosterItem.GetRosterIq(presence.From)
                                );
                            //Send result stanza
                            sender.SendTo(session, new IQ(IqType.result));
                        }
                    }
                }
            }
            else if (newType == PresenceType.subscribed)
            {
                if (bMutualCreating)
                {
                    if (fromRosterItem.Subscribtion == SubscriptionType.from && fromRosterItem.Ask == AskType.subscribe)
                    {
                        //Send roster to contact with both to 'from'
                        //Create both subscription

                        //Send subscribed back
                        toRosterItem.Subscribtion = SubscriptionType.both;
                        toRosterItem.Ask          = AskType.NONE;
                        UpdateItems(presence, ref fromRosterItem, ref toRosterItem);
                        sender.Broadcast(
                            sessionManager.GetBareJidSessions(presence.From),
                            toRosterItem.GetRosterIq(presence.From)
                            );
                        sender.SendTo(session, new IQ(IqType.result));
                        //fwd
                        presence.To = new Jid(presence.To.Bare);
                        if (!sender.Broadcast(sessionManager.GetBareJidSessions(presence.To), presence))
                        {
                            StoreOffline(presence);
                        }
                        //Send contact with both
                        fromRosterItem.Subscribtion = SubscriptionType.both;
                        fromRosterItem.Ask          = AskType.NONE;
                        UpdateItems(presence, ref fromRosterItem, ref toRosterItem);
                        sender.Broadcast(
                            sessionManager.GetBareJidSessions(presence.To),
                            fromRosterItem.GetRosterIq(presence.To)
                            );
                        //Send to session presence
                        if (session.Presence != null)
                        {
                            sender.Broadcast(sessionManager.GetBareJidSessions(presence.To), session.Presence);
                        }
                    }
                }
                else
                {
                    //It's outbound for user 'from'
                    ChangeOutboundPresence(stateOut, toRosterItem, fromRosterItem, newType, out bRoute);
                    //Roster oush for 'from'
                    if (bRoute)
                    {
                        //State is changed init roster push
                        UpdateItems(presence, ref fromRosterItem, ref toRosterItem);
                        sender.Broadcast(
                            sessionManager.GetBareJidSessions(presence.From),
                            toRosterItem.GetRosterIq(presence.From)
                            );
                        //Send result stanza
                        sender.SendTo(session, new IQ(IqType.result));                         //dont send
                    }
                    //It's inbound for user 'to'
                    if ((fromRosterItem.Subscribtion == SubscriptionType.none || fromRosterItem.Subscribtion == SubscriptionType.from) &&
                        fromRosterItem.Ask == AskType.subscribe)
                    {
                        ChangeInboundPresence(stateIn, fromRosterItem, toRosterItem, newType, out bRoute, out bAutoReply);
                        if (bRoute)
                        {
                            presence.To = new Jid(presence.To.Bare);
                            if (sender.Broadcast(sessionManager.GetBareJidSessions(presence.To), presence))
                            {
                                StoreOffline(presence);
                            }
                            else
                            {
                                if (session.Presence != null)
                                {
                                    sender.Broadcast(sessionManager.GetBareJidSessions(presence.To), session.Presence);
                                }
                            }
                            //State is changed init roster push
                            UpdateItems(presence, ref fromRosterItem, ref toRosterItem);
                            sender.Broadcast(
                                sessionManager.GetBareJidSessions(presence.To),
                                fromRosterItem.GetRosterIq(presence.To));
                        }
                    }
                }
            }
            else if (newType == PresenceType.unsubscribe)
            {
                //Get to roster
                //it's inbound for user 'to'
                ChangeInboundPresence(stateIn, toRosterItem, fromRosterItem, newType, out bRoute, out bAutoReply);
                if (bAutoReply)
                {
                    //Reply with 'subscribed'
                    Presence autoPresence = new Presence();
                    autoPresence.To   = presence.From;
                    autoPresence.From = presence.To;
                    autoPresence.Type = PresenceType.unsubscribed;
                    sender.Broadcast(sessionManager.GetBareJidSessions(autoPresence.To), autoPresence);
                    //Route
                    presence.To = new Jid(presence.To.Bare);
                    if (!sender.Broadcast(sessionManager.GetBareJidSessions(presence.To), presence))
                    {
                        StoreOffline(presence);
                    }
                }
            }
            else if (newType == PresenceType.unsubscribed)
            {
                //It's outbound for user 'from'
                ChangeOutboundPresence(stateOut, toRosterItem, fromRosterItem, newType, out bRoute);
                //Roster oush for 'from'
                if (bRoute)
                {
                    //State is changed init roster push
                    UpdateItems(presence, ref fromRosterItem, ref toRosterItem);
                    sender.Broadcast(
                        sessionManager.GetBareJidSessions(presence.From),
                        toRosterItem.GetRosterIq(presence.From));
                    //Send result stanza
                    sender.SendTo(session, new IQ(IqType.result));                     //dont send
                }

                ChangeInboundPresence(stateIn, fromRosterItem, toRosterItem, newType, out bRoute, out bAutoReply);
                if (bRoute)
                {
                    presence.To = new Jid(presence.To.Bare);
                    if (!sender.Broadcast(sessionManager.GetBareJidSessions(presence.To), presence))
                    {
                        StoreOffline(presence);
                    }
                    else
                    {
                        sender.Broadcast(
                            sessionManager.GetBareJidSessions(presence.To),
                            new Presence()
                        {
                            Type = PresenceType.unavailable, From = presence.From
                        });
                    }
                    //State is changed init roster push
                    UpdateItems(presence, ref fromRosterItem, ref toRosterItem);
                    sender.Broadcast(
                        sessionManager.GetBareJidSessions(presence.To),
                        fromRosterItem.GetRosterIq(presence.To));
                }
            }

            UpdateItems(presence, ref fromRosterItem, ref toRosterItem);
        }