1 20 21 package org.jivesoftware.smack; 22 23 import org.jivesoftware.smack.debugger.SmackDebugger; 24 import org.jivesoftware.smack.filter.PacketFilter; 25 import org.jivesoftware.smack.filter.PacketIDFilter; 26 import org.jivesoftware.smack.packet.*; 27 import org.jivesoftware.smack.util.StringUtils; 28 29 import javax.net.SocketFactory; 30 import javax.net.ssl.SSLContext; 31 import javax.net.ssl.SSLSocket; 32 import java.io.*; 33 import java.lang.reflect.Constructor ; 34 import java.net.Socket ; 35 import java.net.UnknownHostException ; 36 import java.util.ArrayList ; 37 import java.util.List ; 38 39 54 public class XMPPConnection { 55 56 69 public static boolean DEBUG_ENABLED = false; 70 71 private static List connectionEstablishedListeners = new ArrayList (); 72 73 static { 74 try { 77 DEBUG_ENABLED = Boolean.getBoolean("smack.debugEnabled"); 78 } 79 catch (Exception e) { 80 } 81 SmackConfiguration.getVersion(); 83 } 84 private SmackDebugger debugger = null; 85 86 91 String host; 92 int port; 93 Socket socket; 94 99 String serviceName; 100 101 String connectionID; 102 private String user = null; 103 private boolean connected = false; 104 private boolean authenticated = false; 105 private boolean anonymous = false; 106 private boolean usingTLS = false; 107 108 PacketWriter packetWriter; 109 PacketReader packetReader; 110 111 Roster roster = null; 112 private AccountManager accountManager = null; 113 private SASLAuthentication saslAuthentication = new SASLAuthentication(this); 114 115 Writer writer; 116 Reader reader; 117 118 129 public XMPPConnection(String serviceName) throws XMPPException { 130 this(serviceName, 5222, serviceName); 131 } 132 133 145 public XMPPConnection(String host, int port) throws XMPPException { 146 this(host, port, host); 147 } 148 149 161 public XMPPConnection(String host, int port, String serviceName) throws XMPPException { 162 this.host = host; 163 this.port = port; 164 try { 165 this.socket = new Socket(host, port); 166 } 167 catch (UnknownHostException uhe) { 168 throw new XMPPException( 169 "Could not connect to " + host + ":" + port + ".", 170 new XMPPError(504), 171 uhe); 172 } 173 catch (IOException ioe) { 174 throw new XMPPException( 175 "XMPPError connecting to " + host + ":" + port + ".", 176 new XMPPError(502), 177 ioe); 178 } 179 this.serviceName = serviceName; 180 init(); 181 } 182 183 202 public XMPPConnection(String host, int port, String serviceName, SocketFactory socketFactory) 203 throws XMPPException { 204 this.host = host; 205 this.port = port; 206 try { 207 this.socket = socketFactory.createSocket(host, port); 208 } 209 catch (UnknownHostException uhe) { 210 throw new XMPPException( 211 "Could not connect to " + host + ":" + port + ".", 212 new XMPPError(504), 213 uhe); 214 } 215 catch (IOException ioe) { 216 throw new XMPPException( 217 "XMPPError connecting to " + host + ":" + port + ".", 218 new XMPPError(502), 219 ioe); 220 } 221 this.serviceName = serviceName; 222 init(); 223 } 224 225 230 XMPPConnection() { 231 } 232 233 240 public String getConnectionID() { 241 return connectionID; 242 } 243 244 250 public String getServiceName() { 251 return serviceName; 252 } 253 254 260 public String getHost() { 261 return host; 262 } 263 264 270 public int getPort() { 271 return port; 272 } 273 274 281 public String getUser() { 282 if (!isAuthenticated()) { 283 return null; 284 } 285 return user; 286 } 287 288 298 public void login(String username, String password) throws XMPPException { 299 login(username, password, "Smack"); 300 } 301 302 315 public synchronized void login(String username, String password, String resource) 316 throws XMPPException 317 { 318 login(username, password, resource, true); 319 } 320 321 337 public synchronized void login(String username, String password, String resource, 338 boolean sendPresence) throws XMPPException 339 { 340 if (!isConnected()) { 341 throw new IllegalStateException ("Not connected to server."); 342 } 343 if (authenticated) { 344 throw new IllegalStateException ("Already logged in to server."); 345 } 346 username = username.toLowerCase().trim(); 348 349 String response = null; 350 if (usingTLS) { 351 response = saslAuthentication.authenticate(username, password, resource); 353 } 354 else { 355 response = new NonSASLAuthentication(this).authenticate(username, password, resource); 357 } 358 359 if (response != null) { 361 this.user = response; 362 this.serviceName = StringUtils.parseServer(response); 364 } 365 else { 366 this.user = username + "@" + this.serviceName; 367 if (resource != null) { 368 this.user += "/" + resource; 369 } 370 } 371 372 this.roster = new Roster(this); 374 roster.reload(); 375 376 if (sendPresence) { 378 packetWriter.sendPacket(new Presence(Presence.Type.AVAILABLE)); 379 } 380 381 authenticated = true; 383 anonymous = false; 384 385 if (DEBUG_ENABLED && debugger != null) { 390 debugger.userHasLogged(user); 391 } 392 } 393 394 404 public synchronized void loginAnonymously() throws XMPPException { 405 if (!isConnected()) { 406 throw new IllegalStateException ("Not connected to server."); 407 } 408 if (authenticated) { 409 throw new IllegalStateException ("Already logged in to server."); 410 } 411 412 Authentication auth = new Authentication(); 414 415 PacketCollector collector = 416 packetReader.createPacketCollector(new PacketIDFilter(auth.getPacketID())); 417 packetWriter.sendPacket(auth); 419 IQ response = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout()); 421 if (response == null) { 422 throw new XMPPException("Anonymous login failed."); 423 } 424 else if (response.getType() == IQ.Type.ERROR) { 425 throw new XMPPException(response.getError()); 426 } 427 if (response.getTo() != null) { 429 this.user = response.getTo(); 430 } 431 else { 432 this.user = this.serviceName + "/" + ((Authentication) response).getResource(); 433 } 434 collector.cancel(); 436 437 roster = null; 439 440 packetWriter.sendPacket(new Presence(Presence.Type.AVAILABLE)); 442 443 authenticated = true; 445 anonymous = true; 446 447 if (DEBUG_ENABLED && debugger != null) { 452 debugger.userHasLogged(user); 453 } 454 } 455 456 463 public Roster getRoster() { 464 if (roster == null) { 465 return null; 466 } 467 if (!roster.rosterInitialized) { 475 try { 476 synchronized (roster) { 477 long waitTime = SmackConfiguration.getPacketReplyTimeout(); 478 long start = System.currentTimeMillis(); 479 while (!roster.rosterInitialized) { 480 if (waitTime <= 0) { 481 break; 482 } 483 roster.wait(waitTime); 484 long now = System.currentTimeMillis(); 485 waitTime -= now - start; 486 start = now; 487 } 488 } 489 } 490 catch (InterruptedException ie) { } 491 } 492 return roster; 493 } 494 495 500 public synchronized AccountManager getAccountManager() { 501 if (accountManager == null) { 502 accountManager = new AccountManager(this); 503 } 504 return accountManager; 505 } 506 507 515 public Chat createChat(String participant) { 516 if (!isConnected()) { 517 throw new IllegalStateException ("Not connected to server."); 518 } 519 return new Chat(this, participant); 520 } 521 522 533 public GroupChat createGroupChat(String room) { 534 if (!isConnected()) { 535 throw new IllegalStateException ("Not connected to server."); 536 } 537 return new GroupChat(this, room); 538 } 539 540 545 public boolean isConnected() { 546 return connected; 547 } 548 549 554 public boolean isSecureConnection() { 555 return false; 556 } 557 558 563 public boolean isAuthenticated() { 564 return authenticated; 565 } 566 567 572 public boolean isAnonymous() { 573 return anonymous; 574 } 575 576 580 public void close() { 581 packetWriter.sendPacket(new Presence(Presence.Type.UNAVAILABLE)); 583 packetReader.shutdown(); 584 packetWriter.shutdown(); 585 try { 587 Thread.sleep(150); 588 } 589 catch (Exception e) { 590 } 591 592 if (reader != null) 594 { 595 try { reader.close(); } catch (Throwable ignore) { } 596 reader = null; 597 } 598 if (writer != null) 599 { 600 try { writer.close(); } catch (Throwable ignore) { } 601 writer = null; 602 } 603 604 try { 605 socket.close(); 606 } 607 catch (Exception e) { 608 } 609 authenticated = false; 610 connected = false; 611 } 612 613 618 public void sendPacket(Packet packet) { 619 if (!isConnected()) { 620 throw new IllegalStateException ("Not connected to server."); 621 } 622 if (packet == null) { 623 throw new NullPointerException ("Packet is null."); 624 } 625 packetWriter.sendPacket(packet); 626 } 627 628 635 public void addPacketListener(PacketListener packetListener, PacketFilter packetFilter) { 636 if (!isConnected()) { 637 throw new IllegalStateException ("Not connected to server."); 638 } 639 packetReader.addPacketListener(packetListener, packetFilter); 640 } 641 642 647 public void removePacketListener(PacketListener packetListener) { 648 packetReader.removePacketListener(packetListener); 649 } 650 651 659 public void addPacketWriterListener(PacketListener packetListener, PacketFilter packetFilter) { 660 if (!isConnected()) { 661 throw new IllegalStateException ("Not connected to server."); 662 } 663 packetWriter.addPacketListener(packetListener, packetFilter); 664 } 665 666 671 public void removePacketWriterListener(PacketListener packetListener) { 672 packetWriter.removePacketListener(packetListener); 673 } 674 675 682 public PacketCollector createPacketCollector(PacketFilter packetFilter) { 683 return packetReader.createPacketCollector(packetFilter); 684 } 685 686 692 public void addConnectionListener(ConnectionListener connectionListener) { 693 if (connectionListener == null) { 694 return; 695 } 696 synchronized (packetReader.connectionListeners) { 697 if (!packetReader.connectionListeners.contains(connectionListener)) { 698 packetReader.connectionListeners.add(connectionListener); 699 } 700 } 701 } 702 703 708 public void removeConnectionListener(ConnectionListener connectionListener) { 709 synchronized (packetReader.connectionListeners) { 710 packetReader.connectionListeners.remove(connectionListener); 711 } 712 } 713 714 720 public static void addConnectionListener(ConnectionEstablishedListener connectionEstablishedListener) { 721 synchronized (connectionEstablishedListeners) { 722 if (!connectionEstablishedListeners.contains(connectionEstablishedListener)) { 723 connectionEstablishedListeners.add(connectionEstablishedListener); 724 } 725 } 726 } 727 728 733 public static void removeConnectionListener(ConnectionEstablishedListener connectionEstablishedListener) { 734 synchronized (connectionEstablishedListeners) { 735 connectionEstablishedListeners.remove(connectionEstablishedListener); 736 } 737 } 738 739 745 private void init() throws XMPPException { 746 initReaderAndWriter(); 748 749 try 750 { 751 packetWriter = new PacketWriter(this); 752 packetReader = new PacketReader(this); 753 754 if (DEBUG_ENABLED) { 757 packetReader.addPacketListener(debugger.getReaderListener(), null); 758 if (debugger.getWriterListener() != null) { 759 packetWriter.addPacketListener(debugger.getWriterListener(), null); 760 } 761 } 762 packetWriter.startup(); 764 packetReader.startup(); 767 768 connected = true; 770 771 connectionEstablished(this); 773 } 774 catch (XMPPException ex) 775 { 776 779 if (packetWriter != null) { 780 try { packetWriter.shutdown(); } catch (Throwable ignore) { } 781 packetWriter = null; 782 } 783 if (packetReader != null) { 784 try { packetReader.shutdown(); } catch (Throwable ignore) { } 785 packetReader = null; 786 } 787 if (reader != null) { 788 try { reader.close(); } catch (Throwable ignore) { } 789 reader = null; 790 } 791 if (writer != null) { 792 try { writer.close(); } catch (Throwable ignore) { } 793 writer = null; 794 } 795 if (socket != null) { 796 try { socket.close(); } catch (Exception e) { } 797 socket = null; 798 } 799 authenticated = false; 800 connected = false; 801 802 throw ex; } 804 } 805 806 private void initReaderAndWriter() throws XMPPException { 807 try { 808 reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8")); 809 writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8")); 810 } 811 catch (IOException ioe) { 812 throw new XMPPException( 813 "XMPPError establishing connection with server.", 814 new XMPPError(502), 815 ioe); 816 } 817 818 if (DEBUG_ENABLED) { 820 if (debugger == null) { 821 String className = null; 823 try { 826 className = System.getProperty("smack.debuggerClass"); 827 } 828 catch (Throwable t) { 829 } 830 Class debuggerClass = null; 831 if (className != null) { 832 try { 833 debuggerClass = Class.forName(className); 834 } 835 catch (Exception e) { 836 e.printStackTrace(); 837 } 838 } 839 if (debuggerClass == null) { 840 try { 841 debuggerClass = 842 Class.forName("org.jivesoftware.smackx.debugger.EnhancedDebugger"); 843 } 844 catch (Exception ex) { 845 try { 846 debuggerClass = Class.forName("org.jivesoftware.smack.debugger.LiteDebugger"); 847 } 848 catch (Exception ex2) { 849 ex2.printStackTrace(); 850 } 851 } 852 } 853 try { 856 Constructor constructor = 857 debuggerClass.getConstructor( 858 new Class [] { XMPPConnection.class, Writer.class, Reader.class }); 859 debugger = (SmackDebugger) constructor 860 .newInstance(new Object []{this, writer, reader}); 861 reader = debugger.getReader(); 862 writer = debugger.getWriter(); 863 } 864 catch (Exception e) { 865 e.printStackTrace(); 866 DEBUG_ENABLED = false; 867 } 868 } 869 else { 870 reader = debugger.newConnectionReader(reader); 872 writer = debugger.newConnectionWriter(writer); 873 } 874 } 875 } 876 877 880 private static void connectionEstablished(XMPPConnection connection) { 881 ConnectionEstablishedListener[] listeners = null; 882 synchronized (connectionEstablishedListeners) { 883 listeners = new ConnectionEstablishedListener[connectionEstablishedListeners.size()]; 884 connectionEstablishedListeners.toArray(listeners); 885 } 886 for (int i = 0; i < listeners.length; i++) { 887 listeners[i].connectionEstablished(connection); 888 } 889 } 890 891 894 895 901 public boolean isUsingTLS() { 902 return usingTLS; 903 } 904 905 912 public SASLAuthentication getSASLAuthentication() { 913 return saslAuthentication; 914 } 915 916 920 void startTLSReceived() { 921 try { 922 writer.write("<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>"); 923 writer.flush(); 924 } catch (IOException e) { 925 packetReader.notifyConnectionError(e); 926 } 927 } 928 929 934 void proceedTLSReceived() { 935 try { 936 SSLContext context = SSLContext.getInstance("TLS"); 937 context.init(null, new javax.net.ssl.TrustManager[] { new OpenTrustManager() }, 940 new java.security.SecureRandom ()); 941 Socket plain = socket; 942 socket = context.getSocketFactory().createSocket(plain, 944 plain.getInetAddress().getHostName(), plain.getPort(), true); 945 socket.setSoTimeout(0); 946 socket.setKeepAlive(true); 947 initReaderAndWriter(); 949 ((SSLSocket)socket).startHandshake(); 951 952 usingTLS = true; 954 955 packetWriter.setWriter(writer); 957 packetWriter.openStream(); 959 } 960 catch (Exception e) { 961 packetReader.notifyConnectionError(e); 962 } 963 } 964 965 } | Popular Tags |