예제 #1
0
        public void IdentityTests()
        {
            var info = new DiscoInfo
            {
                Identity = new Identity
                {
                    IdentityName = "SharpXMPP",
                    IdentityType = "pc",
                    Category     = "client"
                },
                Features = new List <string>
                {
                    Namespaces.DiscoInfo
                }
            };
            var cf = new XElement(XNamespace.Get("storage:bookmarks") + "conference");

            cf.SetAttributeValue("jid", "*****@*****.**");
            cf.SetAttributeValue("name", "lalallaa");
            cf.SetAttributeValue("autojoin", "false");
            var room = Stanza.Parse <BookmarkedConference>(cf);

            Assert.IsFalse(room.IsAutojoin);
            var cf2 = new XElement(XNamespace.Get("storage:bookmarks") + "conference");

            cf2.SetAttributeValue("jid", "*****@*****.**");
            cf2.SetAttributeValue("name", "lalallaa");
            cf2.SetAttributeValue("autojoin", "1");
            var room2 = Stanza.Parse <BookmarkedConference>(cf2);

            Assert.IsTrue(room2.IsAutojoin);
        }
예제 #2
0
 public override void SessionLoop()
 {
     while (true)
     {
         try
         {
             var el = NextElement();
             if (el.Name.LocalName.Equals("iq"))
             {
                 OnIq(Stanza.Parse <XMPPIq>(el));
             }
             if (el.Name.LocalName.Equals("message"))
             {
                 OnMessage(Stanza.Parse <XMPPMessage>(el));
             }
             if (el.Name.LocalName.Equals("presence"))
             {
                 OnPresence(Stanza.Parse <XMPPPresence>(el));
             }
         }
         catch (Exception e)
         {
             OnConnectionFailed(new ConnFailedArgs {
                 Message = e.Message
             });
             break;
         }
     }
 }
        public static void BookmarksManagerSendsThePasswordToJoin()
        {
            using var stream     = new MemoryStream();
            using var connection = new MockedXmppTcpConnection(null, stream);
            var elements = new List <XElement>();

            connection.Element += (_, element) => elements.Add(element.Stanza);

            var conference = new BookmarkedConference
            {
                JID      = new JID("*****@*****.**"),
                Password = "******"
            };
            var bookmarksManager = new BookmarksManager(connection, false);

            bookmarksManager.Join(conference);

            Thread.MemoryBarrier();
            var joinElement = Stanza.Parse <XMPPPresence>(elements.Single());
            var password    = joinElement
                              .Element(XNamespace.Get(Namespaces.MUC) + "x") !
                              .Element(XNamespace.Get(Namespaces.MUC) + "password") !
                              .Value;

            Assert.AreEqual("12345", password);
        }
예제 #4
0
 public BookmarksManager(XmppConnection conn, bool autoAsk = true)
 {
     connection           = conn;
     connection.SignedIn += (sender, e) =>
     {
         if (autoAsk)
         {
             var query = new XMPPIq(XMPPIq.IqTypes.get);
             var priv  = new XElement(XNamespace.Get("jabber:iq:private") + "query",
                                      new XElement(XNamespace.Get(Namespaces.StorageBookmarks) + "storage")
                                      );
             query.Add(priv);
             connection.Query(query, (response) =>
             {
                 var roomsXML = response.Element(XNamespace.Get("jabber:iq:private") + "query")
                                .Element(XNamespace.Get(Namespaces.StorageBookmarks) + "storage")
                                .Elements(XNamespace.Get(Namespaces.StorageBookmarks) + "conference");
                 foreach (var roomObj in roomsXML)
                 {
                     var room = Stanza.Parse <BookmarkedConference>(roomObj);
                     Rooms.Add(room);
                     if (room.IsAutojoin)
                     {
                         Join(room);
                     }
                 }
                 OnBookmarksSynced(conn);
             });
         }
     };
 }
