public async Task <StanzaResult> OnStanzaReceivedAsync(Stanza stanza) { if (stanza.Element.Name == Xmlns.Streams.Stream) { if (State.HasDocumentTag) { return(new StanzaResult(StreamAction.Close, Stanza.FromFullElement( new XElement(Xmlns.Streams.Error, new XElement(Xmlns.Client.Namespace + "bad-format"))))); } else { State.HasDocumentTag = true; var element = new XElement(Xmlns.Streams.Stream, new XAttribute(XNamespace.Xmlns + "stream", Xmlns.Streams.Stream.NamespaceName), new XAttribute("xmlns", Xmlns.Client.Namespace.NamespaceName), new XAttribute(Xmlns.Attr.Version, "1.0")); var features = new XElement(Xmlns.Streams.Features); element.Add(features); foreach (var feat in State.Features.Values) { var actor = ActorProxy.Create <IStreamFeature>(feat, Constants.ApplicationName); element.Add(await actor.CreateDescriptiveElementAsync()); } return(new StanzaResult(Stanza.FromOpeningTag(element))); } } else { return(null); } }
/// <summary> /// Accepts the connection. /// </summary> public async void Open() { using (_socket) { Write(); try { _client = ActorProxy.Create <IXmlConnection>(ActorId.NewId(), Constants.ApplicationName, Constants.ActorNames.UnboundClient); await _client.SubscribeAsync(this); } catch (Exception e) { ServiceEventSource.Current.ClientConnectionFailure(_socket.Identifier, e.ToString()); return; } while (!_cancellationToken.IsCancellationRequested) { try { await CreateXmlAsync(); var element = await ReadStartElementAsync(_cancellationToken); var stanza = Stanza.FromOpeningTag(element); while (!_cancellationToken.IsCancellationRequested) { var result = await _client.OnStanzaReceivedAsync(stanza); // Remove stanza elements from the document once we are // done with them. if (!stanza.OpeningTagOnly) { stanza.Element.Remove(); } if (result != null) { if (result.Response != null) { await WriteStanzaAsync(result.Response); } switch (result.StreamAction) { case StreamAction.Close: await CloseAsync(); return; case StreamAction.Abort: return; case StreamAction.StartTls: await StartTlsAsync(); break; } if ((int)result.StreamAction >= (int)StreamAction.Reset) { break; } } element = await ReadFullElementAsync(_cancellationToken); stanza = Stanza.FromFullElement(element); } } catch (Exception e) { var result = await _client.OnErrorOccurredAsync(e); if (result != null && result.Response != null) { await WriteStanzaAsync(result.Response); } // Errors at this level always terminate the connection. return; } } } }