1d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 2d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $RCSfile$ 3d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $Revision$ 4d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $Date$ 5d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 6d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Copyright 2009 Jive Software. 7d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 8d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); 9d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * you may not use this file except in compliance with the License. 10d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * You may obtain a copy of the License at 11d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 12d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * http://www.apache.org/licenses/LICENSE-2.0 13d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 14d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Unless required by applicable law or agreed to in writing, software 15d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * distributed under the License is distributed on an "AS IS" BASIS, 16d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * See the License for the specific language governing permissions and 18d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * limitations under the License. 19d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 20d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 21d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpackage org.jivesoftware.smack; 22d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 23d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.IOException; 24d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.PipedReader; 25d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.PipedWriter; 26d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.Writer; 27d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.concurrent.ExecutorService; 28d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.concurrent.Executors; 29d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.concurrent.ThreadFactory; 30d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 31d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.Connection; 32d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.ConnectionCreationListener; 33d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.ConnectionListener; 34d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.PacketCollector; 35d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.Roster; 36d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.XMPPException; 37d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.packet.Packet; 38d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.packet.Presence; 39d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.packet.XMPPError; 40d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.util.StringUtils; 41d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 42d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport com.kenai.jbosh.BOSHClient; 43d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport com.kenai.jbosh.BOSHClientConfig; 44d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport com.kenai.jbosh.BOSHClientConnEvent; 45d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport com.kenai.jbosh.BOSHClientConnListener; 46d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport com.kenai.jbosh.BOSHClientRequestListener; 47d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport com.kenai.jbosh.BOSHClientResponseListener; 48d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport com.kenai.jbosh.BOSHException; 49d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport com.kenai.jbosh.BOSHMessageEvent; 50d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport com.kenai.jbosh.BodyQName; 51d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport com.kenai.jbosh.ComposableBody; 52d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 53d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 54d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a connection to a XMPP server via HTTP binding. 55d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * This is specified in the XEP-0206: XMPP Over BOSH. 56d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 57d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Connection 58d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Guenther Niess 59d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 60d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic class BOSHConnection extends Connection { 61d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 62d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 63d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The XMPP Over Bosh namespace. 64d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 65d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public static final String XMPP_BOSH_NS = "urn:xmpp:xbosh"; 66d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 67d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 68d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The BOSH namespace from XEP-0124. 69d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 70d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public static final String BOSH_URI = "http://jabber.org/protocol/httpbind"; 71d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 72d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 73d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The used BOSH client from the jbosh library. 74d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 75d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private BOSHClient client; 76d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 77d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 78d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Holds the initial configuration used while creating the connection. 79d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 80d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private final BOSHConfiguration config; 81d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 82d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Some flags which provides some info about the current state. 83d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private boolean connected = false; 84d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private boolean authenticated = false; 85d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private boolean anonymous = false; 86d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private boolean isFirstInitialization = true; 87d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private boolean wasAuthenticated = false; 88d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private boolean done = false; 89d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 90d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 91d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The Thread environment for sending packet listeners. 92d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 93d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private ExecutorService listenerExecutor; 94d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 95d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // The readerPipe and consumer thread are used for the debugger. 96d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private PipedWriter readerPipe; 97d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private Thread readerConsumer; 98d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 99d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 100d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The BOSH equivalent of the stream ID which is used for DIGEST authentication. 101d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 102d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected String authID = null; 103d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 104d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 105d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The session ID for the BOSH session with the connection manager. 106d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 107d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected String sessionID = null; 108d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 109d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 110d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The full JID of the authenticated user. 111d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 112d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private String user = null; 113d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 114d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 115d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The roster maybe also called buddy list holds the list of the users contacts. 116d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 117d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private Roster roster = null; 118d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 119d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 120d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 121d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Create a HTTP Binding connection to a XMPP server. 122d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 123d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param https true if you want to use SSL 124d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * (e.g. false for http://domain.lt:7070/http-bind). 125d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param host the hostname or IP address of the connection manager 126d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * (e.g. domain.lt for http://domain.lt:7070/http-bind). 127d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param port the port of the connection manager 128d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * (e.g. 7070 for http://domain.lt:7070/http-bind). 129d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param filePath the file which is described by the URL 130d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * (e.g. /http-bind for http://domain.lt:7070/http-bind). 131d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param xmppDomain the XMPP service name 132d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * (e.g. domain.lt for the user alice@domain.lt) 133d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 134d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public BOSHConnection(boolean https, String host, int port, String filePath, String xmppDomain) { 135d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen super(new BOSHConfiguration(https, host, port, filePath, xmppDomain)); 136d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.config = (BOSHConfiguration) getConfiguration(); 137d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 138d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 139d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 140d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Create a HTTP Binding connection to a XMPP server. 141d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 142d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param config The configuration which is used for this connection. 143d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 144d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public BOSHConnection(BOSHConfiguration config) { 145d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen super(config); 146d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.config = config; 147d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 148d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 149d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void connect() throws XMPPException { 150d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (connected) { 151d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalStateException("Already connected to a server."); 152d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 153d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen done = false; 154d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 155d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Ensure a clean starting state 156d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (client != null) { 157d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen client.close(); 158d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen client = null; 159d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 160d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen saslAuthentication.init(); 161d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sessionID = null; 162d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen authID = null; 163d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 164d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Initialize BOSH client 165d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen BOSHClientConfig.Builder cfgBuilder = BOSHClientConfig.Builder 166d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen .create(config.getURI(), config.getServiceName()); 167d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (config.isProxyEnabled()) { 168d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen cfgBuilder.setProxy(config.getProxyAddress(), config.getProxyPort()); 169d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 170d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen client = BOSHClient.create(cfgBuilder.build()); 171d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 172d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Create an executor to deliver incoming packets to listeners. 173d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // We'll use a single thread with an unbounded queue. 174d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen listenerExecutor = Executors 175d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen .newSingleThreadExecutor(new ThreadFactory() { 176d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Thread newThread(Runnable runnable) { 177d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Thread thread = new Thread(runnable, 178d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "Smack Listener Processor (" 179d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen + connectionCounterValue + ")"); 180d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen thread.setDaemon(true); 181d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return thread; 182d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 183d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen }); 184d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen client.addBOSHClientConnListener(new BOSHConnectionListener(this)); 185d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen client.addBOSHClientResponseListener(new BOSHPacketReader(this)); 186d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 187d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Initialize the debugger 188d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (config.isDebuggerEnabled()) { 189d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen initDebugger(); 190d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (isFirstInitialization) { 191d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (debugger.getReaderListener() != null) { 192d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen addPacketListener(debugger.getReaderListener(), null); 193d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 194d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (debugger.getWriterListener() != null) { 195d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen addPacketSendingListener(debugger.getWriterListener(), null); 196d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 197d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 198d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 199d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 200d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Send the session creation request 201d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen client.send(ComposableBody.builder() 202d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen .setNamespaceDefinition("xmpp", XMPP_BOSH_NS) 203d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen .setAttribute(BodyQName.createWithPrefix(XMPP_BOSH_NS, "version", "xmpp"), "1.0") 204d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen .build()); 205d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } catch (Exception e) { 206d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException("Can't connect to " + getServiceName(), e); 207d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 208d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 209d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait for the response from the server 210d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (this) { 211d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen long endTime = System.currentTimeMillis() + 212d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen SmackConfiguration.getPacketReplyTimeout() * 6; 213d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen while ((!connected) && (System.currentTimeMillis() < endTime)) { 214d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 215d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen wait(Math.abs(endTime - System.currentTimeMillis())); 216d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 217d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (InterruptedException e) {} 218d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 219d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 220d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 221d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // If there is no feedback, throw an remote server timeout error 222d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!connected && !done) { 223d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen done = true; 224d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String errorMessage = "Timeout reached for the connection to " 225d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen + getHost() + ":" + getPort() + "."; 226d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException( 227d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen errorMessage, 228d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new XMPPError(XMPPError.Condition.remote_server_timeout, errorMessage)); 229d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 230d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 231d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 232d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getConnectionID() { 233d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!connected) { 234d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return null; 235d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else if (authID != null) { 236d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return authID; 237d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else { 238d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return sessionID; 239d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 240d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 241d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 242d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Roster getRoster() { 243d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (roster == null) { 244d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return null; 245d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 246d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!config.isRosterLoadedAtLogin()) { 247d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen roster.reload(); 248d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 249d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // If this is the first time the user has asked for the roster after calling 250d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // login, we want to wait for the server to send back the user's roster. 251d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // This behavior shields API users from having to worry about the fact that 252d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // roster operations are asynchronous, although they'll still have to listen 253d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // for changes to the roster. Note: because of this waiting logic, internal 254d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Smack code should be wary about calling the getRoster method, and may 255d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // need to access the roster object directly. 256d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!roster.rosterInitialized) { 257d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 258d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (roster) { 259d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen long waitTime = SmackConfiguration.getPacketReplyTimeout(); 260d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen long start = System.currentTimeMillis(); 261d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen while (!roster.rosterInitialized) { 262d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (waitTime <= 0) { 263d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen break; 264d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 265d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen roster.wait(waitTime); 266d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen long now = System.currentTimeMillis(); 267d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen waitTime -= now - start; 268d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen start = now; 269d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 270d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 271d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } catch (InterruptedException ie) { 272d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Ignore. 273d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 274d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 275d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return roster; 276d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 277d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 278d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getUser() { 279d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return user; 280d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 281d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 282d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public boolean isAnonymous() { 283d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return anonymous; 284d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 285d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 286d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public boolean isAuthenticated() { 287d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return authenticated; 288d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 289d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 290d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public boolean isConnected() { 291d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return connected; 292d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 293d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 294d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public boolean isSecureConnection() { 295d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // TODO: Implement SSL usage 296d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 297d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 298d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 299d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public boolean isUsingCompression() { 300d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // TODO: Implement compression 301d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 302d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 303d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 304d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void login(String username, String password, String resource) 305d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throws XMPPException { 306d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!isConnected()) { 307d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalStateException("Not connected to server."); 308d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 309d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (authenticated) { 310d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalStateException("Already logged in to server."); 311d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 312d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Do partial version of nameprep on the username. 313d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen username = username.toLowerCase().trim(); 314d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 315d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String response; 316d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (config.isSASLAuthenticationEnabled() 317d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen && saslAuthentication.hasNonAnonymousAuthentication()) { 318d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Authenticate using SASL 319d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (password != null) { 320d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response = saslAuthentication.authenticate(username, password, resource); 321d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else { 322d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response = saslAuthentication.authenticate(username, resource, config.getCallbackHandler()); 323d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 324d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else { 325d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Authenticate using Non-SASL 326d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response = new NonSASLAuthentication(this).authenticate(username, password, resource); 327d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 328d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 329d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Set the user. 330d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (response != null) { 331d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.user = response; 332d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Update the serviceName with the one returned by the server 333d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen config.setServiceName(StringUtils.parseServer(response)); 334d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else { 335d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.user = username + "@" + getServiceName(); 336d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (resource != null) { 337d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.user += "/" + resource; 338d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 339d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 340d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 341d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Create the roster if it is not a reconnection. 342d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (this.roster == null) { 343d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (this.rosterStorage == null) { 344d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.roster = new Roster(this); 345d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else { 346d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.roster = new Roster(this, rosterStorage); 347d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 348d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 349d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 350d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Set presence to online. 351d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (config.isSendPresence()) { 352d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sendPacket(new Presence(Presence.Type.available)); 353d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 354d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 355d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Indicate that we're now authenticated. 356d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen authenticated = true; 357d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen anonymous = false; 358d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 359d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (config.isRosterLoadedAtLogin()) { 360d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.roster.reload(); 361d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 362d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Stores the autentication for future reconnection 363d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen config.setLoginInfo(username, password, resource); 364d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 365d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // If debugging is enabled, change the the debug window title to include 366d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // the 367d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // name we are now logged-in as.l 368d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (config.isDebuggerEnabled() && debugger != null) { 369d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen debugger.userHasLogged(user); 370d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 371d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 372d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 373d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void loginAnonymously() throws XMPPException { 374d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!isConnected()) { 375d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalStateException("Not connected to server."); 376d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 377d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (authenticated) { 378d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalStateException("Already logged in to server."); 379d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 380d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 381d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String response; 382d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (config.isSASLAuthenticationEnabled() && 383d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen saslAuthentication.hasAnonymousAuthentication()) { 384d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response = saslAuthentication.authenticateAnonymously(); 385d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 386d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else { 387d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Authenticate using Non-SASL 388d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response = new NonSASLAuthentication(this).authenticateAnonymously(); 389d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 390d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 391d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Set the user value. 392d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.user = response; 393d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Update the serviceName with the one returned by the server 394d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen config.setServiceName(StringUtils.parseServer(response)); 395d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 396d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Anonymous users can't have a roster. 397d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen roster = null; 398d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 399d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Set presence to online. 400d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (config.isSendPresence()) { 401d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sendPacket(new Presence(Presence.Type.available)); 402d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 403d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 404d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Indicate that we're now authenticated. 405d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen authenticated = true; 406d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen anonymous = true; 407d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 408d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // If debugging is enabled, change the the debug window title to include the 409d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // name we are now logged-in as. 410d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // If DEBUG_ENABLED was set to true AFTER the connection was created the debugger 411d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // will be null 412d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (config.isDebuggerEnabled() && debugger != null) { 413d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen debugger.userHasLogged(user); 414d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 415d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 416d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 417d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void sendPacket(Packet packet) { 418d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!isConnected()) { 419d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalStateException("Not connected to server."); 420d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 421d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (packet == null) { 422d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new NullPointerException("Packet is null."); 423d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 424d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!done) { 425d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Invoke interceptors for the new packet that is about to be sent. 426d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Interceptors 427d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // may modify the content of the packet. 428d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen firePacketInterceptors(packet); 429d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 430d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 431d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen send(ComposableBody.builder().setPayloadXML(packet.toXML()) 432d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen .build()); 433d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } catch (BOSHException e) { 434d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen e.printStackTrace(); 435d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return; 436d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 437d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 438d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Process packet writer listeners. Note that we're using the 439d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // sending 440d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // thread so it's expected that listeners are fast. 441d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen firePacketSendingListeners(packet); 442d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 443d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 444d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 445d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void disconnect(Presence unavailablePresence) { 446d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!connected) { 447d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return; 448d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 449d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen shutdown(unavailablePresence); 450d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 451d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Cleanup 452d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (roster != null) { 453d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen roster.cleanup(); 454d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen roster = null; 455d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 456d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sendListeners.clear(); 457d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen recvListeners.clear(); 458d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen collectors.clear(); 459d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen interceptors.clear(); 460d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 461d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Reset the connection flags 462d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen wasAuthenticated = false; 463d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen isFirstInitialization = true; 464d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 465d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Notify connection listeners of the connection closing if done hasn't already been set. 466d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (ConnectionListener listener : getConnectionListeners()) { 467d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 468d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen listener.connectionClosed(); 469d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 470d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (Exception e) { 471d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Catch and print any exception so we can recover 472d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // from a faulty listener and finish the shutdown process 473d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen e.printStackTrace(); 474d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 475d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 476d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 477d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 478d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 479d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Closes the connection by setting presence to unavailable and closing the 480d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * HTTP client. The shutdown logic will be used during a planned disconnection or when 481d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * dealing with an unexpected disconnection. Unlike {@link #disconnect()} the connection's 482d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * BOSH packet reader and {@link Roster} will not be removed; thus 483d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * connection's state is kept. 484d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 485d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param unavailablePresence the presence packet to send during shutdown. 486d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 487d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected void shutdown(Presence unavailablePresence) { 488d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen setWasAuthenticated(authenticated); 489d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen authID = null; 490d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sessionID = null; 491d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen done = true; 492d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen authenticated = false; 493d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connected = false; 494d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen isFirstInitialization = false; 495d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 496d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 497d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen client.disconnect(ComposableBody.builder() 498d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen .setNamespaceDefinition("xmpp", XMPP_BOSH_NS) 499d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen .setPayloadXML(unavailablePresence.toXML()) 500d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen .build()); 501d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait 150 ms for processes to clean-up, then shutdown. 502d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Thread.sleep(150); 503d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 504d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (Exception e) { 505d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Ignore. 506d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 507d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 508d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Close down the readers and writers. 509d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (readerPipe != null) { 510d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 511d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen readerPipe.close(); 512d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 513d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (Throwable ignore) { /* ignore */ } 514d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen reader = null; 515d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 516d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (reader != null) { 517d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 518d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen reader.close(); 519d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 520d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (Throwable ignore) { /* ignore */ } 521d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen reader = null; 522d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 523d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (writer != null) { 524d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 525d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen writer.close(); 526d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 527d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (Throwable ignore) { /* ignore */ } 528d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen writer = null; 529d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 530d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 531d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Shut down the listener executor. 532d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (listenerExecutor != null) { 533d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen listenerExecutor.shutdown(); 534d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 535d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen readerConsumer = null; 536d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 537d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 538d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 539d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Sets whether the connection has already logged in the server. 540d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 541d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param wasAuthenticated true if the connection has already been authenticated. 542d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 543d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void setWasAuthenticated(boolean wasAuthenticated) { 544d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!this.wasAuthenticated) { 545d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.wasAuthenticated = wasAuthenticated; 546d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 547d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 548d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 549d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 550d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Send a HTTP request to the connection manager with the provided body element. 551d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 552d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param body the body which will be sent. 553d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 554d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected void send(ComposableBody body) throws BOSHException { 555d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!connected) { 556d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalStateException("Not connected to a server!"); 557d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 558d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (body == null) { 559d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new NullPointerException("Body mustn't be null!"); 560d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 561d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (sessionID != null) { 562d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen body = body.rebuild().setAttribute( 563d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen BodyQName.create(BOSH_URI, "sid"), sessionID).build(); 564d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 565d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen client.send(body); 566d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 567d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 568d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 569d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Processes a packet after it's been fully parsed by looping through the 570d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * installed packet collectors and listeners and letting them examine the 571d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * packet to see if they are a match with the filter. 572d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 573d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param packet the packet to process. 574d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 575d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected void processPacket(Packet packet) { 576d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (packet == null) { 577d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return; 578d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 579d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 580d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Loop through all collectors and notify the appropriate ones. 581d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (PacketCollector collector : getPacketCollectors()) { 582d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen collector.processPacket(packet); 583d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 584d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 585d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Deliver the incoming packet to listeners. 586d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen listenerExecutor.submit(new ListenerNotification(packet)); 587d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 588d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 589d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 590d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Initialize the SmackDebugger which allows to log and debug XML traffic. 591d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 592d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected void initDebugger() { 593d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // TODO: Maybe we want to extend the SmackDebugger for simplification 594d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // and a performance boost. 595d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 596d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Initialize a empty writer which discards all data. 597d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen writer = new Writer() { 598d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void write(char[] cbuf, int off, int len) { /* ignore */} 599d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void close() { /* ignore */ } 600d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void flush() { /* ignore */ } 601d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen }; 602d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 603d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Initialize a pipe for received raw data. 604d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 605d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen readerPipe = new PipedWriter(); 606d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen reader = new PipedReader(readerPipe); 607d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 608d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (IOException e) { 609d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Ignore 610d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 611d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 612d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Call the method from the parent class which initializes the debugger. 613d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen super.initDebugger(); 614d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 615d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Add listeners for the received and sent raw data. 616d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen client.addBOSHClientResponseListener(new BOSHClientResponseListener() { 617d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void responseReceived(BOSHMessageEvent event) { 618d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (event.getBody() != null) { 619d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 620d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen readerPipe.write(event.getBody().toXML()); 621d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen readerPipe.flush(); 622d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } catch (Exception e) { 623d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Ignore 624d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 625d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 626d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 627d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen }); 628d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen client.addBOSHClientRequestListener(new BOSHClientRequestListener() { 629d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void requestSent(BOSHMessageEvent event) { 630d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (event.getBody() != null) { 631d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 632d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen writer.write(event.getBody().toXML()); 633d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } catch (Exception e) { 634d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Ignore 635d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 636d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 637d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 638d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen }); 639d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 640d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Create and start a thread which discards all read data. 641d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen readerConsumer = new Thread() { 642d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private Thread thread = this; 643d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private int bufferLength = 1024; 644d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 645d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void run() { 646d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 647d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen char[] cbuf = new char[bufferLength]; 648d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen while (readerConsumer == thread && !done) { 649d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen reader.read(cbuf, 0, bufferLength); 650d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 651d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } catch (IOException e) { 652d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Ignore 653d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 654d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 655d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen }; 656d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen readerConsumer.setDaemon(true); 657d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen readerConsumer.start(); 658d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 659d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 660d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 661d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Sends out a notification that there was an error with the connection 662d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * and closes the connection. 663d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 664d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param e the exception that causes the connection close event. 665d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 666d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected void notifyConnectionError(Exception e) { 667d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Closes the connection temporary. A reconnection is possible 668d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen shutdown(new Presence(Presence.Type.unavailable)); 669d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Print the stack trace to help catch the problem 670d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen e.printStackTrace(); 671d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Notify connection listeners of the error. 672d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (ConnectionListener listener : getConnectionListeners()) { 673d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 674d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen listener.connectionClosedOnError(e); 675d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 676d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (Exception e2) { 677d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Catch and print any exception so we can recover 678d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // from a faulty listener 679d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen e2.printStackTrace(); 680d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 681d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 682d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 683d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 684d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 685d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 686d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * A listener class which listen for a successfully established connection 687d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * and connection errors and notifies the BOSHConnection. 688d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 689d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Guenther Niess 690d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 691d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private class BOSHConnectionListener implements BOSHClientConnListener { 692d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 693d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private final BOSHConnection connection; 694d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 695d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public BOSHConnectionListener(BOSHConnection connection) { 696d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.connection = connection; 697d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 698d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 699d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 700d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Notify the BOSHConnection about connection state changes. 701d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Process the connection listeners and try to login if the 702d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * connection was formerly authenticated and is now reconnected. 703d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 704d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void connectionEvent(BOSHClientConnEvent connEvent) { 705d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 706d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (connEvent.isConnected()) { 707d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connected = true; 708d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (isFirstInitialization) { 709d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen isFirstInitialization = false; 710d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (ConnectionCreationListener listener : getConnectionCreationListeners()) { 711d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen listener.connectionCreated(connection); 712d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 713d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 714d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else { 715d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 716d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (wasAuthenticated) { 717d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.login( 718d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen config.getUsername(), 719d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen config.getPassword(), 720d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen config.getResource()); 721d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 722d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (ConnectionListener listener : getConnectionListeners()) { 723d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen listener.reconnectionSuccessful(); 724d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 725d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 726d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (XMPPException e) { 727d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (ConnectionListener listener : getConnectionListeners()) { 728d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen listener.reconnectionFailed(e); 729d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 730d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 731d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 732d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 733d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else { 734d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (connEvent.isError()) { 735d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 736d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connEvent.getCause(); 737d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 738d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (Exception e) { 739d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen notifyConnectionError(e); 740d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 741d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 742d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connected = false; 743d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 744d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 745d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen finally { 746d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (connection) { 747d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.notifyAll(); 748d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 749d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 750d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 751d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 752d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 753d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 754d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * This class notifies all listeners that a packet was received. 755d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 756d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private class ListenerNotification implements Runnable { 757d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 758d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private Packet packet; 759d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 760d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public ListenerNotification(Packet packet) { 761d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.packet = packet; 762d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 763d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 764d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void run() { 765d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (ListenerWrapper listenerWrapper : recvListeners.values()) { 766d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen listenerWrapper.notifyListener(packet); 767d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 768d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 769d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 770d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 771d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen @Override 772d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void setRosterStorage(RosterStorage storage) 773d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throws IllegalStateException { 774d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if(this.roster!=null){ 775d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalStateException("Roster is already initialized"); 776d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 777d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.rosterStorage = storage; 778d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 779d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 780