public override void ElementHandle(XmppStream stream, Element element, XmppHandlerContext context)
        {
            if (stream.Authenticated)
            {
                return;
            }

            var    handshake = (Handshake)element;
            string digest    = handshake.Digest;
            string hash      = Hash.Sha1Hash(stream.Id + password);

            if (string.Compare(hash, digest, StringComparison.OrdinalIgnoreCase) == 0)
            {
                context.Sender.SendTo(stream, new Handshake());                 //TODO: auth with sha1
                //stream.Authenticated = true;
            }
            else
            {
                context.Sender.SendToAndClose(stream, XmppStreamError.NotAuthorized);
            }
        }
        private IQ GetPrivateLog(XmppStream stream, IQ iq, XmppHandlerContext context)
        {
            if (!iq.HasTo)
            {
                return(XmppStanzaError.ToBadRequest(iq));
            }

            var privateLog = (PrivateLog)iq.Query;

            privateLog.RemoveAllChildNodes();
            var logging = archiveStore.GetMessageLogging(iq.From, iq.To);

            privateLog.AddChild(new PrivateLogItem()
            {
                Jid = iq.To, Log = logging
            });

            iq.SwitchDirection();
            iq.Type = IqType.result;
            return(iq);
        }
        private IQ GetRegister(XmppStream stream, IQ iq, XmppHandlerContext context)
        {
            var register = (Register)iq.Query;

            register.Username = string.Empty;
            register.Password = string.Empty;
            iq.Type           = IqType.result;

            if (iq.From.HasUser && context.UserManager.IsUserExists(iq.From))
            {
                register.Username = iq.From.User;
                register.AddChild(new Element("registered"));
                iq.SwitchDirection();
                iq.From = null;
            }
            else
            {
                iq.From = iq.To = null;
            }
            return(iq);
        }
Exemple #4
0
        protected override IQ GetDiscoItems(XmppStream stream, IQ iq, XmppHandlerContext context)
        {
            if (((DiscoItems)iq.Query).Node != null)
            {
                return(XmppStanzaError.ToServiceUnavailable(iq));
            }

            var answer = new IQ(IqType.result);

            answer.Id   = iq.Id;
            answer.From = Jid;
            answer.To   = iq.From;
            var items = new DiscoItems();

            answer.Query = items;
            if (realJid != null)
            {
                items.AddDiscoItem().Jid = realJid;
            }
            return(answer);
        }
        private IQ GetHistory(XmppStream stream, IQ iq, XmppHandlerContext context)
        {
            if (!iq.HasTo)
            {
                return(XmppStanzaError.ToServiceUnavailable(iq));
            }

            FlushMessageBuffer();

            var history = (History)iq.Query;

            history.RemoveAllChildNodes();
            foreach (var m in archiveStore.GetMessages(iq.From, iq.To, history.From, history.To, history.Count))
            {
                history.AddChild(HistoryItem.FromMessage(m));
            }

            iq.Type = IqType.result;
            iq.SwitchDirection();
            return(iq);
        }
Exemple #6
0
        /// <summary>
        /// Create a Node.  Next, call Create and/or Subscribe.
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="jid"></param>
        /// <param name="node"></param>
        /// <param name="maxItems"></param>
        internal PubSubNode(XmppStream stream, JID jid, string node, int maxItems)
        {
            if (stream == null)
            {
                throw new ArgumentException("must not be null", "stream");
            }
            if (node == null)
            {
                throw new ArgumentException("must not be null", "node");
            }
            if (node == "")
            {
                throw new ArgumentException("must not be empty", "node");
            }

            m_stream             = stream;
            m_stream.OnProtocol += m_stream_OnProtocol;
            m_jid   = jid;
            m_node  = node;
            m_items = new ItemList(this, maxItems);
        }
        private IQ SetPrivate(XmppStream stream, IQ iq, XmppHandlerContext context)
        {
            var @private = (Private)iq.Query;

            if ([email protected])
            {
                return(XmppStanzaError.ToNotAcceptable(iq));
            }

            foreach (var childNode in @private.ChildNodes)
            {
                if (childNode is Element)
                {
                    context.StorageManager.PrivateStorage.SetPrivate(iq.From, (Element)childNode);
                }
            }
            iq.Query = null;
            iq.SwitchDirection();
            iq.Type = IqType.result;
            return(iq);
        }
