private void OnNewRoosterMessage(IMessageSender sender, NewValidMessageEventArgs args) { if (args.MESSAGE is RosterResultMessage msg && sender is XMPPClient xmppClient) { string type = msg.TYPE; if (!string.Equals(type, IQMessage.RESULT) && !string.Equals(type, IQMessage.SET)) { // No roster result or set => return return; } SemaLock semaLock = DataCache.INSTANCE.NewChatSemaLock(); IEnumerable <ChatModel> chats = DataCache.INSTANCE.GetChats(client.dbAccount.bareJid, semaLock); // TYPE == SET is being send by the server when the roster changes from outside: if (string.Equals(type, IQMessage.RESULT)) { foreach (ChatModel chat in chats) { chat.inRoster = false; } } List <ChatModel> addedChats = new List <ChatModel>(); List <ChatModel> updatedChats = new List <ChatModel>(); foreach (RosterItem item in msg.ITEMS) { ChatModel chat = chats.Where(c => string.Equals(c.bareJid, item.JID)).FirstOrDefault(); if (!(chat is null)) { chat.inRoster = !string.Equals(item.SUBSCRIPTION, "remove"); updatedChats.Add(chat); }
//--------------------------------------------------------Events:---------------------------------------------------------------------\\ #region --Events-- private async void OnNewValidMessage(IMessageSender sender, NewValidMessageEventArgs args) { if (args.MESSAGE is OmemoDeviceListEventMessage eventMsg) { await onOmemoDeviceListEventMessageAsync(eventMsg); } }
private async void OnNewValidMessage(IMessageSender sender, NewValidMessageEventArgs args) { if (args.MESSAGE is MUCErrorMessage) { await OnMucErrorMessageAsync((XMPPClient)sender, args.MESSAGE as MUCErrorMessage); } }
protected override async Task processMessageAsync(NewValidMessageEventArgs args) { if (!STREAM_MANAGEMENT_ENABLED) { return; } AbstractMessage msg = args.MESSAGE; switch (state) { case SMState.DISABLED: if (msg is StreamFeaturesMessage || msg is OpenStreamAnswerMessage) { StreamFeaturesMessage features = null; if (msg is OpenStreamAnswerMessage) { features = (msg as OpenStreamAnswerMessage).getStreamFeaturesMessage(); } else { features = msg as StreamFeaturesMessage; } if (features is null) { return; } if (features.containsFeature("sm")) { setMessageProcessed(args); SMEnableMessage enableMsg = new SMEnableMessage(); await XMPP_CONNECTION.sendAsync(enableMsg, true); serverSMEnabled = true; state = SMState.REQUESTED; } } break; case SMState.REQUESTED: if (msg is SMEnableMessage enableAnswMsg) { setMessageProcessed(args); // Update connection information: state = SMState.ENABLED; clientSMEnabled = true; stopListeningForMessages(); } else if (msg is SMFailedMessage failedMsg) { setMessageProcessed(args); // Handle errors: state = SMState.ERROR; stopListeningForMessages(); } break; } }
protected async override Task processMessageAsync(NewValidMessageEventArgs args) { AbstractMessage msg = args.MESSAGE; if (state == RecourceBindingState.BOUND || state == RecourceBindingState.ERROR || msg.isProcessed()) { return; } switch (state) { case RecourceBindingState.UNBOUND: if (msg is StreamFeaturesMessage || msg is OpenStreamAnswerMessage) { StreamFeaturesMessage features; if (msg is OpenStreamAnswerMessage) { features = (msg as OpenStreamAnswerMessage).getStreamFeaturesMessage(); } else { features = msg as StreamFeaturesMessage; } if (features is null) { return; } if (features.containsFeature("bind")) { setMessageProcessed(args); BindResourceMessage bindMsg = new BindResourceMessage(XMPP_CONNECTION.account.user.resourcePart); id = bindMsg.ID; await XMPP_CONNECTION.SendAsync(bindMsg, true); state = RecourceBindingState.BINDING; } } break; case RecourceBindingState.BINDING: if (msg is IQMessage) { IQMessage iQM = msg as IQMessage; if (string.Equals(iQM.ID, id)) { stopListeningForMessages(); setMessageProcessed(args); XMPP_CONNECTION.SendAsync(new StartSessionMessage(), true).Wait(); state = RecourceBindingState.BOUND; ResourceBound?.Invoke(this, new EventArgs()); } } break; } }
private void Connection_ConnectionNewValidMessage(IMessageSender connection, NewValidMessageEventArgs args) { AbstractMessage msg = args.MESSAGE; if (msg is MessageMessage mMsg) { NewChatMessage?.Invoke(this, new NewChatMessageEventArgs(mMsg)); } else if (msg is ChatStateMessage sMsg) { NewChatState?.Invoke(this, new NewChatStateEventArgs(sMsg)); } else if (msg is DeliveryReceiptMessage dRMsg) { NewDeliveryReceipt?.Invoke(this, new NewDeliveryReceiptEventArgs(dRMsg)); } NewValidMessage?.Invoke(this, args); }
protected async override Task processMessageAsync(NewValidMessageEventArgs args) { AbstractMessage msg = args.MESSAGE; if (msg.isProcessed()) { return; } switch (state) { case SASLState.DISCONNECTED: if (msg is StreamFeaturesMessage || msg is OpenStreamAnswerMessage) { StreamFeaturesMessage features = null; if (msg is OpenStreamAnswerMessage) { features = (msg as OpenStreamAnswerMessage).getStreamFeaturesMessage(); } else { features = msg as StreamFeaturesMessage; } if (features is null) { return; } ArrayList mechanisms = getMechanisms(features); if (mechanisms is null) { return; } setMessageProcessed(args); selectMechanism(mechanisms); if (selectedMechanism is null) { state = SASLState.ERROR; await XMPP_CONNECTION.OnMessageProcessorFailedAsync(new ConnectionError(ConnectionErrorCode.SASL_FAILED, "selectedMechanism is null"), true); return; } await XMPP_CONNECTION.SendAsync(selectedMechanism.getSelectSASLMechanismMessage(), true); state = SASLState.REQUESTED; } break; case SASLState.REQUESTED: case SASLState.CHALLENGING: if (msg is ScramSHAChallengeMessage) { state = SASLState.CHALLENGING; setMessageProcessed(args); AbstractMessage response = selectedMechanism.generateResponse(msg); if (!(response is null)) { await XMPP_CONNECTION.SendAsync(response, true); } } else if (msg is SASLSuccessMessage) { state = SASLState.CONNECTED; msg.setRestartConnection(AbstractMessage.SOFT_RESTART); setMessageProcessed(args); stopListeningForMessages(); } else if (msg is SASLFailureMessage) { stopListeningForMessages(); SASLFailureMessage saslFailureMessage = msg as SASLFailureMessage; state = SASLState.ERROR; Logger.Error("Error during SASL authentication: " + saslFailureMessage.ERROR_TYPE + "\n" + saslFailureMessage.ERROR_MESSAGE); if (saslFailureMessage.ERROR_TYPE == SASLErrorType.UNKNOWN_ERROR) { await XMPP_CONNECTION.OnMessageProcessorFailedAsync(new ConnectionError(ConnectionErrorCode.SASL_FAILED, "SASL: " + saslFailureMessage.ERROR_MESSAGE), true); } else { await XMPP_CONNECTION.OnMessageProcessorFailedAsync(new ConnectionError(ConnectionErrorCode.SASL_FAILED, "SASL: " + saslFailureMessage.ERROR_TYPE), true); } } break; case SASLState.CONNECTED: break; default: throw new InvalidOperationException("Unexpected value for state: " + state); } }
private void C_NewRoosterMessage(IMessageSender sender, NewValidMessageEventArgs args) { if (args.MESSAGE is RosterResultMessage msg && sender is XMPPClient client) { string to = client.getXMPPAccount().getBareJid(); string type = msg.TYPE; if (string.Equals(type, IQMessage.RESULT)) { ChatDBManager.INSTANCE.setAllNotInRoster(client.getXMPPAccount().getBareJid()); } else if (!string.Equals(type, IQMessage.SET)) { // No roster result or set => return return; } foreach (RosterItem item in msg.ITEMS) { string from = item.JID; string id = ChatTable.generateId(from, to); ChatTable chat = ChatDBManager.INSTANCE.getChat(id); if (chat != null) { chat.inRoster = !string.Equals(item.SUBSCRIPTION, "remove"); } else if (!string.Equals(item.SUBSCRIPTION, "remove")) { chat = new ChatTable(from, to) { inRoster = true, chatType = ChatType.CHAT }; } else { continue; } // Only update the subscription state, if not set to subscribe: if (!string.Equals(chat.subscription, "subscribe")) { chat.subscription = item.SUBSCRIPTION; } chat.subscriptionRequested = string.Equals(item.ASK, "subscribe"); switch (chat.subscription) { case "unsubscribe": case "from": case "none": case "pending": case null: chat.presence = Presence.Unavailable; break; default: break; } ChatDBManager.INSTANCE.setChat(chat, false, true); } } }
protected async override Task processMessageAsync(NewValidMessageEventArgs args) { AbstractMessage msg = args.MESSAGE; if (msg.isProcessed()) { return; } if ((state == TLSState.CONNECTING || state == TLSState.REQUESTED) && msg is ErrorMessage) { setMessageProcessed(args); setState(TLSState.ERROR); ErrorMessage error = msg as ErrorMessage; if (error.getType().Equals(Consts.XML_FAILURE)) { error.setRestartConnection(AbstractMessage.HARD_RESTART); } return; } switch (state) { case TLSState.DISCONNECTED: case TLSState.CONNECTING: if (msg is OpenStreamAnswerMessage) { StreamFeaturesMessage features = (msg as OpenStreamAnswerMessage).getStreamFeaturesMessage(); if (features != null) { await streamFeaturesMessageReceivedAsync(features, args); } } else if (msg is StreamFeaturesMessage) { await streamFeaturesMessageReceivedAsync(msg as StreamFeaturesMessage, args); } break; case TLSState.REQUESTED: if (msg is ProceedAnswerMessage) { setMessageProcessed(args); XMPPAccount account = XMPP_CONNECTION.account; Logger.Debug("Upgrading " + account.getBareJid() + " connection to TLS..."); try { TCP_CONNECTION.upgradeToTLSAsync().Wait(); } catch (AggregateException e) { if (e.InnerException is TaskCanceledException) { Logger.Error("Timeout during upgrading " + account.getBareJid() + " to TLS!", e); setState(TLSState.ERROR); await XMPP_CONNECTION.onMessageProcessorFailedAsync(new ConnectionError(ConnectionErrorCode.TLS_CONNECTION_FAILED, "TSL upgrading timeout!"), true); return; } else { Logger.Error("Error during upgrading " + account.getBareJid() + " to TLS!", e.InnerException); setState(TLSState.ERROR); await XMPP_CONNECTION.onMessageProcessorFailedAsync(new ConnectionError(ConnectionErrorCode.TLS_CONNECTION_FAILED, e.InnerException?.Message), true); return; } } catch (Exception e) { Logger.Error("Error during upgrading " + account.getBareJid() + " to TLS!", e); setState(TLSState.ERROR); await XMPP_CONNECTION.onMessageProcessorFailedAsync(new ConnectionError(ConnectionErrorCode.TLS_CONNECTION_FAILED, e.Message), true); return; } Logger.Debug("Success upgrading " + account.getBareJid() + " to TLS."); setState(TLSState.CONNECTED); stopListeningForMessages(); // TLS established ==> resend stream header msg.setRestartConnection(AbstractMessage.SOFT_RESTART); } break; } }
private void C_NewRoosterMessage(IMessageSender sender, NewValidMessageEventArgs args) { XMPPClient client = sender as XMPPClient; if (args.MESSAGE is RosterMessage) { RosterMessage msg = args.MESSAGE as RosterMessage; string to = client.getXMPPAccount().getIdAndDomain(); string type = msg.TYPE; if (string.Equals(type, IQMessage.RESULT)) { ChatDBManager.INSTANCE.setAllNotInRoster(client.getXMPPAccount().getIdAndDomain()); } else if (type == null || !string.Equals(type, IQMessage.SET)) { // No roster result or set => return return; } foreach (RosterItem item in msg.ITEMS) { string from = item.JID; string id = ChatTable.generateId(from, to); ChatTable chat = ChatDBManager.INSTANCE.getChat(id); if (chat != null) { chat.subscription = item.SUBSCRIPTION; chat.inRoster = !item.SUBSCRIPTION.Equals("remove"); chat.ask = item.ASK; } else if (!Equals(item.SUBSCRIPTION, "remove")) { chat = new ChatTable() { id = id, chatJabberId = from, userAccountId = to, subscription = item.SUBSCRIPTION, lastActive = DateTime.Now, muted = false, inRoster = true, ask = item.ASK, chatType = ChatType.CHAT }; } else { continue; } switch (chat.subscription) { case "unsubscribe": case "from": case "none": case "pending": case null: chat.presence = Presence.Unavailable; break; default: break; } ChatDBManager.INSTANCE.setChat(chat, false, true); } } }
protected abstract Task processMessageAsync(NewValidMessageEventArgs args);
//--------------------------------------------------------Events:---------------------------------------------------------------------\\ #region --Events-- private async void XMPP_CONNECTION_ConnectionNewValidMessage(IMessageSender sender, NewValidMessageEventArgs args) { await processMessageAsync(args); }
protected void setMessageProcessed(NewValidMessageEventArgs args) { setMessageProcessed(args, true); }
//--------------------------------------------------------Set-, Get- Methods:---------------------------------------------------------\\ #region --Set-, Get- Methods-- protected void setMessageProcessed(NewValidMessageEventArgs args, bool cancelEvent) { args.MESSAGE.setProcessed(); args.Cancel = cancelEvent; }
private async Task streamFeaturesMessageReceivedAsync(StreamFeaturesMessage features, NewValidMessageEventArgs args) { TLSStreamFeature tlsFeature = getTLSStreamFeature(features); TLSConnectionMode connectionMode = TCP_CONNECTION.account.connectionConfiguration.tlsMode; if (tlsFeature != null) { if (connectionMode == TLSConnectionMode.PROHIBIT) { if (tlsFeature.REQUIRED) { stopListeningForMessages(); string errorMsg = "TSL is required for server but TLS connection mode is set to prohibit!"; Logger.Error(errorMsg); setState(TLSState.ERROR); await XMPP_CONNECTION.onMessageProcessorFailedAsync(new ConnectionError(ConnectionErrorCode.TLS_CONNECTION_FAILED, errorMsg), true); } else { setState(TLSState.PROHIBITED); } return; } // Starting the TSL process: setMessageProcessed(args); setState(TLSState.CONNECTING); await XMPP_CONNECTION.sendAsync(new RequesStartTLSMessage(), true); setState(TLSState.REQUESTED); } else { if (connectionMode == TLSConnectionMode.FORCE) { stopListeningForMessages(); string errorMsg = "TSL is not available for this server but TLS connection mode is set to force!"; Logger.Error(errorMsg); setState(TLSState.ERROR); await XMPP_CONNECTION.onMessageProcessorFailedAsync(new ConnectionError(ConnectionErrorCode.TLS_CONNECTION_FAILED, errorMsg), true); } } }
private void Connection_ConnectionNewPresenceMessage(IMessageSender connection, NewValidMessageEventArgs args) { // XEP-0045 (MUC member presence): if (args.MESSAGE is MUCMemberPresenceMessage mucPresence) { NewMUCMemberPresenceMessage?.Invoke(this, new NewMUCMemberPresenceMessageEventArgs(mucPresence)); } else if (args.MESSAGE is MUCPresenceErrorMessage mucPresenceError) { NewMUCPresenceErrorMessage?.Invoke(this, new NewMUCPresenceErrorMessageEventArgs(mucPresenceError)); } else { NewPresence?.Invoke(this, new NewPresenceMessageEventArgs(args.MESSAGE as PresenceMessage)); } }
//--------------------------------------------------------Events:---------------------------------------------------------------------\\ #region --Events-- private void Connection_ConnectionNewRoosterMessage(IMessageSender sender, NewValidMessageEventArgs args) { NewRoosterMessage?.Invoke(this, args); }