private void switchOverToZLib(Tag currentTag)
      throws XmlPullParserException, IOException, NoSuchAlgorithmException {
    tagReader.readTag(); // read tag close

    tagWriter.setOutputStream(new ZLibOutputStream(tagWriter.getOutputStream()));
    tagReader.setInputStream(new ZLibInputStream(tagReader.getInputStream()));

    sendStartStream();
    Log.d(LOGTAG, account.getJid() + ": compression enabled");
    processStream(tagReader.readTag());
  }
 private void sendSaslAuthPlain() throws IOException {
   String saslString = CryptoHelper.saslPlain(account.getUsername(), account.getPassword());
   Element auth = new Element("auth");
   auth.setAttribute("xmlns", "urn:ietf:params:xml:ns:xmpp-sasl");
   auth.setAttribute("mechanism", "PLAIN");
   auth.setContent(saslString);
   tagWriter.writeElement(auth);
 }
 public void sendPing() {
   if (streamFeatures.hasChild("sm")) {
     tagWriter.writeStanzaAsync(new RequestPacket(smVersion));
   } else {
     IqPacket iq = new IqPacket(IqPacket.TYPE_GET);
     iq.setFrom(account.getFullJid());
     iq.addChild("ping", "urn:xmpp:ping");
     this.sendIqPacket(iq, null);
   }
 }
 private void sendStartStream() throws IOException {
   Tag stream = Tag.start("stream:stream");
   stream.setAttribute("from", account.getJid());
   stream.setAttribute("to", account.getServer());
   stream.setAttribute("version", "1.0");
   stream.setAttribute("xml:lang", "en");
   stream.setAttribute("xmlns", "jabber:client");
   stream.setAttribute("xmlns:stream", "http://etherx.jabber.org/streams");
   tagWriter.writeTag(stream);
 }
 private synchronized void sendPacket(final AbstractStanza packet, PacketReceived callback) {
   // TODO dont increment stanza count if packet = request packet or ack;
   ++stanzasSent;
   tagWriter.writeStanzaAsync(packet);
   if (callback != null) {
     if (packet.getId() == null) {
       packet.setId(nextRandomId());
     }
     packetCallbacks.put(packet.getId(), callback);
   }
 }
 public void disconnect(boolean force) {
   changeStatus(Account.STATUS_OFFLINE);
   Log.d(LOGTAG, "disconnecting");
   try {
     if (force) {
       socket.close();
       return;
     }
     if (tagWriter.isActive()) {
       tagWriter.finish();
       while (!tagWriter.finished()) {
         // Log.d(LOGTAG,"not yet finished");
         Thread.sleep(100);
       }
       tagWriter.writeTag(Tag.end("stream:stream"));
     }
   } catch (IOException e) {
     Log.d(LOGTAG, "io exception during disconnect");
   } catch (InterruptedException e) {
     Log.d(LOGTAG, "interupted while waiting for disconnect");
   }
 }
 private void sendSaslAuthDigestMd5() throws IOException {
   Element auth = new Element("auth");
   auth.setAttribute("xmlns", "urn:ietf:params:xml:ns:xmpp-sasl");
   auth.setAttribute("mechanism", "DIGEST-MD5");
   tagWriter.writeElement(auth);
 }
  private void switchOverToTls(Tag currentTag) throws XmlPullParserException, IOException {
    Tag nextTag = tagReader.readTag(); // should be proceed end tag
    try {
      SSLContext sc = SSLContext.getInstance("TLS");
      TrustManagerFactory tmf =
          TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
      // Initialise the TMF as you normally would, for example:
      // tmf.in
      try {
        tmf.init((KeyStore) null);
      } catch (KeyStoreException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
      }

      TrustManager[] trustManagers = tmf.getTrustManagers();
      final X509TrustManager origTrustmanager = (X509TrustManager) trustManagers[0];

      TrustManager[] wrappedTrustManagers =
          new TrustManager[] {
            new X509TrustManager() {

              @Override
              public void checkClientTrusted(X509Certificate[] chain, String authType)
                  throws CertificateException {
                origTrustmanager.checkClientTrusted(chain, authType);
              }

              @Override
              public void checkServerTrusted(X509Certificate[] chain, String authType)
                  throws CertificateException {
                try {
                  origTrustmanager.checkServerTrusted(chain, authType);
                } catch (CertificateException e) {
                  if (e.getCause() instanceof CertPathValidatorException) {
                    String sha;
                    try {
                      MessageDigest sha1 = MessageDigest.getInstance("SHA1");
                      sha1.update(chain[0].getEncoded());
                      sha = CryptoHelper.bytesToHex(sha1.digest());
                      if (!sha.equals(account.getSSLFingerprint())) {
                        changeStatus(Account.STATUS_TLS_ERROR);
                        if (tlsListener != null) {
                          tlsListener.onTLSExceptionReceived(sha, account);
                        }
                        throw new CertificateException();
                      }
                    } catch (NoSuchAlgorithmException e1) {
                      // TODO Auto-generated catch block
                      e1.printStackTrace();
                    }
                  } else {
                    throw new CertificateException();
                  }
                }
              }

              @Override
              public X509Certificate[] getAcceptedIssuers() {
                return origTrustmanager.getAcceptedIssuers();
              }
            }
          };
      sc.init(null, wrappedTrustManagers, null);
      SSLSocketFactory factory = sc.getSocketFactory();
      SSLSocket sslSocket =
          (SSLSocket)
              factory.createSocket(
                  socket, socket.getInetAddress().getHostAddress(), socket.getPort(), true);
      tagReader.setInputStream(sslSocket.getInputStream());
      tagWriter.setOutputStream(sslSocket.getOutputStream());
      sendStartStream();
      Log.d(LOGTAG, account.getJid() + ": TLS connection established");
      processStream(tagReader.readTag());
      sslSocket.close();
    } catch (NoSuchAlgorithmException e1) {
      // TODO Auto-generated catch block
      e1.printStackTrace();
    } catch (KeyManagementException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
 private void sendStartTLS() throws IOException {
   Tag startTLS = Tag.empty("starttls");
   startTLS.setAttribute("xmlns", "urn:ietf:params:xml:ns:xmpp-tls");
   tagWriter.writeTag(startTLS);
 }
 private void sendCompressionZlib() throws IOException {
   Element compress = new Element("compress");
   compress.setAttribute("xmlns", "http://jabber.org/protocol/compress");
   compress.addChild("method").setContent("zlib");
   tagWriter.writeElement(compress);
 }
 private void processStream(Tag currentTag)
     throws XmlPullParserException, IOException, NoSuchAlgorithmException {
   Tag nextTag = tagReader.readTag();
   while ((nextTag != null) && (!nextTag.isEnd("stream"))) {
     if (nextTag.isStart("error")) {
       processStreamError(nextTag);
     } else if (nextTag.isStart("features")) {
       processStreamFeatures(nextTag);
       if ((streamFeatures.getChildren().size() == 1)
           && (streamFeatures.hasChild("starttls"))
           && (!account.isOptionSet(Account.OPTION_USETLS))) {
         changeStatus(Account.STATUS_SERVER_REQUIRES_TLS);
       }
     } else if (nextTag.isStart("proceed")) {
       switchOverToTls(nextTag);
     } else if (nextTag.isStart("compressed")) {
       switchOverToZLib(nextTag);
     } else if (nextTag.isStart("success")) {
       Log.d(LOGTAG, account.getJid() + ": logged in");
       tagReader.readTag();
       tagReader.reset();
       sendStartStream();
       processStream(tagReader.readTag());
       break;
     } else if (nextTag.isStart("failure")) {
       Element failure = tagReader.readElement(nextTag);
       changeStatus(Account.STATUS_UNAUTHORIZED);
     } else if (nextTag.isStart("challenge")) {
       String challange = tagReader.readElement(nextTag).getContent();
       Element response = new Element("response");
       response.setAttribute("xmlns", "urn:ietf:params:xml:ns:xmpp-sasl");
       response.setContent(CryptoHelper.saslDigestMd5(account, challange));
       tagWriter.writeElement(response);
     } else if (nextTag.isStart("enabled")) {
       this.stanzasSent = 0;
       Element enabled = tagReader.readElement(nextTag);
       if ("true".equals(enabled.getAttribute("resume"))) {
         this.streamId = enabled.getAttribute("id");
         Log.d(
             LOGTAG,
             account.getJid() + ": stream managment(" + smVersion + ") enabled (resumable)");
       } else {
         Log.d(LOGTAG, account.getJid() + ": stream managment(" + smVersion + ") enabled");
       }
       this.lastSessionStarted = SystemClock.elapsedRealtime();
       this.stanzasReceived = 0;
       RequestPacket r = new RequestPacket(smVersion);
       tagWriter.writeStanzaAsync(r);
     } else if (nextTag.isStart("resumed")) {
       tagReader.readElement(nextTag);
       sendPing();
       changeStatus(Account.STATUS_ONLINE);
       Log.d(LOGTAG, account.getJid() + ": session resumed");
     } else if (nextTag.isStart("r")) {
       tagReader.readElement(nextTag);
       AckPacket ack = new AckPacket(this.stanzasReceived, smVersion);
       // Log.d(LOGTAG,ack.toString());
       tagWriter.writeStanzaAsync(ack);
     } else if (nextTag.isStart("a")) {
       Element ack = tagReader.readElement(nextTag);
       lastPaketReceived = SystemClock.elapsedRealtime();
       int serverSequence = Integer.parseInt(ack.getAttribute("h"));
       if (serverSequence > this.stanzasSent) {
         this.stanzasSent = serverSequence;
       }
       // Log.d(LOGTAG,"server ack"+ack.toString()+" ("+this.stanzasSent+")");
     } else if (nextTag.isStart("failed")) {
       tagReader.readElement(nextTag);
       Log.d(LOGTAG, account.getJid() + ": resumption failed");
       streamId = null;
       if (account.getStatus() != Account.STATUS_ONLINE) {
         sendBindRequest();
       }
     } else if (nextTag.isStart("iq")) {
       processIq(nextTag);
     } else if (nextTag.isStart("message")) {
       processMessage(nextTag);
     } else if (nextTag.isStart("presence")) {
       processPresence(nextTag);
     } else {
       Log.d(
           LOGTAG,
           "found unexpected tag: " + nextTag.getName() + " as child of " + currentTag.getName());
     }
     nextTag = tagReader.readTag();
   }
   if (account.getStatus() == Account.STATUS_ONLINE) {
     account.setStatus(Account.STATUS_OFFLINE);
     if (statusListener != null) {
       statusListener.onStatusChanged(account);
     }
   }
 }
 protected void connect() {
   Log.d(LOGTAG, account.getJid() + ": connecting");
   lastConnect = SystemClock.elapsedRealtime();
   try {
     shouldAuthenticate = shouldBind = !account.isOptionSet(Account.OPTION_REGISTER);
     tagReader = new XmlReader(wakeLock);
     tagWriter = new TagWriter();
     packetCallbacks.clear();
     this.changeStatus(Account.STATUS_CONNECTING);
     Bundle namePort = DNSHelper.getSRVRecord(account.getServer());
     if ("timeout".equals(namePort.getString("error"))) {
       Log.d(LOGTAG, account.getJid() + ": dns timeout");
       this.changeStatus(Account.STATUS_OFFLINE);
       return;
     }
     String srvRecordServer = namePort.getString("name");
     String srvIpServer = namePort.getString("ipv4");
     int srvRecordPort = namePort.getInt("port");
     if (srvRecordServer != null) {
       if (srvIpServer != null) {
         Log.d(
             LOGTAG,
             account.getJid()
                 + ": using values from dns "
                 + srvRecordServer
                 + "["
                 + srvIpServer
                 + "]:"
                 + srvRecordPort);
         socket = new Socket(srvIpServer, srvRecordPort);
       } else {
         Log.d(
             LOGTAG,
             account.getJid()
                 + ": using values from dns "
                 + srvRecordServer
                 + ":"
                 + srvRecordPort);
         socket = new Socket(srvRecordServer, srvRecordPort);
       }
     } else {
       socket = new Socket(account.getServer(), 5222);
     }
     OutputStream out = socket.getOutputStream();
     tagWriter.setOutputStream(out);
     InputStream in = socket.getInputStream();
     tagReader.setInputStream(in);
     tagWriter.beginDocument();
     sendStartStream();
     Tag nextTag;
     while ((nextTag = tagReader.readTag()) != null) {
       if (nextTag.isStart("stream")) {
         processStream(nextTag);
         break;
       } else {
         Log.d(LOGTAG, "found unexpected tag: " + nextTag.getName());
         return;
       }
     }
     if (socket.isConnected()) {
       socket.close();
     }
   } catch (UnknownHostException e) {
     this.changeStatus(Account.STATUS_SERVER_NOT_FOUND);
     if (wakeLock.isHeld()) {
       wakeLock.release();
     }
     return;
   } catch (IOException e) {
     if (account.getStatus() != Account.STATUS_TLS_ERROR) {
       this.changeStatus(Account.STATUS_OFFLINE);
     }
     if (wakeLock.isHeld()) {
       wakeLock.release();
     }
     return;
   } catch (NoSuchAlgorithmException e) {
     this.changeStatus(Account.STATUS_OFFLINE);
     Log.d(LOGTAG, "compression exception " + e.getMessage());
     if (wakeLock.isHeld()) {
       wakeLock.release();
     }
     return;
   } catch (XmlPullParserException e) {
     this.changeStatus(Account.STATUS_OFFLINE);
     Log.d(LOGTAG, "xml exception " + e.getMessage());
     if (wakeLock.isHeld()) {
       wakeLock.release();
     }
     return;
   }
 }