Example #1
0
        /// <summary>
        /// Called once the connection timer got triggered.
        /// </summary>
        private async Task OnConnetionTimerTimeoutAsync()
        {
            string errorMessage = "Connection timeout got triggered for account: " + account.getBareJid();

            Logger.Warn(LOGGER_TAG + errorMessage);
            lastConnectionError = new ConnectionError(ConnectionErrorCode.XMPP_CONNECTION_TIMEOUT, errorMessage);

            await OnConnectionErrorAsync();
        }
Example #2
0
        /// <summary>
        /// Called once the connection timer got triggered.
        /// </summary>
        private async Task onConnetionTimerTimeoutAsync()
        {
            string errorMessage = "Connection timeout got triggered for account: " + account.getIdAndDomain();

            Logger.Warn(errorMessage);
            lastConnectionError = new ConnectionError(ConnectionErrorCode.XMPP_CONNECTION_TIMEOUT, errorMessage);

            await onConnectionErrorAsync();
        }
Example #3
0
        private async void TCPConnection_ConnectionStateChanged(AbstractConnection2 connection, ConnectionStateChangedEventArgs args)
        {
            switch (args.newState)
            {
            case ConnectionState.CONNECTED:
                // TCP connection established start reading:
                TCP_CONNECTION.startReaderTask();

                // Send initial stream header:
                await softRestartAsync();

                break;

            case ConnectionState.ERROR:
                if (args.param is ConnectionError cError)
                {
                    lastConnectionError = cError;
                }
                if (args.oldState == ConnectionState.CONNECTED)
                {
                    switch (state)
                    {
                    case ConnectionState.CONNECTING:
                    case ConnectionState.CONNECTED:
                        await onConnectionErrorAsync();

                        break;

                    case ConnectionState.DISCONNECTING:
                        setState(ConnectionState.DISCONNECTED);
                        break;
                    }
                }
                else
                {
                    // Unable to connect to server:
                    connectionErrorCount = 3;
                    await internalDisconnectAsync();

                    setState(ConnectionState.ERROR, args.param);
                }
                break;

            case ConnectionState.DISCONNECTED when holdConnection:
                await reconnectAsync(false);

                break;
            }
        }
Example #4
0
        //--------------------------------------------------------Set-, Get- Methods:---------------------------------------------------------\\
        #region --Set-, Get- Methods--
        protected override void setState(ConnectionState newState, object param)
        {
            base.setState(newState, param);
            switch (newState)
            {
            case ConnectionState.DISCONNECTED:
                onDisconnected();
                break;

            case ConnectionState.CONNECTED:
                // Reset last error message:
                lastConnectionError = null;
                break;
            }
        }
Example #5
0
        //--------------------------------------------------------Constructor:----------------------------------------------------------------\\
        #region --Constructors--
        /// <summary>
        /// Basic Constructor
        /// </summary>
        /// <history>
        /// 05/05/2018 Created [Fabian Sauter]
        /// </history>
        public XMPPConnection2(XMPPAccount account) : base(account)
        {
            this.holdConnection       = false;
            this.connectionErrorCount = 0;
            this.lastConnectionError  = null;
            this.TCP_CONNECTION       = new TCPConnection2(account);
            this.TCP_CONNECTION.ConnectionStateChanged += TCPConnection_ConnectionStateChanged;
            this.TCP_CONNECTION.NewDataReceived        += TCPConnection_NewDataReceived;

            this.PARSER             = new MessageParser2();
            this.MESSAGE_PROCESSORS = new AbstractMessageProcessor[4];
            this.streamId           = null;
            this.messageIdCache     = new TSTimedList <string>();

            this.connectionTimer    = null;
            this.reconnectRequested = false;
            this.timeout            = TimeSpan.FromMilliseconds(CONNECTION_TIMEOUT);

            this.GENERAL_COMMAND_HELPER = new GeneralCommandHelper(this);
            this.MUC_COMMAND_HELPER     = new MUCCommandHelper(this);
            this.PUB_SUB_COMMAND_HELPER = new PubSubCommandHelper(this);
            this.OMEMO_COMMAND_HELPER   = new OmemoCommandHelper(this);

            // The order in which new messages should get processed (TLS -- SASL -- Stream Management -- Resource binding -- ...).
            // https://xmpp.org/extensions/xep-0170.html
            //-------------------------------------------------------------
            // TLS:
            this.MESSAGE_PROCESSORS[0] = new TLSConnection(TCP_CONNECTION, this);

            // SASL:
            this.MESSAGE_PROCESSORS[1] = new SASLConnection(TCP_CONNECTION, this);

            // XEP-0198 (Stream Management):
            this.MESSAGE_PROCESSORS[2] = new SMConnection(TCP_CONNECTION, this);

            // Resource binding:
            RecourceBindingConnection recourceBindingConnection = new RecourceBindingConnection(TCP_CONNECTION, this);

            recourceBindingConnection.ResourceBound += RecourceBindingConnection_ResourceBound;
            this.MESSAGE_PROCESSORS[3] = recourceBindingConnection;
            //-------------------------------------------------------------

            NetworkHelper.Instance.NetworkChanged += Instance_NetworkChanged;

            this.omemoHelper          = null;
            this.DISCO_FEATURE_HELPER = new DiscoFeatureHelper(this);
        }
