aboutsummaryrefslogtreecommitdiff
path: root/src/org/jivesoftware/smack/BOSHPacketReader.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/org/jivesoftware/smack/BOSHPacketReader.java')
-rw-r--r--src/org/jivesoftware/smack/BOSHPacketReader.java169
1 files changed, 169 insertions, 0 deletions
diff --git a/src/org/jivesoftware/smack/BOSHPacketReader.java b/src/org/jivesoftware/smack/BOSHPacketReader.java
new file mode 100644
index 0000000..c86d756
--- /dev/null
+++ b/src/org/jivesoftware/smack/BOSHPacketReader.java
@@ -0,0 +1,169 @@
+/**
+ * $RCSfile$
+ * $Revision$
+ * $Date$
+ *
+ * Copyright 2009 Jive Software.
+ *
+ * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jivesoftware.smack;
+
+import java.io.StringReader;
+
+import org.jivesoftware.smack.util.PacketParserUtils;
+import org.jivesoftware.smack.sasl.SASLMechanism.Challenge;
+import org.jivesoftware.smack.sasl.SASLMechanism.Failure;
+import org.jivesoftware.smack.sasl.SASLMechanism.Success;
+import org.xmlpull.v1.XmlPullParserFactory;
+import org.xmlpull.v1.XmlPullParser;
+
+import com.kenai.jbosh.AbstractBody;
+import com.kenai.jbosh.BOSHClientResponseListener;
+import com.kenai.jbosh.BOSHMessageEvent;
+import com.kenai.jbosh.BodyQName;
+import com.kenai.jbosh.ComposableBody;
+
+/**
+ * Listens for XML traffic from the BOSH connection manager and parses it into
+ * packet objects.
+ *
+ * @author Guenther Niess
+ */
+public class BOSHPacketReader implements BOSHClientResponseListener {
+
+ private BOSHConnection connection;
+
+ /**
+ * Create a packet reader which listen on a BOSHConnection for received
+ * HTTP responses, parse the packets and notifies the connection.
+ *
+ * @param connection the corresponding connection for the received packets.
+ */
+ public BOSHPacketReader(BOSHConnection connection) {
+ this.connection = connection;
+ }
+
+ /**
+ * Parse the received packets and notify the corresponding connection.
+ *
+ * @param event the BOSH client response which includes the received packet.
+ */
+ public void responseReceived(BOSHMessageEvent event) {
+ AbstractBody body = event.getBody();
+ if (body != null) {
+ try {
+ if (connection.sessionID == null) {
+ connection.sessionID = body.getAttribute(BodyQName.create(BOSHConnection.BOSH_URI, "sid"));
+ }
+ if (connection.authID == null) {
+ connection.authID = body.getAttribute(BodyQName.create(BOSHConnection.BOSH_URI, "authid"));
+ }
+ final XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
+ parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES,
+ true);
+ parser.setInput(new StringReader(body.toXML()));
+ int eventType = parser.getEventType();
+ do {
+ eventType = parser.next();
+ if (eventType == XmlPullParser.START_TAG) {
+ if (parser.getName().equals("body")) {
+ // ignore the container root element
+ } else if (parser.getName().equals("message")) {
+ connection.processPacket(PacketParserUtils.parseMessage(parser));
+ } else if (parser.getName().equals("iq")) {
+ connection.processPacket(PacketParserUtils.parseIQ(parser, connection));
+ } else if (parser.getName().equals("presence")) {
+ connection.processPacket(PacketParserUtils.parsePresence(parser));
+ } else if (parser.getName().equals("challenge")) {
+ // The server is challenging the SASL authentication
+ // made by the client
+ final String challengeData = parser.nextText();
+ connection.getSASLAuthentication()
+ .challengeReceived(challengeData);
+ connection.processPacket(new Challenge(
+ challengeData));
+ } else if (parser.getName().equals("success")) {
+ connection.send(ComposableBody.builder()
+ .setNamespaceDefinition("xmpp", BOSHConnection.XMPP_BOSH_NS)
+ .setAttribute(
+ BodyQName.createWithPrefix(BOSHConnection.XMPP_BOSH_NS, "restart", "xmpp"),
+ "true")
+ .setAttribute(
+ BodyQName.create(BOSHConnection.BOSH_URI, "to"),
+ connection.getServiceName())
+ .build());
+ connection.getSASLAuthentication().authenticated();
+ connection.processPacket(new Success(parser.nextText()));
+ } else if (parser.getName().equals("features")) {
+ parseFeatures(parser);
+ } else if (parser.getName().equals("failure")) {
+ if ("urn:ietf:params:xml:ns:xmpp-sasl".equals(parser.getNamespace(null))) {
+ final Failure failure = PacketParserUtils.parseSASLFailure(parser);
+ connection.getSASLAuthentication().authenticationFailed();
+ connection.processPacket(failure);
+ }
+ } else if (parser.getName().equals("error")) {
+ throw new XMPPException(PacketParserUtils.parseStreamError(parser));
+ }
+ }
+ } while (eventType != XmlPullParser.END_DOCUMENT);
+ }
+ catch (Exception e) {
+ if (connection.isConnected()) {
+ connection.notifyConnectionError(e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Parse and setup the XML stream features.
+ *
+ * @param parser the XML parser, positioned at the start of a message packet.
+ * @throws Exception if an exception occurs while parsing the packet.
+ */
+ private void parseFeatures(XmlPullParser parser) throws Exception {
+ boolean done = false;
+ while (!done) {
+ int eventType = parser.next();
+
+ if (eventType == XmlPullParser.START_TAG) {
+ if (parser.getName().equals("mechanisms")) {
+ // The server is reporting available SASL mechanisms. Store
+ // this information
+ // which will be used later while logging (i.e.
+ // authenticating) into
+ // the server
+ connection.getSASLAuthentication().setAvailableSASLMethods(
+ PacketParserUtils.parseMechanisms(parser));
+ } else if (parser.getName().equals("bind")) {
+ // The server requires the client to bind a resource to the
+ // stream
+ connection.getSASLAuthentication().bindingRequired();
+ } else if (parser.getName().equals("session")) {
+ // The server supports sessions
+ connection.getSASLAuthentication().sessionsSupported();
+ } else if (parser.getName().equals("register")) {
+ connection.getAccountManager().setSupportsAccountCreation(
+ true);
+ }
+ } else if (eventType == XmlPullParser.END_TAG) {
+ if (parser.getName().equals("features")) {
+ done = true;
+ }
+ }
+ }
+ }
+}