/** * Notification message saying that the server supports TLS so confirm the server that we want to * secure the connection. * * @param required true when the server indicates that TLS is required. */ void startTLSReceived(boolean required) { if (required && config.getSecurityMode() == ConnectionConfiguration.SecurityMode.disabled) { packetReader.notifyConnectionError( new IllegalStateException( "TLS required by server but not allowed by connection configuration")); return; } if (required && usingSSL) { packetReader.notifyConnectionError( new IllegalStateException("TLS required by server but legacy SSL already enabled")); return; } if ((config.getSecurityMode() == ConnectionConfiguration.SecurityMode.disabled) || (config.getSecurityMode() == ConnectionConfiguration.SecurityMode.legacy)) { // Do not secure the connection using TLS since TLS was disabled or we are using SSL. return; } try { writer.write("<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>"); writer.flush(); } catch (IOException e) { packetReader.notifyConnectionError(e); } }
@Override public void run() { ServerSocket sSock = null; try { sSock = new ServerSocket(port); while (true) { try { PacketReader pr = new PacketReader(sockets); pr.socket = sSock.accept(); pr.start(); } catch (Exception ex) { ex.printStackTrace(); Thread.sleep(5000); } } } catch (Exception ex) { ex.printStackTrace(); } }
/** * Closes the connection by setting presence to unavailable then closing the stream to the XMPP * server. The shutdown logic will be used during a planned disconnection or when dealing with an * unexpected disconnection. Unlike {@link #disconnect()} the connection's packet reader, packet * writer, and {@link Roster} will not be removed; thus connection's state is kept. * * @param unavailablePresence the presence packet to send during shutdown. */ protected void shutdown(Presence unavailablePresence) { // Set presence to offline. PacketWriter packetWriter = this.packetWriter; if (packetWriter != null) { packetWriter.sendPacket(unavailablePresence); } this.setWasAuthenticated(authenticated); authenticated = false; connected = false; PacketReader packetReader = this.packetReader; if (packetReader != null) { packetReader.shutdown(); } packetWriter = this.packetWriter; if (packetWriter != null) { packetWriter.shutdown(); } // Wait 150 ms for processes to clean-up, then shutdown. try { Thread.sleep(150); } catch (Exception e) { // Ignore. } // Close down the readers and writers. Reader reader = this.reader; if (reader != null) { try { reader.close(); } catch (Throwable ignore) { /* ignore */ } this.reader = null; } Writer writer = this.writer; if (writer != null) { try { writer.close(); } catch (Throwable ignore) { /* ignore */ } this.writer = null; } try { socket.close(); } catch (Exception e) { // Ignore. } saslAuthentication.init(); }
/** * Request the server that we want to start using stream compression. When using TLS then * negotiation of stream compression can only happen after TLS was negotiated. If TLS compression * is being used the stream compression should not be used. */ private void requestStreamCompression() { try { writer.write("<compress xmlns='http://jabber.org/protocol/compress'>"); writer.write("<method>zlib</method></compress>"); writer.flush(); } catch (IOException e) { packetReader.notifyConnectionError(e); } }
@Test public void shouldFailWhenPacketLengthTooLarge() throws Exception { dataout.writeInt(Integer.MAX_VALUE); dataout.flush(); try { reader.readPacket(); fail("Should have failed to read packet of size " + Integer.MAX_VALUE); } catch (SSHException e) { e.printStackTrace(); // success; indicated packet size was too large } }
// FIXME What is the byte format for the size? Big endian? Little endian? @Test public void shouldReadPacket() throws Exception { byte[] bytes = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; dataout.writeInt(10); dataout.write(bytes); dataout.flush(); SFTPPacket<Response> packet = reader.readPacket(); assertEquals(packet.available(), 10); assertTrue( "actual=" + Arrays.toString(packet.array()), Arrays.equals(bytes, subArray(packet.array(), 0, 10))); }
public void disconnect(Presence unavailablePresence) { // If not connected, ignore this request. PacketReader packetReader = this.packetReader; PacketWriter packetWriter = this.packetWriter; if (packetReader == null || packetWriter == null) { return; } shutdown(unavailablePresence); if (roster != null) { roster.cleanup(); roster = null; } chatManager = null; wasAuthenticated = false; packetWriter.cleanup(); this.packetWriter = null; packetReader.cleanup(); this.packetReader = null; }
protected void customRun() throws InterruptedException { if (outRunnable.reconnection.get()) { Thread.sleep(10L); return; } Packet packet; try { Connection oldConnection = connection; connection = client.connectionManager.getConnection(); if (restoredConnection(oldConnection, connection)) { if (outRunnable.sendReconnectCall(connection)) { logger.log(Level.FINEST, "restoredConnection"); if (oldConnection != null) { redoUnfinishedCalls(oldConnection); } } return; } if (connection == null) { outRunnable.clusterIsDown(oldConnection); Thread.sleep(10); } else { packet = reader.readPacket(connection); // logger.log(Level.FINEST, "Reading " + packet.getOperation() + " Call id: " // + packet.getCallId()); this.lastReceived = System.currentTimeMillis(); Call call = callMap.remove(packet.getCallId()); if (call != null) { call.received = System.nanoTime(); call.setResponse(packet); } else { if (packet.getOperation().equals(ClusterOperation.EVENT)) { client.getListenerManager().enqueue(packet); } if (packet.getCallId() != -1) { logger.log( Level.SEVERE, "In Thread can not handle: " + packet.getOperation() + " : " + packet.getCallId()); } } } } catch (Throwable e) { logger.log( Level.FINEST, "InRunnable [" + connection + "] got an exception:" + e.toString(), e); outRunnable.clusterIsDown(connection); } }
/** * Establishes a connection to the XMPP server and performs an automatic login only if the * previous connection state was logged (authenticated). It basically creates and maintains a * socket connection to the server. * * <p> * * <p>Listeners will be preserved from a previous connection if the reconnection occurs after an * abrupt termination. * * @throws XMPPException if an error occurs while trying to establish the connection. Two possible * errors can occur which will be wrapped by an XMPPException -- UnknownHostException (XMPP * error code 504), and IOException (XMPP error code 502). The error codes and wrapped * exceptions can be used to present more appropiate error messages to end-users. */ public void connect() throws XMPPException { // Stablishes the connection, readers and writers connectUsingConfiguration(config); // Automatically makes the login if the user was previouslly connected successfully // to the server and the connection was terminated abruptly if (connected && wasAuthenticated) { // Make the login try { if (isAnonymous()) { // Make the anonymous login loginAnonymously(); } else { login(config.getUsername(), config.getPassword(), config.getResource()); } packetReader.notifyReconnection(); } catch (XMPPException e) { e.printStackTrace(); } } }
@Override public void read(ByteBuffer inBuffer) throws Exception { packetReader.readPacket(inBuffer); }
/** * Initializes the connection by creating a packet reader and writer and opening a XMPP stream to * the server. * * @throws XMPPException if establishing a connection to the server fails. */ private void initConnection() throws XMPPException { PacketReader packetReader = this.packetReader; PacketWriter packetWriter = this.packetWriter; boolean isFirstInitialization = packetReader == null || packetWriter == null; usingCompression = false; // Set the reader and writer instance variables initReaderAndWriter(); try { if (isFirstInitialization) { this.packetWriter = packetWriter = new PacketWriter(this); this.packetReader = packetReader = new PacketReader(this); // If debugging is enabled, we should start the thread that will listen for // all packets and then log them. if (config.isDebuggerEnabled()) { addPacketListener(debugger.getReaderListener(), null); if (debugger.getWriterListener() != null) { addPacketSendingListener(debugger.getWriterListener(), null); } } } else { packetWriter.init(); packetReader.init(); } // Start the packet writer. This will open a XMPP stream to the server packetWriter.startup(); // Start the packet reader. The startup() method will block until we // get an opening stream packet back from server. packetReader.startup(); // Make note of the fact that we're now connected. connected = true; // Start keep alive process (after TLS was negotiated - if available) packetWriter.startKeepAliveProcess(); if (isFirstInitialization) { // Notify listeners that a new connection has been established for (ConnectionCreationListener listener : getConnectionCreationListeners()) { listener.connectionCreated(this); } } else if (!wasAuthenticated) { packetReader.notifyReconnection(); } } catch (XMPPException ex) { // An exception occurred in setting up the connection. Make sure we shut down the // readers and writers and close the socket. if (packetWriter != null) { try { packetWriter.shutdown(); } catch (Throwable ignore) { /* ignore */ } this.packetWriter = null; } if (packetReader != null) { try { packetReader.shutdown(); } catch (Throwable ignore) { /* ignore */ } this.packetReader = null; } if (reader != null) { try { reader.close(); } catch (Throwable ignore) { /* ignore */ } reader = null; } if (writer != null) { try { writer.close(); } catch (Throwable ignore) { /* ignore */ } writer = null; } if (socket != null) { try { socket.close(); } catch (Exception e) { /* ignore */ } socket = null; } this.setWasAuthenticated(authenticated); chatManager = null; authenticated = false; connected = false; throw ex; // Everything stoppped. Now throw the exception. } }