Example #6
0
        /// <summary>
        /// Connects to the XMPP server.
        /// </summary>
        private async Task connectAsync()
        {
            if (!NetworkHelper.Instance.ConnectionInformation.IsInternetAvailable)
            {
                connectionErrorCount = 3;
                lastConnectionError  = new ConnectionError(ConnectionErrorCode.NO_INTERNET);
                setState(ConnectionState.ERROR, lastConnectionError);
                reconnectRequested = false;
                holdConnection     = false;
                Logger.Warn("[XMPPConnection2]: Unable to connect to " + account.serverAddress + " - no internet!");
                return;
            }

            switch (state)
            {
            case ConnectionState.DISCONNECTED:
            case ConnectionState.ERROR:
                if (connectionErrorCount < 3)
                {
                    setState(ConnectionState.CONNECTING);

                    // Reset stuff:
                    streamId       = null;
                    messageIdCache = new TSTimedList <string>();
                    resetMessageProcessors();

                    await TCP_CONNECTION.connectAsync();
                }
                break;

            default:
                Logger.Warn("[XMPPConnection2]: Trying to connect but state is not " + ConnectionState.DISCONNECTED + " or " + ConnectionState.ERROR + "! State = " + state);
                await reconnectAsync(false);

                break;
            }
        }
Example #7
0
        /// <summary>
        /// Parses the given messages and invokes the ConnectionNewValidMessage event for each message.
        /// </summary>
        /// <param name="data">The messages string to parse.</param>
        private async Task ParseMessageAsync(string data)
        {
            // Parse message:
            List <AbstractMessage> messages = null;

            try
            {
                messages = PARSER.parseMessages(ref data);
            }
            catch (Exception e)
            {
                Logger.Error("[XMPPConnection2]: Error during message parsing." + e);
                return;
            }

            // Process messages:
            foreach (AbstractMessage msg in messages)
            {
                // Stream error messages:
                if (msg is StreamErrorMessage errorMessage)
                {
                    Logger.Warn("[XMPPConnection2]: Received stream error message: " + errorMessage.ToString());
                    lastConnectionError = new ConnectionError(ConnectionErrorCode.SERVER_ERROR, errorMessage.ToString());
                    await OnConnectionErrorAsync();
                    await SendStreamCloseMessageAsync();

                    return;
                }

                // Filter IQ messages which ids are not valid:
                if (msg is IQMessage iq)
                {
                    if (iq.GetType().Equals(IQMessage.RESULT) && messageIdCache.GetTimed(iq.ID) != null)
                    {
                        Logger.Warn("[XMPPConnection2]: Invalid message id received!");
                        return;
                    }
                }

                // Respond to XEP-0199 (XMPP Ping) messages:
                if (msg is PingMessage pingMsg)
                {
                    Logger.Debug("[XMPPConnection2]: XMPP ping received from " + pingMsg.getFrom());
                    await SendAsync(pingMsg.generateResponse(), true);
                }

                // Invoke message processors:
                NewValidMessage?.Invoke(this, new NewValidMessageEventArgs(msg));

                // Should restart connection?
                if (msg.getRestartConnection() != AbstractMessage.NO_RESTART)
                {
                    if (msg.getRestartConnection() == AbstractMessage.SOFT_RESTART)
                    {
                        await SoftRestartAsync();
                    }
                    else if (msg.getRestartConnection() == AbstractMessage.HARD_RESTART)
                    {
                        await HardRestartAsync();
                    }
                    else
                    {
                        throw new ArgumentException("[XMPPConnection2]: Invalid restart type: " + msg.getRestartConnection());
                    }
                }

                // Filter already processed messages:
                if (msg.isProcessed())
                {
                    return;
                }

                // --------------------------------------------------------------------
                // Open stream:
                if (msg is OpenStreamAnswerMessage oA)
                {
                    if (oA.ID is null)
                    {
                        // TODO Handle OpenStreamAnswerMessage id is null
                        //Error throw exception?!
                        return;
                    }
                }
                // Close stream message:
                else if (msg is CloseStreamMessage)
                {
                    switch (state)
                    {
                    case ConnectionState.CONNECTING:
                    case ConnectionState.CONNECTED:
                        await InternalDisconnectAsync(false);

                        break;
                    }
                }
                // Rooster:
                else if (msg is RosterResultMessage)
                {
                    NewRoosterMessage?.Invoke(this, new NewValidMessageEventArgs(msg));
                }
                // Presence:
                else if (msg is PresenceMessage presenceMessage && !(presenceMessage.getFrom() is null))
                {
                    NewPresenceMessage?.Invoke(this, new NewValidMessageEventArgs(msg));
                }