예제 #5
0
 public void Start(XmppTcpConnection connection)
 {
     connection.Features = Stanza.Parse <Features>(connection.NextElement());
     if (connection.Features.Bind)
     {
         var bind = new Elements.Bind(connection.Jid.Resource);
         var iq   = new XMPPIq(XMPPIq.IqTypes.set);
         iq.Add(bind);
         connection.Query(iq, (bindResult) =>
         {
             var jid = bindResult.Element(XNamespace.Get(Namespaces.XmppBind) + "bind");
             if (jid == null)
             {
                 return;
             }
             connection.Jid = new JID(jid.Element(XNamespace.Get(Namespaces.XmppBind) + "jid").Value);
             if (connection.Features.Session)
             {
                 var sess   = new XElement(XNamespace.Get(Namespaces.XmppSession) + "session");
                 var sessIq = new XMPPIq(XMPPIq.IqTypes.set);
                 sessIq.Add(sess);
                 connection.Query(sessIq, (sessionResponse) => OnSessionStarted(connection));
             }
             else
             {
                 OnSessionStarted(connection);
             }
         });
         connection.SessionLoop();
     }
 }
예제 #6
0
 public override bool Handle(XmppConnection sender, XMPPIq element)
 {
     if (Stanza.Parse <DiscoItems>(element.Elements().FirstOrDefault()) != null)
     {
         sender.Send(element.Reply());
         return(true);
     }
     return(false);
 }
예제 #7
0
        private async Task <bool> InitTlsIfSupported(Features features)
        {
            if (!features.Tls)
            {
                return(false);
            }

            Send(new StartTLS());
            var res = Stanza.Parse <Proceed>(NextElement());

            if (res == null)
            {
                return(false);
            }

            ConnectionStream = new SslStream(ConnectionStream, true);
            await((SslStream)ConnectionStream).AuthenticateAsClientAsync(Jid.Domain);
            RestartXmlStreams();
            return(true);
        }
예제 #8
0
        public override bool Handle(XmppConnection connection, XMPPIq element)
        {
            var info = Stanza.Parse <DiscoInfo>(element.Elements().FirstOrDefault());

            if (info != null)
            {
                if (info.Node == string.Empty || info.Node == string.Format("{0}#{1}", _capabilities.Node, _capabilities.OurHash))
                {
                    info.Identity = _capabilities.Identity;
                    info.Features = _capabilities.Features;
                    info.Node     = _capabilities.Node;
                    var reply = element.Reply();
                    reply.RemoveNodes();
                    reply.Add(info);
                    connection.Send(reply);
                    return(true);
                }
            }
            return(false);
        }
예제 #9
0
 public override Task SessionLoopAsync(CancellationToken token)
 {
     return(Task.Run(() =>
     {
         while (!token.IsCancellationRequested)
         {
             try
             {
                 var el = NextElement();
                 token.ThrowIfCancellationRequested();
                 if (el.Name.LocalName.Equals("iq"))
                 {
                     token.ThrowIfCancellationRequested();
                     OnIq(Stanza.Parse <XMPPIq>(el));
                 }
                 if (el.Name.LocalName.Equals("message"))
                 {
                     token.ThrowIfCancellationRequested();
                     OnMessage(Stanza.Parse <XMPPMessage>(el));
                 }
                 if (el.Name.LocalName.Equals("presence"))
                 {
                     token.ThrowIfCancellationRequested();
                     OnPresence(Stanza.Parse <XMPPPresence>(el));
                 }
             }
             catch (OperationCanceledException)
             {
                 break;
             }
             catch (Exception e)
             {
                 OnConnectionFailed(new ConnFailedArgs {
                     Message = e.Message
                 });
                 break;
             }
         }
     }, token));
 }
