//--------------------------------------------------------Constructor:----------------------------------------------------------------\\ #region --Constructors-- /// <summary> /// Basic Constructor /// </summary> /// <history> /// 29/01/2017 Created [Fabian Sauter] /// </history> public OpenStreamAnswerMessage(XmlNode streamNode) : base(streamNode.Attributes["id"]?.Value) { this.STREAM_NODE = streamNode; this.FROM = STREAM_NODE.Attributes["from"]?.Value; this.TO = STREAM_NODE.Attributes.GetNamedItem("to")?.Value; this.STREAM_FEATURES = getStreamFeaturesMessage(streamNode); }
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 = null; if (msg is OpenStreamAnswerMessage) { features = (msg as OpenStreamAnswerMessage).getStreamFeaturesMessage(); } else { features = msg as StreamFeaturesMessage; } if (features == null) { return; } if (features.containsFeature("bind")) { setMessageProcessed(args); BindResourceMessage bindMsg = new BindResourceMessage(XMPP_CONNECTION.account.user.resource); id = bindMsg.ID; await XMPP_CONNECTION.sendAsync(bindMsg, false, 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(), false, true).Wait(); state = RecourceBindingState.BOUND; ResourceBound?.Invoke(this, new EventArgs()); } } break; } }
//--------------------------------------------------------Set-, Get- Methods:---------------------------------------------------------\\ #region --Set-, Get- Methods-- private ArrayList getMechanisms(StreamFeaturesMessage msg) { foreach (StreamFeature sF in msg.getFeatures()) { if (sF is SASLStreamFeature) { return((sF as SASLStreamFeature).MECHANISMS); } } return(null); }
public TLSStreamFeature getTLSStreamFeature(StreamFeaturesMessage msg) { foreach (StreamFeature f in msg.getFeatures()) { if (f is TLSStreamFeature) { return(f as TLSStreamFeature); } } return(null); }
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(), false, 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); return; } } }
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); } }
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; } }