private void doAuthenticate() { doChangeState(XmppEngineState.Opening); if (tcpClient != null) { tcpClient.Dispose(); tcpClient = null; } try { tcpClient = new XmppTcpSocket(HostName, HostPort); } catch (Exception ex) { if (Error != null) { Error(this, new XmppErrorEventArgs(XmppErrorType.SocketError, string.Empty, ex.GetType().ToString() + ": " + ex.Message)); } if (tcpClient != null) { tcpClient.Dispose(); tcpClient = null; } return; } string stream; XmppIQ xStream; // ========================================================================== // === START TLS LAYER ====================================================== stream = doRequestFeatures(); if (stream.Contains("<starttls")) { sendStream("<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>"); stream = recvStream(); if (stream.Contains("<proceed")) { bool sslStarted = false; string message = string.Empty; try { sslStarted = tcpClient.StartSSL(); sslStarted = true; } catch (Exception ex) { sslStarted = false; message = string.Format("{0}: {1}", ex.GetType(), ex.Message); } if (!sslStarted) { if (Error != null) { Error(this, new XmppErrorEventArgs(XmppErrorType.SocketStartSSLError, string.Empty, message)); } return; } stream = doRequestFeatures(); } } if (stream.Contains("<mechanism>DIGEST-MD5</mechanism>")) { // ========================================================================== // === SASL DIGEST-MD5 AUTHENTICATION PROCESS =============================== DigestMD5MechanismProvider mech = new DigestMD5MechanismProvider(UserName, UserPassword); sendStream(mech.GetAuthStream()); stream = recvStream(); xStream = XmppIQ.Parse(stream); if (!xStream.Equal("challenge", "urn:ietf:params:xml:ns:xmpp-sasl")) { if (Error != null) { string tag, message; XmppError.Parse(XmppIQ.Parse(stream), out tag, out message); Error(this, new XmppErrorEventArgs(XmppErrorType.AuthUserNotAuthorized, tag, message)); } return; } sendStream(mech.GetChallengeResponse(xStream.Text)); stream = recvStream(); xStream = XmppIQ.Parse(stream); if (!xStream.Equal("challenge", "urn:ietf:params:xml:ns:xmpp-sasl")) { if (Error != null) { string tag, message; XmppError.Parse(XmppIQ.Parse(stream), out tag, out message); Error(this, new XmppErrorEventArgs(XmppErrorType.AuthUserNotAuthorized, tag, message)); } return; } sendStream("<response xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\"/>"); } else if (stream.Contains("<mechanism>PLAIN</mechanism>")) { // ========================================================================== // === SASL PLAIN AUTHENTICATION PROCESS ==================================== PlainMechanismProvider mech = new PlainMechanismProvider(UserName, UserPassword); sendStream(mech.GetAuthStream()); } else if (stream.Contains("<mechanism>X-GOOGLE-TOKEN</mechanism>")) { // ========================================================================== // === SASL X-GOOGLE-TOKEN AUTHENTICATION PROCESS ==================================== XGoogleTokenMechanismProvider mech = new XGoogleTokenMechanismProvider(UserName, UserPassword, UserResource); sendStream(mech.GetAuthStream()); } else if (stream.Contains("<mechanism>X-MESSENGER-OAUTH2</mechanism>")) { // ========================================================================== // === SASL X-MESSENGER-OAUTH2 AUTHENTICATION PROCESS ==================================== XMessengerOAuth2MechanismProvider mech = new XMessengerOAuth2MechanismProvider(UserName, UserOAuthToken); sendStream(mech.GetAuthStream()); } else if (stream.Contains("<mechanism>X-FACEBOOK-PLATFORM</mechanism>")) { // ========================================================================== // === SASL X-FACEBOOK-PLATFORM AUTHENTICATION PROCESS ==================================== XFacebookPlatformMechanismProvider mech = new XFacebookPlatformMechanismProvider(UserName, UserOAuthToken); sendStream(mech.GetAuthStream()); stream = recvStream(); xStream = XmppIQ.Parse(stream); if (!xStream.Equal("challenge", "urn:ietf:params:xml:ns:xmpp-sasl")) { if (Error != null) { string tag, message; XmppError.Parse(XmppIQ.Parse(stream), out tag, out message); Error(this, new XmppErrorEventArgs(XmppErrorType.AuthUserNotAuthorized, tag, message)); } return; } sendStream(mech.GetChallengeResponse(xStream.Text)); } else { if (Error != null) { Error(this, new XmppErrorEventArgs(XmppErrorType.AuthModeNotSupported)); } return; } stream = recvStream(); if (stream.Contains("<failure")) { if (Error != null) { string tag, message; XmppError.Parse(XmppIQ.Parse(stream), out tag, out message); Error(this, new XmppErrorEventArgs(XmppErrorType.AuthUserNotAuthorized, tag, message)); } return; } // ========================================================================== // === BIND RESOURCE ======================================================== stream = doRequestFeatures(); SendIq(Jid, null, XmppIqType.Set, "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\"><resource>" + UserResource + "</resource></bind>"); stream = recvStream(); xStream = new XmppIQ(stream); XmppIQ xJid = xStream.FindDescendant("jid", "urn:ietf:params:xml:ns:xmpp-bind"); if (xJid != null) { Jid = new XmppJid(xJid.Text); } // ========================================================================== // === START SESSION ======================================================== SendIq(Jid, null, XmppIqType.Set, "<session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/>"); stream = recvStream(); // ========================================================================== // === OK: AUTHENTICATED IN JABBER NETWORK, You rocks! ====================== //tcpClient.SetReadTimeout(0); doChangeState(XmppEngineState.Open); if (UserConnected != null) { UserConnected(this, new XmppEventArgs(Jid.Value)); } }
private string recvStream() { if (tcpClient == null) { if (Error != null) { Error(this, new XmppErrorEventArgs(XmppErrorType.ClientNotConnected, string.Empty, string.Empty)); } return(string.Empty); } int iteration = 0; StringBuilder buf = new StringBuilder(); while (true) { string internalBuf = tcpClient.ReadStream(); if (string.IsNullOrWhiteSpace(internalBuf)) { break; } if (internalBuf.Contains("<stream:error")) { if (RecvStreamCallback != null) { RecvStreamCallback(this, new XmppEventArgs(buf.Append(internalBuf).ToString())); } if (Error != null) { string tag, message; XmppError.Parse(XmppIQ.Parse(internalBuf), out tag, out message); Error(this, new XmppErrorEventArgs(XmppErrorType.XmppStreamError, tag, message)); } Disconnect(); break; } else if (internalBuf.Contains("</stream:stream>")) { if (RecvStreamCallback != null) { RecvStreamCallback(this, new XmppEventArgs(buf.Append(internalBuf).ToString())); } if (Error != null) { Error(this, new XmppErrorEventArgs(XmppErrorType.ConnectionClosedByServer, string.Empty, string.Empty)); } Disconnect(); break; } buf.Append(internalBuf); if (state == XmppEngineState.Open) { if (XmppStream.IsValid(buf.ToString())) { break; } } else { break; } iteration++; if (iteration > 100) { if (Error != null) { Error(this, new XmppErrorEventArgs(XmppErrorType.RecvTooManyInvalidStream, string.Empty, "")); } Disconnect(); return(string.Empty); } } if (RecvStreamCallback != null) { RecvStreamCallback(this, new XmppEventArgs(buf.ToString())); } // flush string buffer string stringBuffer = buf.ToString(); buf.EnsureCapacity(0); // it's ok, return a valid stream return(stringBuffer); }
private void doParseStream(string stream) { XmppIQ xStream; try { xStream = XmppIQ.Parse(stream); } catch (Exception) { //MessageBox.Show("Invalid stream :(\n\n" + stream); return; } switch (xStream.Name) { #region PRESENCE case "presence": { XmppPresence presence = new XmppPresence(); string type = xStream.GetAttribute("type"); presence.From = new XmppJid(xStream.GetAttribute("from")); presence.To = new XmppJid(xStream.GetAttribute("to")); // # type == "" if (string.IsNullOrEmpty(type)) { XmppIQ xStatus = xStream.FindDescendant("status"); if (xStatus != null) { presence.MessageStatus = xStatus.Text; } XmppIQ xShow = xStream.FindDescendant("show"); presence.Status = xShow != null?XmppIq.StrToPresence(xShow.Text) : XmppPresenceStatus.Online; XmppIQ xCard = xStream.FindDescendant("x", "vcard-temp:x:update"); if (xCard != null) { XmppIQ xPhoto = xCard.FindDescendant("photo", "vcard-temp:x:update"); if (xPhoto != null) { presence.PhotoHash = xPhoto.Text; } } if (Presence != null) { Presence(this, new XmppPresenceEventArgs(presence)); } } // # type == "unavailable" else if (type == "unavailable") { presence.Status = XmppPresenceStatus.Unavailable; if (Presence != null) { Presence(this, new XmppPresenceEventArgs(presence)); } } // # type == "probe" // probe request from server else if (type == "probe") { SetPresence(statePresence, string.Empty, null); } // # type == "subscribe" // new subscription request else if (type == "subscribe") { if (SubscribeRequest != null) { SubscribeRequest(this, new XmppSubscribeRequestEventArgs(presence.From)); } } // # type == "error" // presence stanza error else if (type == "error") { // @@@ } } break; #endregion #region MESSAGE case "message": { XmppMessage message = new XmppMessage(); message.Type = xStream.GetAttribute("type"); message.From = new XmppJid(xStream.GetAttribute("from")); message.To = new XmppJid(xStream.GetAttribute("to")); Int32.TryParse(xStream.GetAttribute("id"), out message.ID); if (message.Type != "error") { // # user composing new message if (xStream.FindDescendant("composing", "http://jabber.org/protocol/chatstates") != null) { if (ChatNotify != null) { ChatNotify(this, new XmppChatNotifyEventArgs(message.From, string.Empty, XmppChatStatus.NowComposing)); } } // # user stop composing else if (xStream.FindDescendant("paused", "http://jabber.org/protocol/chatstates") != null) { if (ChatNotify != null) { ChatNotify(this, new XmppChatNotifyEventArgs(message.From, string.Empty, XmppChatStatus.StopComposing)); } } // # user is inactive else if (xStream.FindDescendant("inactive", "http://jabber.org/protocol/chatstates") != null) { if (ChatNotify != null) { ChatNotify(this, new XmppChatNotifyEventArgs(message.From, string.Empty, XmppChatStatus.Inactive)); } } // # user has left conversation else if (xStream.FindDescendant("gone", "http://jabber.org/protocol/chatstates") != null) { if (ChatNotify != null) { ChatNotify(this, new XmppChatNotifyEventArgs(message.From, string.Empty, XmppChatStatus.Gone)); } } // # user is active ;) else if (xStream.FindDescendant("active", "http://jabber.org/protocol/chatstates") != null) { if (ChatNotify != null) { ChatNotify(this, new XmppChatNotifyEventArgs(message.From, string.Empty, XmppChatStatus.Active)); } } // # check for new message XmppIQ xBody = xStream.FindDescendant("body"); if (xBody != null) { message.Body = xBody.Text; XmppIQ xThread = xStream.FindDescendant("thread"); if (xThread != null) { message.Thread = xThread.Text; } XmppIQ xSubject = xStream.FindDescendant("subject"); if (xSubject != null) { message.Subject = xSubject.Text; } if (Message != null) { Message(this, new XmppMessageEventArgs(message)); } } } } break; #endregion #region IQ case "iq": { XmppIQ xQuery = null; string type = xStream.GetAttribute("type"); // Roster xQuery = xStream.FindDescendant("query", "jabber:iq:roster"); if (xQuery != null) { List <XmppRosterItem> roster = new List <XmppRosterItem>(); foreach (XmppIQ xItem in xQuery.Children()) { if (xItem.Name != "item") { continue; } string jid = xItem.GetAttribute("jid"); string sub = xItem.GetAttribute("subscription"); string ask = xItem.GetAttribute("ask"); string name = xItem.GetAttribute("name"); string group = xItem.GetAttribute("group"); roster.Add(new XmppRosterItem(jid, sub, name, group, ask)); } if (Roster != null) { Roster(this, new XmppRosterEventArgs(roster, XmppIq.StrToType(type))); } } // Disco xQuery = xStream.FindDescendant("query", "http://jabber.org/protocol/disco#info"); if (xQuery != null) { if (type == "get") { XmppJid from = new XmppJid(xStream.GetAttribute("from")); string id = xStream.GetAttribute("id"); sendStream(new XmppIq().ToStream(Jid, from, XmppIqType.Result, id, Disco.ToStreamResult())); // @@@@@ ottimizza SendIq(...) //SendIq(from, XmppIqType.Result, Disco.ToStreamResult());// @@@@@ ottimizza SendIq(...) } } // vCard xQuery = xStream.FindDescendant("vCard", "vcard-temp"); if (xQuery != null) { if (type == "result") { XmppJid from = new XmppJid(xStream.GetAttribute("from")); XmppVCard vCard = new XmppVCard(from, xQuery); if (VCard != null) { VCard(this, new XmppVCartEventArgs(vCard)); } } } // Ping xQuery = xStream.FindDescendant("ping", "urn:xmpp:ping"); if (xQuery != null) { if (type == "get") { XmppJid from = new XmppJid(xStream.GetAttribute("from")); string id = xStream.GetAttribute("id"); sendStream(new XmppIq().ToStream(Jid, from, XmppIqType.Result, id, string.Empty)); // @@@@@ ottimizza SendIq(...) } } } break; #endregion } Signal(xStream); }