/* Copyright (c) 2008 Bluendo S.r.L. * See about.html for details about license. * * $Id: SocketStream.java 1577 2009-06-15 14:38:27Z luca $ */ package it.yup.xmlstream; import java.io.IOException; import org.xmlpull.v1.XmlPullParserException; import it.yup.transport.BaseChannel; import it.yup.transport.SocketChannel; // #mdebug import it.yup.util.Logger; // #enddebug import it.yup.util.Utils; import it.yup.xml.Element; import it.yup.xml.KXmlParser; import it.yup.xml.KXmlProcessor; import it.yup.xmpp.Contact; public class SocketStream extends BasicXmlStream implements Runnable { private KXmlParser parser = null; private SocketChannel channel = null; private int level; public void initialize(String jid, String password) { this.jid = jid; this.password = password; // Create an instance of the XML parser lasting as long as the stream parser = new KXmlParser(); try { parser.setFeature(KXmlParser.FEATURE_PROCESS_NAMESPACES, true); } catch (XmlPullParserException e1) { // Can't happen } } protected void restart() { try { // parser.require(KXmlParser.START_DOCUMENT, null, null); // #debug Logger.log("setting parser input"); level = 0; parser.setInput(this.channel.getReader()); parser.defineEntityReplacementText("quot", "\""); StringBuffer streamStart = new StringBuffer(); streamStart.append("<?xml version=\"1.0\"?>\n"); streamStart .append("<stream:stream xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\" xmlns=\"jabber:client\" xml:lang=\"en\" xmlns:xml=\"http://www.w3.org/XML/1998/namespace\""); streamStart.append((" to=\"" + Contact.domain(jid) + "\">")); // #debug Logger.log("Sending stream start"); // channel.sendContent(streamStart.toString().getBytes("utf-8")); channel.sendContent(Utils.getBytesUtf8(streamStart.toString())); } catch (XmlPullParserException e) { dispatchEvent(BasicXmlStream.STREAM_ERROR, null); // #mdebug Logger.log("[SocketStream::restart] XmlPullParserException: " + e.getMessage()); // #enddebug } } protected void tryToSend() { // simply pass the packets to the channel synchronized (this.sendQueue) { for (int i = 0; i < this.sendQueue.size(); i++) this.channel .sendContent(((Element) this.sendQueue.elementAt(i)) .toXml()); this.sendQueue.removeAllElements(); } } public void connectionEstablished(BaseChannel connection) { // #debug Logger.log("Connection established"); this.channel = (SocketChannel) connection; dispatchEvent(BasicXmlStream.STREAM_CONNECTED, null); // #debug Logger.log("restarting stream"); restart(); // #debug Logger.log("starting reader"); new Thread(this).start(); } public void connectionFailed(BaseChannel connection) { dispatchEvent(BasicXmlStream.CONNECTION_FAILED, null); } public void connectionLost(BaseChannel connection) { synchronized (this.sendQueue) { // XXX: not the final answer: we must take into // consideration that when switching through // multiple transports this is not feasible!!! this.sendQueue.removeAllElements(); } dispatchEvent(BasicXmlStream.STREAM_TERMINATED, null); dispatchEvent(BasicXmlStream.CONNECTION_LOST, null); } public void run() { try { level = 0; parser.require(KXmlParser.START_DOCUMENT, null, null); while (true) { int token = parser.nextToken(); // logger.log("Got token: " + token + " level: " + level); if (token == KXmlParser.START_TAG) { level += 1; if (level == 1) { Element documentStart = KXmlProcessor .pullDocumentStart(parser); this.SID = documentStart.getAttribute("id"); } else if (level == 2) { // logger.log("pulling stanza"); Element stanza = KXmlProcessor.pullElement(parser); level -= 1; // #debug Logger.log("[RECV] " + new String(stanza.toXml())); promotePacket(stanza); if ("features".equals(stanza.name)) { processFeatures(stanza.getChildren()); } } } } } catch (XmlPullParserException e) { // #debug Logger.log(e.getMessage()); this.channel.close(); connectionLost(this.channel); } catch (IOException e) { // #mdebug Logger.log(e.getMessage()); e.printStackTrace(); // #enddebug connectionLost(this.channel); } catch (Exception e) { // catch this to avoid a problem that cannot be catched outside try { this.channel.close(); connectionLost(this.channel); } catch (Exception innerE) { } // #mdebug Logger.log("Parser " + e.getClass().getName() + ":" + e.getMessage()); // #enddebug } } // #ifdef TLS protected void startTLS() throws IOException { channel.startTLS(); } // #endif // #ifdef COMPRESSION protected void startCompression() { channel.startCompression(); } // #endif }