Exemple #8
0
        public override IQ HandleIQ(XmppStream stream, IQ iq, XmppHandlerContext context)
        {
            //Admins iq

            //New member
            MucRoomMember member = Room.GetRealMember(iq.From);

            if (member != null)
            {
                if (iq.Query != null)
                {
                    if (iq.Query is Admin && (member.Affiliation == Affiliation.admin || member.Affiliation == Affiliation.owner))
                    {
                        Room.AdminCommand(iq, member);
                    }
                    else if (iq.Query is Owner && (member.Affiliation == Affiliation.owner))
                    {
                        Room.OwnerCommand(iq, member);
                    }
                    else
                    {
                        XmppStanzaError.ToForbidden(iq);
                    }
                }
                else
                {
                    XmppStanzaError.ToBadRequest(iq);
                }
            }
            else
            {
                XmppStanzaError.ToForbidden(iq);
            }
            if (!iq.Switched)
            {
                iq.SwitchDirection();
            }
            iq.From = Room.Jid;
            return(iq);
        }
Exemple #9
0
        private void ProcessException(Exception ex, Node node, XmppStream stream)
        {
            if (ex is JabberException)
            {
                log.Warn("JabberError", ex);
                var je    = (JabberException)ex;
                var error = je.ToElement();

                if (je.StreamError)
                {
                    ((Error)error).Text = je.Message;
                    sender.SendTo(stream, error);
                }
                else
                {
                    if (node is Stanza && error is StanzaError)
                    {
                        sender.SendTo(stream, XmppStanzaError.ToErrorStanza((Stanza)node, (StanzaError)error));
                    }
                    else
                    {
                        var streamError = XmppStreamError.InternalServerError;
                        streamError.Text = "Stanza error in stream.";
                        sender.SendToAndClose(stream, streamError);
                    }
                }

                if (je.CloseStream)
                {
                    sender.CloseStream(stream);
                }
            }
            else
            {
                log.Error("InternalServerError", ex);
                var error = XmppStreamError.InternalServerError;
                error.Text = ex.Message;
                sender.SendToAndClose(stream, error);
            }
        }
        public override void HandleMessage(XmppStream stream, Message message, XmppHandlerContext context)
        {
            if (!message.HasTo)
            {
                return;
            }
            if (archiveStore == null)
            {
                archiveStore = new DbMessageArchive();
                var properties = new Dictionary <string, string>(1);
                properties.Add("connectionStringName", "core");
                archiveStore.Configure(properties);
            }
            if (archiveStore.GetMessageLogging(message.From, message.To))
            {
                if (!string.IsNullOrEmpty(message.Body) ||
                    !string.IsNullOrEmpty(message.Subject) ||
                    !string.IsNullOrEmpty(message.Thread) ||
                    message.Html != null)
                {
                    var flush = false;
                    lock (messageBuffer)
                    {
                        //Add xdelay
                        if (message.XDelay == null)
                        {
                            message.XDelay       = new Delay();
                            message.XDelay.Stamp = DateTime.UtcNow;
                        }
                        messageBuffer.Add(message);

                        flush = BUFFER_SIZE <= messageBuffer.Count;
                    }
                    if (flush)
                    {
                        FlushMessageBuffer();
                    }
                }
            }
        }
        private void ProcessResponse(XmppStream stream, Response response, XmppHandlerContext context)
        {
            AuthData authStep;

            lock (authData)
            {
                authData.TryGetValue(stream.Id, out authStep);
            }

            if (authStep == null)
            {
                context.Sender.SendToAndClose(stream, XmppFailureError.TemporaryAuthFailure);
                return;
            }
            if (!authStep.IsPlain)
            {
                if (authStep.Step == AuthStep.Step1)
                {
                    var challenge = ProcessStep1(stream, response, context);
                    if (challenge != null)
                    {
                        context.Sender.SendTo(stream, challenge);
                        authStep.DoStep();
                    }
                    else
                    {
                        context.Sender.SendToAndClose(stream, XmppFailureError.NotAuthorized);
                    }
                }
                else if (authStep.Step == AuthStep.Step2)
                {
                    var success = ProcessStep2(stream, response, context);
                    context.Sender.SendTo(stream, success);
                }
                else
                {
                    context.Sender.SendToAndClose(stream, XmppFailureError.TemporaryAuthFailure);
                }
            }
        }
        public override IQ HandleIQ(XmppStream stream, IQ iq, XmppHandlerContext context)
        {
            //Admins iq

                //New member
                MucRoomMember member = Room.GetRealMember(iq.From);
                if (member!=null)
                {
                    if (iq.Query!=null)
                    {
                        if (iq.Query is Admin && (member.Affiliation==Affiliation.admin || member.Affiliation==Affiliation.owner))
                        {
                            Room.AdminCommand(iq, member);
                        }
                        else if (iq.Query is Owner && (member.Affiliation == Affiliation.owner))
                        {
                            Room.OwnerCommand(iq, member);
                        }
                        else
                        {
                            XmppStanzaError.ToForbidden(iq);
                        }
                    }
                    else
                    {
                        XmppStanzaError.ToBadRequest(iq);
                    }
            }
            else
            {
                XmppStanzaError.ToForbidden(iq);
            }
            if (!iq.Switched)
            {
                iq.SwitchDirection();
            }
            iq.From = Room.Jid;
            return iq;
        }