예제 #10
0
        public void StanzaTests()
        {
            const string xmldata    = "<stream:error xmlns:stream=\"http://etherx.jabber.org/streams\"><not-well-formed xmlns=\"urn:ietf:params:xml:ns:xmpp-streams\" /></stream:error>";
            var          errorinput = XElement.Parse(xmldata);
            var          payload    = Stanza.Parse <StreamError>(errorinput);

            Assert.AreEqual(StreamErrorType.NotWellFormed, payload.ErrorType);

            var error = new StreamError {
                ErrorType = StreamErrorType.NotWellFormed
            };

            // Remove all namespace attributes.
            error.DescendantsAndSelf().Attributes().Where(n => n.IsNamespaceDeclaration).Remove();

            // Specify that the namespace will be serialized with a namespace prefix of 'stream'.
            error.Add(new XAttribute(XNamespace.Xmlns + "stream", Namespaces.Streams));
            Assert.AreEqual(payload.ToString(), Stanza.Parse <StreamError>(XElement.Parse(error.ToString())).ToString());
            var bad = Stanza.Parse <StartTLS>(errorinput);

            Assert.IsNull(bad);
        }
예제 #11
0
 public RosterManager(XmppConnection conn, bool autoAsk = true)
 {
     Roster         = new ObservableCollection <RosterItem>();
     conn.SignedIn += (sender, e) =>
     {
         if (autoAsk)
         {
             var query = new XMPPIq(XMPPIq.IqTypes.get);
             query.Add(new XElement(XNamespace.Get(Namespaces.JabberRoster) + "query"));
             conn.Query(query, (response) =>
             {
                 var roster = response.Element(XNamespace.Get(Namespaces.JabberRoster) + "query")
                              .Elements(XNamespace.Get(Namespaces.JabberRoster) + "item");
                 foreach (var item in roster)
                 {
                     Roster.Add(Stanza.Parse <RosterItem>(item));
                 }
                 OnRosterUpdated(conn);
             });
         }
     };
 }
예제 #12
0
        public override async void Connect()
        {
            List <IPAddress> HostAddresses = new List <IPAddress>();

            var srvs = await Resolver.ResolveXMPPClient(Jid.Domain);

            if (srvs.Any())
            {
                foreach (var srv in srvs)
                {
                    var addresses = await Dns.GetHostAddressesAsync(srv.Host);

                    HostAddresses.AddRange(addresses);
                }
            }
            else
            {
                HostAddresses.AddRange(await Dns.GetHostAddressesAsync(Jid.Domain));
            }
            _client = new TcpClient();
            await _client.ConnectAsync(HostAddresses.ToArray(), TcpPort); // TODO: check ports

            ConnectionStream = _client.GetStream();
            Iq += (sender, iq) => new IqManager(this)
            {
                PayloadHandlers = new List <PayloadHandler>
                {
                    new InfoHandler(Capabilities),
                    new ItemsHandler()
                }
            }.Handle(iq);
            RestartXmlStreams();
            var features = Stanza.Parse <Features>(NextElement());

            if (features.Tls)
            {
                Send(new StartTLS());
                var res = Stanza.Parse <Proceed>(NextElement());
                if (res != null)
                {
                    ConnectionStream = new SslStream(ConnectionStream, true);
                    await((SslStream)ConnectionStream).AuthenticateAsClientAsync(Jid.Domain);
                    RestartXmlStreams();
                    features = Stanza.Parse <Features>(NextElement());
                }
            }

            var authenticator = SASLHandler.Create(features.SaslMechanisms, Jid, Password);

            if (authenticator == null)
            {
                OnConnectionFailed(new ConnFailedArgs {
                    Message = "supported sasl mechanism not available"
                });
                return;
            }
            authenticator.Authenticated += sender =>
            {
                RestartXmlStreams();
                var session = new SessionHandler();
                session.SessionStarted += connection => OnSignedIn(new SignedInArgs {
                    Jid = connection.Jid
                });
                session.Start(this);
            };
            authenticator.AuthenticationFailed += sender =>
            {
                OnConnectionFailed(new ConnFailedArgs {
                    Message = "Authentication failed"
                });
                return;
            };
            authenticator.Start(this);
        }
