/// <summary> /// Creates a Web-socket session. /// </summary> public override async void CreateSession() { try { lock (this.queue) { this.terminated = false; this.writing = false; this.closeSent = false; this.queue.Clear(); this.webSocketClient?.Dispose(); this.webSocketClient = null; this.webSocketClient = new ClientWebSocket(); this.webSocketClient.Options.KeepAliveInterval = TimeSpan.FromSeconds(30); } await this.webSocketClient.ConnectAsync(this.url, CancellationToken.None); // TODO: this.xmppClient.TrustServer if (this.xmppClient.HasSniffers) { this.xmppClient.Information("Initiating session."); } await this.SendAsync("<?"); string XmlResponse = await this.ReadText(); XmlDocument ResponseXml = new XmlDocument() { PreserveWhitespace = true }; ResponseXml.LoadXml(XmlResponse); XmlElement Open; if ((Open = ResponseXml.DocumentElement) is null || Open.LocalName != "open" || Open.NamespaceURI != FramingNamespace) { throw new Exception("Unexpected response returned."); } string StreamPrefix = "stream"; LinkedList <KeyValuePair <string, string> > Namespaces = null; this.to = null; this.from = null; this.version = 0; this.language = null; foreach (XmlAttribute Attr in Open.Attributes) { switch (Attr.Name) { case "version": if (!CommonTypes.TryParse(Attr.Value, out this.version)) { throw new Exception("Invalid version number."); } break; case "to": this.to = Attr.Value; break; case "from": this.from = Attr.Value; break; case "xml:lang": this.language = Attr.Value; break; default: if (Attr.Prefix == "xmlns") { if (Attr.Value == XmppClient.NamespaceStream) { StreamPrefix = Attr.LocalName; } else { if (Namespaces is null) { Namespaces = new LinkedList <KeyValuePair <string, string> >(); } Namespaces.AddLast(new KeyValuePair <string, string>(Attr.Prefix, Attr.Value)); } } break; } } StringBuilder sb = new StringBuilder(); sb.Append('<'); sb.Append(StreamPrefix); sb.Append(":stream xmlns:"); sb.Append(StreamPrefix); sb.Append("='"); sb.Append(XmppClient.NamespaceStream); if (!(this.to is null)) { sb.Append("' to='"); sb.Append(XML.Encode(this.to)); } if (!(this.from is null)) { sb.Append("' from='"); sb.Append(XML.Encode(this.from)); } if (this.version > 0) { sb.Append("' version='"); sb.Append(CommonTypes.Encode(this.version)); } if (!(this.language is null)) { sb.Append("' xml:lang='"); sb.Append(XML.Encode(this.language)); } sb.Append("' xmlns='"); sb.Append(XmppClient.NamespaceClient); if (!(Namespaces is null)) { foreach (KeyValuePair <string, string> P in Namespaces) { sb.Append("' xmlns:"); sb.Append(P.Key); sb.Append("='"); sb.Append(XML.Encode(P.Value)); } } sb.Append("'>"); this.bindingInterface.StreamHeader = sb.ToString(); sb.Clear(); sb.Append("</"); sb.Append(StreamPrefix); sb.Append(":stream>"); this.bindingInterface.StreamFooter = sb.ToString(); this.StartReading(); } catch (Exception ex) { await this.bindingInterface.ConnectionError(ex); } }
private Task <bool> BodyReceived(string Xml, bool First) { string Body; int i, j; i = Xml.IndexOf("<body"); if (i >= 0) { i = Xml.IndexOf('>', i + 5); if (i > 0) { Body = Xml.Substring(0, i + 1); if (Xml[i - 1] == '/') { Xml = null; } else { Body += "</body>"; j = Xml.LastIndexOf("</body"); if (i < 0) { Xml = Xml.Substring(i + 1); } else { Xml = Xml.Substring(i + 1, j - i - 1).Trim(); } } bool Terminate = false; string Condition = null; string To = null; string From = null; string Version = null; string Language = null; string StreamPrefix = "stream"; XmlDocument BodyDoc = new XmlDocument(); LinkedList <KeyValuePair <string, string> > Namespaces = null; BodyDoc.LoadXml(Body); foreach (XmlAttribute Attr in BodyDoc.DocumentElement.Attributes) { switch (Attr.Name) { case "type": if (Attr.Value == "terminate") { Terminate = true; } break; case "condition": Condition = Attr.Value; break; case "xml:lang": Language = Attr.Value; break; default: if (Attr.Prefix == "xmlns") { if (Attr.Value == XmppClient.NamespaceStream) { StreamPrefix = Attr.LocalName; } else { if (Namespaces is null) { Namespaces = new LinkedList <KeyValuePair <string, string> >(); } Namespaces.AddLast(new KeyValuePair <string, string>(Attr.Prefix, Attr.Value)); } } else if (Attr.LocalName == "version" && Attr.NamespaceURI == BoshNamespace) { Version = Attr.Value; } break; } } if (Terminate) { this.terminated = true; lock (this.httpClients) { this.outputQueue.Clear(); } throw new Exception("Session terminated. Condition: " + Condition); } if (First) { StringBuilder sb = new StringBuilder(); sb.Append('<'); sb.Append(StreamPrefix); sb.Append(":stream xmlns:"); sb.Append(StreamPrefix); sb.Append("='"); sb.Append(XmppClient.NamespaceStream); if (To != null) { sb.Append("' to='"); sb.Append(XML.Encode(To)); } if (From != null) { sb.Append("' from='"); sb.Append(XML.Encode(From)); } if (Version != null) { sb.Append("' version='"); sb.Append(XML.Encode(Version)); } if (Language != null) { sb.Append("' xml:lang='"); sb.Append(XML.Encode(Language)); } sb.Append("' xmlns='"); sb.Append(XmppClient.NamespaceClient); if (Namespaces != null) { foreach (KeyValuePair <string, string> P in Namespaces) { sb.Append("' xmlns:"); sb.Append(P.Key); sb.Append("='"); sb.Append(XML.Encode(P.Value)); } } sb.Append("'>"); this.bindingInterface.StreamHeader = sb.ToString(); sb.Clear(); sb.Append("</"); sb.Append(StreamPrefix); sb.Append(":stream>"); this.bindingInterface.StreamFooter = sb.ToString(); } } } if (Xml != null) { return(this.RaiseOnReceived(Xml)); } else { return(Task.FromResult <bool>(true)); } }