Exemple #13
0
        public MucRoomMember(MucRoom room, Jid memberJid, Jid realJid, XmppStream stream, XmppHandlerContext context)
        {
            if (room == null)
            {
                throw new ArgumentNullException("room");
            }
            if (memberJid == null)
            {
                throw new ArgumentNullException("memberJid");
            }
            if (realJid == null)
            {
                throw new ArgumentNullException("realJid");
            }
            if (context == null)
            {
                throw new ArgumentNullException("sender");
            }
            this.room    = room;
            this.stream  = stream;
            this.context = context;
            this.sender  = context.Sender;

            //Register disconect
            context.SessionManager.SessionUnavailable += SessionManager_SessionUnavailable;

            ParentService = room;
            RealJid       = realJid;
            Jid           = memberJid;
            Name          = memberJid.Resource;
            presenceType  = PresenceType.unavailable;
            //Create handler
            Handlers.Add(new MucRoomMemberStanzaHandler(this));
            Handlers.Add(new MucRoomMemberDiscoHandler(Jid, RealJid));

            DiscoInfo.AddIdentity(new DiscoIdentity("text", Name, "member"));
            DiscoInfo.AddFeature(new DiscoFeature(Core.protocol.Uri.DISCO_INFO));
            DiscoInfo.AddFeature(new DiscoFeature(Core.protocol.Uri.DISCO_ITEMS));
        }
        private void Announce(XmppStream stream, Message message, XmppHandlerContext context)
        {
            var userName = GetUser(message);

            message.Body = string.Format("{0} announces {1}", userName, message.Body);
            var offlineMessages = new List <Message>();

            foreach (var user in context.UserManager.GetUsers(stream.Domain))
            {
                message.To = user.Jid;
                var session = context.SessionManager.GetSession(message.To);
                if (session != null)
                {
                    context.Sender.SendTo(session, message);
                }
                else
                {
                    offlineMessages.Add(message);
                }
            }
            context.StorageManager.OfflineStorage.SaveOfflineMessages(offlineMessages.ToArray());
        }