예제 #13
0
 private Features GetServerFeatures() => Stanza.Parse <Features>(NextElement());
        public void ReadStreamStart(string data, string defaultNamespace = Namespaces.JabberClient)
        {
            var mngr = Stanza.Parse <Open>(XElement.Parse(data));

            OnStreamStart(mngr.ID);
        }
        public override Task ConnectAsync(CancellationToken token)
        {
            return(Task.Run(async() =>
            {
                if (string.IsNullOrEmpty(websocketUri))
                {
                    var lookup = new LookupClient();
                    var response = await lookup.QueryAsync("_xmppconnect." + Jid.Domain, QueryType.TXT);
                    if (response.Answers.TxtRecords().Any())
                    {
                        foreach (var srv in response.Answers.TxtRecords())
                        {
                            foreach (var addr in srv.Text)
                            {
                                if (addr.StartsWith("_xmpp-client-websocket"))
                                {
                                    websocketUri = addr.Split('=')[1];
                                    break;
                                }
                            }
                        }
                    }
                }
                if (string.IsNullOrEmpty(websocketUri))
                {
                    OnConnectionFailed(new ConnFailedArgs
                    {
                        Message = "WebSocket URI is not resolved or set."
                    });
                    return;
                }
                _connection = new WebSocket(websocketUri, "xmpp", WebSocketVersion.Rfc6455);
                _connection.Opened += (sender, args) =>

                {
                    _currentState = XmppConnectionState.Connected;
                    RestartStream();
                };
                _connection.MessageReceived += (sender, args) =>
                {
                    OnElement(new ElementArgs
                    {
                        IsInput = true,
                        Stanza = XElement.Parse(args.Message)
                    });
                    if (_currentState == XmppConnectionState.Connected)
                    {
                        ReadStreamStart(args.Message);
                        _currentState = XmppConnectionState.StreamInitiated;
                    }
                    else if (_currentState == XmppConnectionState.StreamAuthenticated)
                    {
                        ReadStreamStart(args.Message);
                        _currentState =
                            XmppConnectionState.StreamResourceBindingRequest;
                    }
                    else
                    {
                        var currentStanza = XElement.Parse(args.Message);
                        var error = Stanza.Parse <StreamError>(currentStanza);
                        if (error != null)
                        {
                            OnConnectionFailed(new ConnFailedArgs {
                                Message = error.Value
                            });
                            return;
                        }
                        switch (_currentState)
                        {
                        case XmppConnectionState.StreamInitiated:

                            var features = Stanza.Parse <Features>(currentStanza);

                            authenticator = SASLHandler.Create(features.SaslMechanisms,
                                                               Jid, Password);
                            if (authenticator == null)
                            {
                                OnConnectionFailed(new ConnFailedArgs
                                {
                                    Message = "supported sasl mechanism not available"
                                });
                                return;
                            }
                            var auth = new SASLAuth();
                            auth.SetAttributeValue("mechanism", authenticator.SASLMethod);
                            var authInit = authenticator.Initiate();
                            if (!string.IsNullOrEmpty(authInit))
                            {
                                auth.SetValue(authInit);
                            }
                            Send(auth);
                            _currentState = XmppConnectionState.StreamAuthenticating;
                            break;

                        case XmppConnectionState.StreamAuthenticating:
                            switch (currentStanza.Name.LocalName)
                            {
                            case "success":
                                _currentState =
                                    XmppConnectionState.StreamAuthenticated;
                                RestartStream();
                                break;

                            case "failure":
                                OnConnectionFailed(new ConnFailedArgs
                                {
                                    Message = currentStanza.Value
                                });
                                _currentState = XmppConnectionState.Disconnected;
                                return;

                            case "challenge":
                                var response = new SASLResponse();
                                response.SetValue(
                                    authenticator.NextChallenge(currentStanza.Value));
                                Send(response);
                                break;
                            }
                            break;

                        case XmppConnectionState.StreamResourceBindingRequest:
                            // todo: parse features of negotiated stream
                            //Stanza.Parse<Features>(currentStanza);
                            var bind = new Bind(Jid.Resource);
                            var iq = new XMPPIq(XMPPIq.IqTypes.set);
                            iq.Add(bind);
                            Send(iq);
                            _currentState =
                                XmppConnectionState.StreamResourceBindingResponse;
                            break;

                        case XmppConnectionState.StreamResourceBindingResponse:
                            var bindedJid =
                                currentStanza.Element(
                                    XNamespace.Get(Namespaces.XmppBind) +
                                    "bind");
                            if (bindedJid == null)
                            {
                                OnConnectionFailed(new ConnFailedArgs
                                {
                                    Message = "bind failed"
                                });
                                _currentState = XmppConnectionState.Disconnected;
                            }
                            else
                            {
                                var sess =
                                    new XElement(
                                        XNamespace.Get(Namespaces.XmppSession) +
                                        "session");
                                var sessIq = new XMPPIq(XMPPIq.IqTypes.set);
                                sessIq.Add(sess);
                                Send(sessIq);
                                _currentState = XmppConnectionState.StreamSessionNoOp;
                                Jid =
                                    new JID(
                                        bindedJid.Element(
                                            XNamespace.Get(Namespaces.XmppBind) + "jid")
                                        .Value);
                            }
                            break;

                        case XmppConnectionState.StreamSessionNoOp:
                            OnSignedIn(new SignedInArgs {
                                Jid = Jid
                            });
                            _currentState = XmppConnectionState.StreamNegotiated;
                            break;

                        case XmppConnectionState.StreamNegotiated:
                            if (currentStanza.Name.LocalName.Equals("iq"))
                            {
                                OnIq(Stanza.Parse <XMPPIq>(currentStanza));
                            }
                            if (currentStanza.Name.LocalName.Equals("message"))
                            {
                                OnMessage(Stanza.Parse <XMPPMessage>(currentStanza));
                            }
                            if (currentStanza.Name.LocalName.Equals("presence"))
                            {
                                OnPresence(Stanza.Parse <XMPPPresence>(currentStanza));
                            }
                            break;

                        default:
                            throw new IOException("Invalid state");
                        }
                    }
                };
                _connection.Open();
            }));
        }
