/// <summary> /// Returns the most appropriate subclass of StreamElement for the given XML /// </summary> /// <param name="xml">XML representation of some stream element</param> /// <returns>A subclass of StreamElement or new instance of StreamElement of no subclass was an exact match.</returns> public static StreamElement GetStreamElement(XmlNode xml) { StreamElement e = null; switch(xml.Name) { case "stream:features": e = new StreamFeaturesElement(xml); break; case "auth": e = new AuthenticationElement(xml); break; case "success": e = new ResponseElement(xml, ResponseType.Success); break; case "failure": e = new ResponseElement(xml, ResponseType.Failure); break; case "stream:error": e = new ResponseElement(xml, ResponseType.StreamError); break; case "starttls": e = new ResponseElement(xml, ResponseType.StartTls); break; case "proceed": e = new ResponseElement(xml, ResponseType.ProceedTls); break; case "challenge": case "response": e = new SaslResponseElement(xml); break; default: e = new StreamElement(xml); break; } return e; }
private void receivedStreamEnd(int dataLength) { string chunk = newData.Substring(chunkStart, dataLength-chunkStart+1); if(oldData.Length > 0) { chunk = oldData + chunk; oldData = ""; } docEnd = chunk; doc.LoadXml(docBegin+docEnd); // Hack to work with .NET's phobia of open tags in XmlDocuments StreamElement endElement = new StreamElement(doc.DocumentElement); chunkStart = dataLength + 1; if(OnStreamEnd != null) OnStreamEnd(this, endElement); }
/// <summary> /// Called when a new stream element is parsed from the stream. /// </summary> /// <param name="e">Element parsed from stream</param> private void onNewStreamElement(StreamElement e) { if(e is ResponseElement) { ResponseElement responseE = (ResponseElement)e; switch(responseE.Type) { case ResponseType.Success: if(state == SessionState.StartingSasl) { // Restart stream in the online state streamParser.Reset(); openStream(domain, "1.0"); setState(SessionState.StartingSession); } break; case ResponseType.Failure: if(state == SessionState.StartingSasl) { setState(SessionState.Connected); // Unblock so client can deal with the login failure. blockingOpenEvent.Set(); } break; case ResponseType.StreamError: if(OnError != null) OnError(this, responseE.ToString()); break; case ResponseType.SaslChallenge: SaslResponseElement saslChallengeE = (SaslResponseElement)responseE; if(saslChallengeE.Data["rspauth"] != null) { SaslResponseElement response = StreamElementFactory.GetSaslResponseElement(); send(response); } else { SaslResponseElement response = StreamElementFactory.GetSaslResponseElement(username, password, saslChallengeE.Data["realm"] as string, saslChallengeE.Data["nonce"] as string, saslChallengeE.Data["qop"] as string); send(response); } break; case ResponseType.ProceedTls: streamParser.Reset(); try { tcpClient.Stream.Flush(); tcpClient.IsSecure = true; } catch(IOException err) { if(OnError != null) OnError(this, err); closeTcpClient(); } catch (Exception err) { if(OnError != null) OnError(this, err); Close(); } break; } } else if (e is StreamFeaturesElement) { StreamFeaturesElement featuresE = (StreamFeaturesElement)e; switch(featuresE.Type) { case StreamFeaturesType.SaslMechanisms: if(state == SessionState.Connected) { setState(SessionState.StartingSasl); AuthenticationElement response = StreamElementFactory.GetAuthenticationElement(featuresE.BestSaslAuthMech, this.domain, this.username, this.password); send(response); } break; case StreamFeaturesType.StartTls: if(state == SessionState.Connected) { setState(SessionState.StartingTls); ResponseElement startTls = StreamElementFactory.GetStartTlsElement(); send(startTls); } break; case StreamFeaturesType.Bind: if(state == SessionState.StartingSession) { IQStanza bindStanza = StanzaFactory.GetRequestResourceBindStanza(resource); send(bindStanza); } break; case StreamFeaturesType.Session: startSession(this.JabberID); break; } } }