Exemple #15
0
        protected virtual IQ GetDiscoInfo(XmppStream stream, IQ iq, XmppHandlerContext context)
        {
            if (((DiscoInfo)iq.Query).Node != null)
            {
                return(XmppStanzaError.ToServiceUnavailable(iq));
            }

            var service = ServiceManager.GetService(Jid);

            if (service == null)
            {
                return(XmppStanzaError.ToItemNotFound(iq));
            }

            var answer = new IQ(IqType.result);

            answer.Id    = iq.Id;
            answer.From  = Jid;
            answer.To    = iq.From;
            answer.Query = service.DiscoInfo;
            return(answer);
        }
        private IQ SetVCardSearch(XmppStream stream, IQ iq, XmppHandlerContext context)
        {
            var answer = new IQ(IqType.result);

            answer.Id   = iq.Id;
            answer.To   = iq.From;
            answer.From = iq.To;

            var search = (Search)iq.Query;

            var pattern = new Vcard();

            pattern.Nickname = search.Nickname;
            pattern.Name     = new Name(search.Lastname, search.Firstname, null);
            //pattern.AddEmailAddress(new Email() { UserId = search.Email });

            search = new Search();
            foreach (var vcard in context.StorageManager.VCardStorage.Search(pattern))
            {
                var item = new SearchItem();
                item.Jid      = vcard.JabberId;
                item.Nickname = vcard.Nickname;
                if (vcard.Name != null)
                {
                    item.Firstname = vcard.Name.Given;
                    item.Lastname  = vcard.Name.Family;
                }
                var email = vcard.GetPreferedEmailAddress();
                if (email != null)
                {
                    item.Email = email.UserId;
                }
                search.AddChild(item);
            }

            answer.Query = search;
            return(answer);
        }
Exemple #17
0
        public override void ElementHandle(XmppStream stream, Element element, XmppHandlerContext context)
        {
            var iq = (AuthIq)element;

            if (stream.Authenticated)
            {
                context.Sender.SendTo(stream, XmppStanzaError.ToConflict(iq));
                return;
            }

            if (iq.Type == IqType.get)
            {
                ProcessAuthIQGet(stream, iq, context);
            }
            else if (iq.Type == IqType.set)
            {
                ProcessAuthIQSet(stream, iq, context);
            }
            else
            {
                context.Sender.SendTo(stream, XmppStanzaError.ToNotAcceptable(iq));
            }
        }
Exemple #18
0
        public override void HandlePresence(XmppStream stream, Presence presence, XmppHandlerContext context)
        {
            var session = sessionManager.GetSession(presence.From);

            if (session == null)
            {
                context.Sender.SendTo(stream, XmppStanzaError.ToNotFound(presence));
                return;
            }

            if (presence.Type == PresenceType.available || presence.Type == PresenceType.invisible || presence.Type == PresenceType.unavailable)
            {
                sessionManager.SetSessionPresence(session, presence);
            }

            if (presence.HasTo && presence.To.ToString() != stream.Domain)
            {
                HandlePresence(presence, session);                //Presence to one of contacts
            }
            else
            {
                BroadcastPresence(presence);
            }
        }
 public override IQ HandleIQ(XmppStream stream, IQ iq, XmppHandlerContext context)
 {
     if (iq.Query is PrivateLog && iq.Type == IqType.get)
     {
         return(GetPrivateLog(stream, iq, context));
     }
     if (iq.Query is PrivateLog && iq.Type == IqType.set)
     {
         return(SetPrivateLog(stream, iq, context));
     }
     if (iq.Query is PrivateLog && (iq.Type == IqType.result || iq.Type == IqType.error))
     {
         return(null);
     }
     if (iq.Query is History && iq.Type == IqType.get)
     {
         return(GetHistory(stream, iq, context));
     }
     if (iq.Query is Chatmarkers && iq.Type == IqType.get)
     {
         return(ClearUnreadMessages(stream, iq, context, _serviceProvider));
     }
     return(XmppStanzaError.ToServiceUnavailable(iq));
 }
