Search in sources :

Example 1 with XmppMalformedException

use of com.googlecode.asmack.XmppMalformedException in project AsmackService by rtreffer.

the class RosterResultReceiver method onReceive.

/**
     * Receive a stanza intent, check for roster entries and write results to
     * the result queue.
     */
public void onReceive(Context context, Intent intent) {
    Stanza stanza = intent.getParcelableExtra("stanza");
    if (stanza.getName() == null || stanza.getVia() == null || stanza.getAttribute("type") == null) {
        return;
    }
    if (!"iq".equals(stanza.getName())) {
        return;
    }
    if (!stanza.getVia().startsWith(account.name + "/")) {
        return;
    }
    if (!"result".equals(stanza.getAttribute("type").getValue())) {
        return;
    }
    try {
        Node node = stanza.getDocumentNode();
        Node roster = XMLUtils.getFirstChild(node, "jabber:iq:roster", "query");
        if (roster == null) {
            return;
        }
        rosterQueue.put(roster);
    } catch (XmppMalformedException e) {
        Log.w(TAG, "PLEASE REPORT", e);
    } catch (InterruptedException e) {
        Log.w(TAG, "PLEASE REPORT", e);
    }
}
Also used : XmppMalformedException(com.googlecode.asmack.XmppMalformedException) Stanza(com.googlecode.asmack.Stanza) Node(org.w3c.dom.Node)

Example 2 with XmppMalformedException

use of com.googlecode.asmack.XmppMalformedException in project AsmackService by rtreffer.

the class DiscoReceiver method onReceive.

/**
     * Called on incoming stanzas and replies on service discovery requests.
     * @param context The current context.
     * @param intent The stanza intent.
     */
@Override
public void onReceive(Context context, Intent intent) {
    Stanza stanza = intent.getParcelableExtra("stanza");
    // only accept IQ stanzas
    if (!"iq".equals(stanza.getName())) {
        return;
    }
    // of type="get"
    if (!"get".equals(stanza.getAttributeValue("type"))) {
        return;
    }
    // from / to / id are mandatory
    Attribute from = stanza.getAttribute("from");
    Attribute to = stanza.getAttribute("to");
    Attribute id = stanza.getAttribute("id");
    if (id == null || from == null || to == null) {
        return;
    }
    try {
        Node node = stanza.getDocumentNode();
        Node query = XMLUtils.getFirstChild(node, "http://jabber.org/protocol/disco#info", "query");
        if (query == null || !query.hasAttributes()) {
            return;
        }
        Node discoAttributeNode = query.getAttributes().getNamedItem("node");
        String discoNode = null;
        if (discoAttributeNode != null) {
            discoNode = discoAttributeNode.getTextContent();
        }
        // we got a disco, reply
        StringBuilder payload = new StringBuilder("<iq type='result'");
        payload.append(" from='");
        payload.append(XMLUtils.xmlEscape(to.getValue()));
        payload.append("' to='");
        payload.append(XMLUtils.xmlEscape(from.getValue()));
        payload.append("'>");
        payload.append("<query xmlns='");
        payload.append("http://jabber.org/protocol/disco#info");
        if (discoNode != null) {
            payload.append("' node='");
            payload.append(XMLUtils.xmlEscape(discoNode));
        }
        payload.append("'>");
        String myJid = XMPPUtils.getBareJid(to.getValue());
        for (XmppIdentity identity : Database.getIdentities(context, myJid, null)) {
            payload.append("<identity");
            if (identity.getCategory().length() > 0) {
                payload.append(" category='");
                payload.append(XMLUtils.xmlEscape(identity.getCategory()));
                payload.append('\'');
            }
            if (identity.getType().length() > 0) {
                payload.append(" type='");
                payload.append(XMLUtils.xmlEscape(identity.getType()));
                payload.append('\'');
            }
            if (identity.getLang().length() > 0) {
                payload.append(" lang='");
                payload.append(XMLUtils.xmlEscape(identity.getLang()));
                payload.append('\'');
            }
            if (identity.getName().length() > 0) {
                payload.append(" name='");
                payload.append(XMLUtils.xmlEscape(identity.getName()));
                payload.append('\'');
            }
            payload.append("/>");
        }
        for (String feature : Database.getFeatures(context, myJid, null)) {
            payload.append("<feature var='");
            payload.append(XMLUtils.xmlEscape(feature));
            payload.append("'/>");
        }
        payload.append("</query></iq>");
        Stanza discoReply = new Stanza("iq", "", XMPPUtils.getBareJid(to.getValue()), payload.toString(), Arrays.asList(new Attribute[] { id }));
        intent = new Intent();
        intent.setAction(XmppTransportService.XMPP_STANZA_SEND_INTENT);
        intent.putExtra("stanza", discoReply);
        intent.addFlags(Intent.FLAG_FROM_BACKGROUND);
        context.sendBroadcast(intent, XmppTransportService.XMPP_STANZA_SEND_INTENT);
    } catch (XmppMalformedException e) {
        // Impossible
        Log.e("AsmackService", "Please report (impossible condition)", e);
    }
}
Also used : XmppMalformedException(com.googlecode.asmack.XmppMalformedException) Attribute(com.googlecode.asmack.Attribute) XmppIdentity(com.googlecode.asmack.XmppIdentity) Stanza(com.googlecode.asmack.Stanza) Node(org.w3c.dom.Node) Intent(android.content.Intent)