예제 #16
0
        public XmppWebSocketConnection(JID jid, string password, string websocketUri)
            : base(jid, password)
        {
            Capabilities = new CapabilitiesManager
            {
                Identity = new Identity
                {
                    Category     = "client",
                    IdentityType = "mobile",
                    IdentityName = "SharpXMPP"
                },

                Node     = "http://bggg.net.ru/caps",
                Features = new List <string>
                {
                    Namespaces.DiscoInfo,
                    Namespaces.DiscoItems
                }
            };
            IqTracker = new XMPP.Client.IqHandler(this)
            {
                ResponseHandlers = new Dictionary <string, ResponseHandler>(),
                PayloadHandlers  = new List <PayloadHandler>
                {
                    new InfoHandler(Capabilities),
                    new ItemsHandler()
                }
            };
            Iq += (sender, iq) => IqTracker.Handle(iq);
// ReSharper disable RedundantArgumentDefaultValue
            _connection = new WebSocket(websocketUri, "xmpp", cookies: (List <KeyValuePair <string, string> >)null);
// ReSharper restore RedundantArgumentDefaultValue
            _connection.Opened += (sender, args) =>

            {
                _currentState = XmppConnectionState.Connected;
                RestartStream();
            };
            _connection.MessageReceived += (sender, args) =>
            {
                if (_currentState == XmppConnectionState.Connected)
                {
                    ReadStreamStart(args.Message);
                    _currentState = XmppConnectionState.StreamInitiated;
                }
                else if (_currentState == XmppConnectionState.StreamAuthenticated)
                {
                    ReadStreamStart(args.Message);
                    _currentState =
                        XmppConnectionState.StreamResourceBindingRequest;
                }
                else
                {
                    var currentStanza = Stanza.Parse(args.Message);
                    OnElement(new ElementArgs
                    {
                        IsInput = false,
                        Stanza  = currentStanza
                    });
                    var error = Stanza.Parse <StreamError>(currentStanza);
                    if (error != null)
                    {
                        OnConnectionFailed(new ConnFailedArgs {
                            Message = error.Value
                        });
                        return;
                    }
                    switch (_currentState)
                    {
                    case XmppConnectionState.StreamInitiated:

                        var features = Stanza.Parse <Features>(currentStanza);

                        authenticator = SASLHandler.Create(features.SaslMechanisms,
                                                           Jid, Password);
                        if (authenticator == null)
                        {
                            OnConnectionFailed(new ConnFailedArgs
                            {
                                Message =
                                    "supported sasl mechanism not available"
                            });
                            return;
                        }
                        var auth = new SASLAuth();
                        auth.SetAttributeValue("mechanism", authenticator.SASLMethod);
                        var authInit = authenticator.Initiate();
                        if (!string.IsNullOrEmpty(authInit))
                        {
                            auth.SetValue(authInit);
                        }
                        Send(auth);
                        _currentState = XmppConnectionState.StreamAuthenticating;
                        break;

                    case XmppConnectionState.StreamAuthenticating:
                        switch (currentStanza.Name.LocalName)
                        {
                        case "success":
                            _currentState =
                                XmppConnectionState.StreamAuthenticated;
                            RestartStream();
                            break;

                        case "failure":
                            OnConnectionFailed(new ConnFailedArgs
                            {
                                Message =
                                    currentStanza.Value
                            });
                            _currentState = XmppConnectionState.Disconnected;
                            return;

                        case "challenge":
                            var response = new SASLResponse();
                            response.SetValue(
                                authenticator.NextChallenge(currentStanza.Value));
                            Send(response);
                            break;
                        }
                        break;

                    case XmppConnectionState.StreamResourceBindingRequest:
                        // todo: parse features of negotiated stream
                        //Stanza.Parse<Features>(currentStanza);
                        var bind = new Bind(Jid.Resource);
                        var iq   = new Iq(XMPP.Client.Elements.Iq.IqTypes.set);
                        iq.Add(bind);
                        Send(iq);
                        _currentState =
                            XmppConnectionState.StreamResourceBindingResponse;
                        break;

                    case XmppConnectionState.StreamResourceBindingResponse:
                        var bindedJid =
                            currentStanza.Element(
                                XNamespace.Get(Namespaces.XmppBind) +
                                "bind");
                        if (bindedJid == null)
                        {
                            OnConnectionFailed(new ConnFailedArgs
                            {
                                Message =
                                    "bind failed"
                            });
                            _currentState = XmppConnectionState.Disconnected;
                        }
                        else
                        {
                            var sess =
                                new XElement(
                                    XNamespace.Get(Namespaces.XmppSession) +
                                    "session");
                            var sessIq = new Iq(XMPP.Client.Elements.Iq.IqTypes.set);
                            sessIq.Add(sess);
                            Send(sessIq);
                            _currentState = XmppConnectionState.StreamSessionNoOp;
                            Jid           =
                                new JID(
                                    bindedJid.Element(
                                        XNamespace.Get(Namespaces.XmppBind) + "jid")
                                    .Value);
                        }
                        break;

                    case XmppConnectionState.StreamSessionNoOp:
                        OnSignedIn(new SignedInArgs {
                            Jid = Jid
                        });
                        Roster.Query(this);
                        var initPresence = new Presence(Capabilities);
                        Send(initPresence);
                        _currentState = XmppConnectionState.StreamNegotiated;
                        break;

                    case XmppConnectionState.StreamNegotiated:
                        if (currentStanza.Name.LocalName.Equals("iq"))
                        {
                            OnIq(Stanza.Parse <Iq>(currentStanza));
                        }
                        if (currentStanza.Name.LocalName.Equals("message"))
                        {
                            OnMessage(Stanza.Parse <Message>(currentStanza));
                        }
                        break;

                    default:
                        throw new IOException("Invalid state");
                    }
                }
            };
        }