Exemple #20
0
        protected virtual IQ GetDiscoItems(XmppStream stream, IQ iq, XmppHandlerContext context)
        {
            if (((DiscoItems)iq.Query).Node != null)
            {
                return(XmppStanzaError.ToServiceUnavailable(iq));
            }

            var answer = new IQ(IqType.result);

            answer.Id   = iq.Id;
            answer.From = Jid;
            answer.To   = iq.From;
            var items = new DiscoItems();

            answer.Query = items;
            foreach (var service in ServiceManager.GetChildServices(Jid))
            {
                if (service.DiscoItem != null)
                {
                    items.AddDiscoItem(service.DiscoItem);
                }
            }
            return(answer);
        }
Exemple #21
0
        public override IQ HandleIQ(XmppStream stream, IQ iq, XmppHandlerContext context)
        {
            var answer = new IQ(IqType.result)
            {
                Id   = iq.Id,
                To   = iq.From,
                From = iq.To,
            };

            //iq sended to server
            if (iq.Type == IqType.get && (!iq.HasTo || iq.To.IsServer || iq.To == iq.From))
            {
                if (iq.Query is Version)
                {
                    answer.Query = new Version()
                    {
                        Name = "TeamLab Jabber Server",
                        Os   = System.Environment.OSVersion.ToString(),
                        Ver  = "1.0",
                    };
                    return(answer);
                }
                else if (iq.Query is Ping)
                {
                    return(answer);
                }
                return(XmppStanzaError.ToServiceUnavailable(iq));
            }

            if (iq.Type == IqType.get && iq.HasTo)
            {
                //resend iq
                var sessionTo   = context.SessionManager.GetSession(iq.To);
                var sessionFrom = context.SessionManager.GetSession(iq.From);
                if (sessionTo != null && sessionFrom != null)
                {
                    if (string.IsNullOrEmpty(iq.Id))
                    {
                        iq.Id = System.Guid.NewGuid().ToString("N");
                    }

                    IdleWatcher.StartWatch(
                        iq.Id + iq.From,
                        System.TimeSpan.FromSeconds(3),
                        (s, e) => { context.Sender.SendTo(sessionFrom, XmppStanzaError.ToServiceUnavailable(iq)); });
                    context.Sender.SendTo(sessionTo, iq);
                }
                else
                {
                    return(XmppStanzaError.ToRecipientUnavailable(iq));
                }
            }
            if (iq.Type == IqType.error || iq.Type == IqType.result)
            {
                if (!iq.HasTo)
                {
                    return(XmppStanzaError.ToBadRequest(iq));
                }

                IdleWatcher.StopWatch(iq.Id + iq.To);
                var session = context.SessionManager.GetSession(iq.To);
                if (session != null)
                {
                    context.Sender.SendTo(session, iq);
                }
            }
            return(null);
        }
 public virtual void HandlePresence(XmppStream stream, Presence presence, XmppHandlerContext context)
 {
 }
 public virtual void HandleMessage(XmppStream stream, Message message, XmppHandlerContext context)
 {
 }
 public virtual IQ HandleIQ(XmppStream stream, IQ iq, XmppHandlerContext context)
 {
     return(null);
 }
Exemple #25
0
 public override void HandlePresence(XmppStream stream, Presence presence, XmppHandlerContext context)
 {
     HandleMulticastStanza(stream, presence, context);
 }
Exemple #26
0
		public void DeclinedUser(Message msg, User user, XmppStream stream)
		{
			Message declineMsg = new Message(user.Decline.To, Jid, MessageType.normal, null);
			User userElement = new User();
			userElement.Decline = new Decline();
			userElement.Decline.From = msg.From;
			userElement.Decline.Reason = user.Decline.Reason;
			declineMsg.RemoveAllChildNodes();
			declineMsg.AddChild(userElement);
			Send(declineMsg);
		}