Example 3 with XmppMalformedException

use of com.googlecode.asmack.XmppMalformedException in project AsmackService by rtreffer.

the class FeatureNegotiationEngine method open.

/*
     * From RFC 3920-bis-13#page-26
     * 4.2.7. Flow Chart
     * 
     *                         +------------+
     *                         |  open TCP  |
     *                         | connection |
     *                         +------------+
     *                               |
     *                               | <------------ open() starts here
     *                               |
     *                               v
     *                        +---------------+
     *                        | send initial  |<-------------------------+
     *                        | stream header |                          ^
     *                        +---------------+                          |
     *                               |                                   |
     *                               v                                   |
     *                       +------------------+                        |
     *                       | receive response |                        |
     *                       | stream header    |                        |
     *                       +------------------+                        |
     *                               |                                   |
     *                               v                                   |
     *                        +----------------+                         |
     *                        | receive stream |                         |
     *    +------------------>| features       |                         |
     *    ^                   +----------------+                         |
     *    |                          |                                   |
     *    |                          v                                   |
     *    |       +<-----------------+                                   |
     *    |       |                                                      |
     *    |    {empty?} ----> {all voluntary?} ----> {some mandatory?}   |
     *    |       |      no          |          no         |             |
     *    |       | yes              | yes                 | yes         |
     *    |       |                  v                     v             |
     *    |       |           +---------------+    +----------------+    |
     *    |       |           | MAY negotiate |    | MUST negotiate |    |
     *    |       |           | any or none   |    | one feature    |    |
     *    |       |           +---------------+    +----------------+    |
     *    |       |                  |                     |             |
     *    |       v                  v                     |             |
     *    |   +----------+      +-----------+              |             |
     *    |   | process  |<-----| negotiate |              |             |
     *    |   | complete |  no  | a feature |              |             |
     *    |   +----------+      +-----------+              |             |
     *    |                          |                     |             |
     *    |                     yes  |                     |             |
     *    |                          v                     v             |
     *    |                          +--------->+<---------+             |
     *    |                                     |                        |
     *    |                                     v                        |
     *    +<-------------------------- {restart mandatory?} ------------>+
     *                   no                                     yes
     * 
     * The "open" method starts directly after opening the TCP streams,
     * negotiates the connection and returns true if the xmpp stream is ready
     * for a bind.
     * 
     * The usual way to bind is
     * if (streamEngine.open(account)) {
     *     String resource = streamEngine.bind(account.getResource);
     * }
     * 
     * Interresting and available features that require restarts:
     * - SASL
     * - TLS
     * - Compression
     */
/**
     * <p>Open a connection for a given account. This will run the full
     * negotiation with the following precedence:
     * <ol>
     *     <li>TLS (if available)</li>
     *     <li>Compression (if available)</li>
     *     <li>SASL</li>
     * <ol></p>
     *
     * <p><b>Note:</b> Servers should not offer compression befor SASL is
     * completed. This is not violated by the rule, mobile devices love xml
     * compression, thus a higher preference. Everything will work as expected
     * when compression is offered after SASL.</p>
     *
     * <p>This method requires a call to bind (if you wish to bind) afterwards.
     * </p>
     * 
     * @param account XmppAccount The account used for negotiation.
     * @throws XmppException In case of an error.
     */
