示例#1
0
        public void Start(XmppConnection connection)
        {
            var auth = new SASLAuth();

            auth.SetAttributeValue("mechanism", SASLMethod);
            auth.SetValue(Initiate());
            connection.Send(auth);
            var authResponse = connection.NextElement();
            var nextResponse = string.Empty;

            Task.Run(() =>
            {
                while ((nextResponse = NextChallenge(authResponse.Value)) != "")
                {
                    if (nextResponse == "error")
                    {
                        OnAuthenticationFailed(connection);
                        return;
                    }
                    var response = new SASLResponse();
                    response.SetValue(nextResponse);
                    connection.Send(response);
                    authResponse = connection.NextElement();
                }
                OnAuthenticated(connection);
            });
        }
        public static AMQPHeader getSASL(IByteBuffer buf)
        {
            TLVAmqp list = TLVFactory.getTlv(buf);

            if (list.Code != AMQPType.LIST_0 && list.Code != AMQPType.LIST_8 && list.Code != AMQPType.LIST_32)
            {
                throw new MalformedMessageException("Received amqp-header with malformed arguments");
            }

            AMQPHeader header = null;

            Byte        byteCode = list.Constructor.getDescriptorCode().Value;
            HeaderCodes code     = (HeaderCodes)byteCode;

            switch (code)
            {
            case HeaderCodes.CHALLENGE:
                header = new SASLChallenge();
                break;

            case HeaderCodes.INIT:
                header = new SASLInit();
                break;

            case HeaderCodes.MECHANISMS:
                header = new SASLMechanisms();
                break;

            case HeaderCodes.OUTCOME:
                header = new SASLOutcome();
                break;

            case HeaderCodes.RESPONSE:
                header = new SASLResponse();
                break;

            default:
                throw new MalformedMessageException("Received sasl-header with unrecognized arguments code");
            }

            header.fillArguments((TLVList)list);

            return(header);
        }
        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();
            }));
        }
示例#4
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");
                    }
                }
            };
        }