Exemple #27
0
 public void ElementHandle(XmppStream stream, Element element, XmppHandlerContext context)
 {
 }
Exemple #28
0
        private void ProcessAuth(XmppStream stream, Auth auth, XmppHandlerContext context)
        {
            AuthData authStep;

            lock (authData)
            {
                authData.TryGetValue(stream.Id, out authStep);
            }

            if (auth.MechanismType == MechanismType.DIGEST_MD5)
            {
                if (authStep != null)
                {
                    context.Sender.SendToAndClose(stream, XmppFailureError.TemporaryAuthFailure);
                }
                else
                {
                    lock (authData)
                    {
                        authData[stream.Id] = new AuthData();
                    }
                    var challenge = GetChallenge(stream.Domain);
                    context.Sender.SendTo(stream, challenge);
                }
            }
            else if (auth.MechanismType == MechanismType.PLAIN)
            {
                if (auth.TextBase64 == null)
                {
                    context.Sender.SendToAndClose(stream, XmppFailureError.TemporaryAuthFailure);
                }
                else
                {
                    string[] array = auth.TextBase64.Split('\0');
                    if (array.Length == 3)
                    {
                        string userName = array[1];
                        string password = array[2];
                        bool   isAuth   = false;
                        User   user     = context.UserManager.GetUser(new Jid(userName, stream.Domain, null));
                        if (user != null)
                        {
                            if (user.Sid != null)
                            {
                                var settings = LdapSettings.Load();

                                using (var ldapHelper = new NovellLdapHelper(settings))
                                {
                                    var accountName = ldapHelper.GetUserBySid(user.Sid);

                                    if (accountName != null)
                                    {
                                        ldapHelper.CheckCredentials(settings.Login, password, settings.Server,
                                                                    settings.PortNumber, settings.StartTls, settings.Ssl,
                                                                    settings.AcceptCertificate, settings.AcceptCertificateHash);

                                        // ldap user
                                        isAuth = true;
                                    }
                                }
                            }
                            else if (user.Password == password)
                            {
                                // usual user
                                isAuth = true;
                            }
                        }
                        if (isAuth)
                        {
                            log.DebugFormat("User {0} authorized, Domain = {1}", userName, stream.Domain);
                            context.Sender.ResetStream(stream);
                            stream.Authenticate(userName);
                            context.Sender.SendTo(stream, new Success());
                        }
                        else
                        {
                            log.DebugFormat("User {0} not authorized, Domain = {1}", userName, stream.Domain);
                            context.Sender.SendToAndClose(stream, XmppFailureError.NotAuthorized);
                        }
                    }
                    else
                    {
                        context.Sender.SendToAndClose(stream, XmppFailureError.TemporaryAuthFailure);
                    }
                }
            }
            else
            {
                context.Sender.SendToAndClose(stream, XmppFailureError.InvalidMechanism);
            }
        }
Exemple #29
0
 private void ProcessAbort(XmppStream stream, Abort abort, XmppHandlerContext context)
 {
     context.Sender.SendToAndClose(stream, XmppFailureError.Aborted);
 }
 private void HandleUserMessage(Message msg, User user, XmppStream stream)
 {
     if (user.Invite != null)
     {
         Room.InviteUser(msg, user,stream);
     }
     else if (user.Decline != null)
     {
         Room.DeclinedUser(msg, user,stream);
     }
 }