public void open(XmppAccount account) throws XmppException {
    boolean rerun = true;
    boolean canBind = false;
    while (rerun) {
        try {
            rerun = false;
            xmppOutput.open(XMPPUtils.getDomain(account.getJid()), null);
            xmppInput.readOpening();
            Node features = null;
            do {
                Node stanza = xmppInput.nextStanza().getDocumentNode();
                if (XMLUtils.isInstance(stanza, "http://etherx.jabber.org/streams", "features")) {
                    features = stanza;
                }
            } while (features == null);
            // check basic stream features
            rosterVersioningSupported |= XMLUtils.hasChild(features, "urn:xmpp:features:rosterver", "ver");
            sessionsSupported |= XMLUtils.hasChild(features, "urn:ietf:params:xml:ns:xmpp-session", "session");
            canBind |= XMLUtils.hasChild(features, "urn:ietf:params:xml:ns:xmpp-bind", "bind");
            hasTLS = XMLUtils.hasChild(features, "urn:ietf:params:xml:ns:xmpp-tls", "starttls");
            Node compression = XMLUtils.getFirstChild(features, "http://jabber.org/features/compress", "compression");
            if (compression != null) {
                NodeList methods = compression.getChildNodes();
                for (int i = 0, l = methods.getLength(); i < l; i++) {
                    Node method = methods.item(i);
                    if (method.getNodeType() != Node.ELEMENT_NODE) {
                        continue;
                    }
                    if (!"method".equals(method.getNodeName())) {
                        continue;
                    }
                    String methodName = method.getFirstChild().getNodeValue();
                    methodName = methodName.trim();
                    compressionSupported |= "zlib".equals(methodName);
                }
            }
            Node saslMechanisms = XMLUtils.getFirstChild(features, "urn:ietf:params:xml:ns:xmpp-sasl", "mechanisms");
            SASLSupported |= saslMechanisms != null;
            if (hasTLS && !secure) {
                // enable tls
                xmppOutput.sendUnchecked("<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>");
                boolean startTLS = XMLUtils.isInstance(xmppInput.nextStanza().getDocumentNode(), "urn:ietf:params:xml:ns:xmpp-tls", "proceed");
                if (startTLS) {
                    startTLS();
                    secure = true;
                    rerun = true;
                    continue;
                }
            }
            if (compressionSupported && !compressed && ZLibOutputStream.SUPPORTED) {
                startCompress();
                rerun = true;
                continue;
            }
            if (SASLSupported && !authenticated) {
                if (saslLogin(saslMechanisms, account)) {
                    authenticated = true;
                    rerun = true;
                    continue;
                }
            }
        } catch (IllegalArgumentException e) {
            throw new XmppMalformedException("Can't negotiate features", e);
        } catch (IllegalStateException e) {
            throw new XmppMalformedException("Can't negotiate features", e);
        } catch (IOException e) {
            throw new XmppTransportException("Can't negotiate features", e);
        } catch (XmlPullParserException e) {
            throw new XmppMalformedException("Can't negotiate features", e);
        } catch (NoSuchAlgorithmException e) {
            // Should never happen - TLS not available?
            throw new XmppTransportException("Can't enable tls", e);
        } catch (KeyManagementException e) {
            throw new XmppTransportException("Can't trust server", e);
        }
    }
    if (!canBind) {
        throw new XmppTransportException("Couldn't reach bind state.");
    }
}
Also used : Node(org.w3c.dom.Node) NodeList(org.w3c.dom.NodeList) XmppTransportException(com.googlecode.asmack.connection.XmppTransportException) IOException(java.io.IOException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) KeyManagementException(java.security.KeyManagementException) XmppMalformedException(com.googlecode.asmack.XmppMalformedException) XmlPullParserException(org.xmlpull.v1.XmlPullParserException)

Example 4 with XmppMalformedException

use of com.googlecode.asmack.XmppMalformedException in project AsmackService by rtreffer.

the class FeatureNegotiationEngine method saslLogin.

/**
     * Run a sasl based login. Most sals parts are handled by
     * {@link SASLEngine#login(XmppInputStream, XmppOutputStream, java.util.Set, XmppAccount)}.
     * @param saslMechanisms Node The DOM node of the sasl mechanisms.
     * @param account XmppAccount The xmpp account to use.
     * @return boolean True on success. False on failore.
     * @throws XmppException On critical connection errors-
     */
protected boolean saslLogin(Node saslMechanisms, XmppAccount account) throws XmppException {
    NodeList nodes = saslMechanisms.getChildNodes();
    HashSet<String> methods = new HashSet<String>(13);
    for (int i = 0, l = nodes.getLength(); i < l; i++) {
        Node node = nodes.item(i);
        if (!XMLUtils.isInstance(node, null, "mechanism")) {
            continue;
        }
        methods.add(node.getFirstChild().getNodeValue().toUpperCase().trim());
    }
    if (SASLEngine.login(xmppInput, xmppOutput, methods, account)) {
        xmppInput.detach();
        try {
            xmppOutput.detach();
            xmppInput.attach(inputStream);
            xmppOutput.attach(outputStream, true, false);
        } catch (IllegalArgumentException e) {
            throw new XmppMalformedException("Please report", e);
        } catch (IllegalStateException e) {
            throw new XmppMalformedException("Please report", e);
        } catch (IOException e) {
            throw new XmppTransportException("Couldn't restart connection", e);
        }
        return true;
    }
    return false;
}
Also used : XmppMalformedException(com.googlecode.asmack.XmppMalformedException) NodeList(org.w3c.dom.NodeList) Node(org.w3c.dom.Node) XmppTransportException(com.googlecode.asmack.connection.XmppTransportException) IOException(java.io.IOException) HashSet(java.util.HashSet)

Example 5 with XmppMalformedException

use of com.googlecode.asmack.XmppMalformedException in project AsmackService by rtreffer.

the class FeatureNegotiationEngine method bind.

/**
     * Bind a given resource, probably resuming an old session.
     * @param resource String The preferred resource string.
     * @return String The actual resource string.
     * @throws XmppException On Error.
     */
public String bind(String resource) throws XmppException {
    try {
        if (!TextUtils.isEmpty(resource)) {
            xmppOutput.sendUnchecked("<iq type=\"set\" id=\"bind_1\">" + "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\">" + "<resource>" + resource + "</resource>" + "</bind>" + "</iq>");
        } else {
            xmppOutput.sendUnchecked("<iq type=\"set\" id=\"bind_1\">" + "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\">" + "</bind>" + "</iq>");
        }
        Stanza stanza = xmppInput.nextStanza();
        Node node = XMLUtils.getDocumentNode(stanza.getXml());
        Node bind = XMLUtils.getFirstChild(node, "urn:ietf:params:xml:ns:xmpp-bind", "bind");
        Node jid = XMLUtils.getFirstChild(bind, null, "jid");
        if (sessionsSupported) {
            startSession();
        }
        return jid.getTextContent();
    } catch (IllegalArgumentException e) {
        throw new XmppMalformedException("bind malformed", e);
    } catch (IllegalStateException e) {
        throw new XmppMalformedException("bind malformed", e);
    } catch (SAXException e) {
        throw new XmppMalformedException("bind malformed", e);
    }
}
Also used : XmppMalformedException(com.googlecode.asmack.XmppMalformedException) Stanza(com.googlecode.asmack.Stanza) Node(org.w3c.dom.Node) SAXException(org.xml.sax.SAXException)

Aggregations

XmppMalformedException (com.googlecode.asmack.XmppMalformedException)8 Node (org.w3c.dom.Node)6 Stanza (com.googlecode.asmack.Stanza)5 XmppTransportException (com.googlecode.asmack.connection.XmppTransportException)4 IOException (java.io.IOException)4 XmlPullParserException (org.xmlpull.v1.XmlPullParserException)3 NodeList (org.w3c.dom.NodeList)2 Intent (android.content.Intent)1 Attribute (com.googlecode.asmack.Attribute)1 XmppIdentity (com.googlecode.asmack.XmppIdentity)1 KeyManagementException (java.security.KeyManagementException)1 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)1 HashSet (java.util.HashSet)1 SocketFactory (javax.net.SocketFactory)1 SAXException (org.xml.sax.SAXException)1