Exemple #31
0
		public void InviteUser(Message msg, User user, XmppStream stream)
		{
			if (RoomSettings.CanInvite)
			{
				Message inviteMsg = new Message(user.Invite.To, Jid, MessageType.normal, null);
				User userElement = new User();
				userElement.Invite = new Invite();

				MucRoomMember member = GetRealMember(msg.From);
				userElement.Invite.From = member == null ? msg.From : member.Jid;
				userElement.Invite.Reason = user.Invite.Reason;
				inviteMsg.RemoveAllChildNodes();
				inviteMsg.AddChild(userElement);

				if (!Send(inviteMsg))
				{
					// Return error
					msg.SwitchDirection();
					msg.Type = MessageType.error;
					msg.Error = new Error(ErrorType.cancel, ErrorCondition.ItemNotFound);
					Sender.SendTo(stream, msg);
				}
			}
			else
			{
				msg.SwitchDirection();
				msg.Type = MessageType.error;
				msg.Error = new Error(ErrorType.cancel, ErrorCondition.NotAllowed);
				Sender.SendTo(stream, msg);
			}
		}
        public bool ValidateNode(Node node, XmppStream stream, XmppHandlerContext handlercontext)
        {
#if (SCHEME)
            var stopwatch = new Stopwatch();
            if (log.IsDebugEnabled)
            {
                stopwatch.Reset();
                stopwatch.Start();
            }
            int  result = ValidateNodeInternal(node);
            if (log.IsDebugEnabled)
            {
                stopwatch.Stop();
                log.DebugFormat("Node validated. Error count: {1}. time: {0}ms", stopwatch.ElapsedMilliseconds, result);
            }
            return result==0;
#else
            return true;
#endif
            
        }
Exemple #33
0
 public override void HandleMessage(XmppStream stream, Message message, XmppHandlerContext context)
 {
     HandleMulticastStanza(stream, message, context);
 }
Exemple #34
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);
            }
        }
		private IQ SetRoster(XmppStream stream, IQ iq, XmppHandlerContext context)
		{
			var answer = new IQ(IqType.result);
			answer.Id = iq.Id;
			answer.To = iq.From;
			answer.From = iq.To;

			iq.Id = UniqueId.CreateNewId();
			var roster = (Roster)iq.Query;
			UserRosterItem item = null;
			try
			{
				var rosterItems = roster.GetRoster();
				if (rosterItems.Length != 1) throw new JabberException(ErrorCode.BadRequest);

				var rosterItem = rosterItems[0];
				item = UserRosterItem.FromRosterItem(rosterItem);

				if (rosterItem.Subscription == SubscriptionType.remove)
				{
					context.StorageManager.RosterStorage.RemoveRosterItem(iq.From, item.Jid);

					//Send presences
					var unsubscribe = new Presence() { Type = PresenceType.unsubscribe, To = item.Jid, From = iq.From };
					var unsubscribed = new Presence() { Type = PresenceType.unsubscribed, To = item.Jid, From = iq.From };
					var unavailable = new Presence() { Type = PresenceType.unavailable, To = item.Jid, From = iq.From };

					bool sended = false;
					foreach (var session in context.SessionManager.GetBareJidSessions(item.Jid))
					{
						if (session.RosterRequested)
						{
							context.Sender.SendTo(session, unsubscribe);
							context.Sender.SendTo(session, unsubscribed);
							sended = true;
						}
						context.Sender.SendTo(session, unavailable);
					}
					if (!sended)
					{
						context.StorageManager.OfflineStorage.SaveOfflinePresence(unsubscribe);
						context.StorageManager.OfflineStorage.SaveOfflinePresence(unsubscribed);
					}
				}
				else
				{
					item = context.StorageManager.RosterStorage.SaveRosterItem(iq.From, item);
					roster.RemoveAllChildNodes();
					roster.AddRosterItem(item.ToRosterItem());
				}
				//send all available user's resources
				context.Sender.Broadcast(context.SessionManager.GetBareJidSessions(iq.From), iq);
			}
			catch (System.Exception)
			{
				roster.RemoveAllChildNodes();
				item = context.StorageManager.RosterStorage.GetRosterItem(iq.From, item.Jid);
				if (item != null)
				{
					roster.AddRosterItem(item.ToRosterItem());
					context.Sender.Broadcast(context.SessionManager.GetBareJidSessions(iq.From), iq);
				}
				throw;
			}

			return answer;
		}