我正在尝试执行https://developers.google.com/cloud-print/docs/rawxmpp中提到的XMPP握手流程。

这使设备可以订阅和接收通知。

到目前为止,我已经探索了以下选项:

1)libcurl
2)Gloox C / C ++
3)TXMPP
4)利比灵

首先选择哪个选项是一个不错的选择?我想将对库的支持和维护视为主要因素。

最佳答案

以下是我使用Gloox C / C ++库执行XMPP握手流程的解决方案:

#include <cassert>
#include <iostream>
#include <boost/make_shared.hpp>
#include <iq.h>
#include <parser.h>
#include <base64.h>
#include <connectiontcpclient.h>
#include <connectiontls.h>
#include <connectiondatahandler.h>
#include <connectionhttpproxy.h>
#include <logsink.h>
#include <client.h>
#include <connectionsocks5proxy.h>

using namespace gloox;
using namespace std;

const string proxyHost = ""; //specify proxy server name
const int proxyPort = 0; //specify proxy port number
const string xmppHost = "talk.google.com";
const int xmppPort = 5222;

Client *c;
ConnectionBase *client_ ;
ConnectionTCPClient* conn0;
ConnectionHTTPProxy* conn2;

class Bot: public ConnectionDataHandler, TagHandler, TLSHandler{
public:
    Bot(): parser_(this)
    {
         conn0 = new ConnectionTCPClient(this, log_, proxyHost, proxyPort);
         ConnectionHTTPProxy* conn2 = new ConnectionHTTPProxy( this, conn0, log_, xmppHost, xmppPort);
         client_ = conn0;
         ConnectionError ce = ConnNoError;
         ce = conn2->connect();
         assert(ce == ConnNoError);
         conn2->receive();
    }
    virtual void handleConnect(const ConnectionBase* con) {
        send("<stream:stream to=\"gmail.com\" xml:lang=\"en\" version=\"1.0\" xmlns:stream=\"http://etherx.jabber.org/streams\" xmlns=\"jabber:client\">\r\n");
    }

    virtual void handleReceivedData(const ConnectionBase* con, const string& data) {
        cerr << "[recv] " << data << endl;
        string copied = data;
        int pos = parser_.feed(copied);
        assert(pos < 0);
    }

    virtual void handleTag(Tag* tag) {
        if (tag->name() == "stream" && tag->xmlns() == "http://etherx.jabber.org/streams") {
            sid_ = tag->findAttribute("id");
        } else{
            if (tag->name() == "features") {
                if (tag->hasChild("starttls", "xmlns", "urn:ietf:params:xml:ns:xmpp-tls")) {
                    send(Tag("starttls", "xmlns", "urn:ietf:params:xml:ns:xmpp-tls").xml());
                }
                else if (tag->hasChild("mechanisms", "xmlns", "urn:ietf:params:xml:ns:xmpp-sasl") && tag->findChild("mechanisms")->hasChildWithCData(
                                "mechanism", "X-OAUTH2"))
                {
                    Tag a("auth", "xmlns", "urn:ietf:params:xml:ns:xmpp-sasl");
                    a.addAttribute("mechanism", "X-OAUTH2");
                    a.addAttribute("service", "chromiumsync");
                    a.addAttribute("allow-generated-jid", "true");
                    a.addAttribute("client-uses-full-bind-result", "true");
                    a.addAttribute("auth", "http://www.google.com/talk/protocol/auth");
                    string credential;
                    credential.append("\0", 1);
                    credential.append(""); //Specify Bare JID
                    credential.append("\0", 1);
                    credential.append("");  //Specify Access Token
                    a.setCData(Base64::encode64(credential));
                    send(a.xml());
                }
                else if (tag->hasChild("bind", "xmlns", "urn:ietf:params:xml:ns:xmpp-bind")) {
                    Tag iq("iq", "xmlns", "jabber:client");
                    iq.addAttribute("type", "set");
                    iq.addAttribute("id", "0");
                    Tag *bind = new Tag("bind", "xmlns", "urn:ietf:params:xml:ns:xmpp-bind");
                    Tag *resource = new Tag("resource");
                    resource->setCData("GCPResource");
                    bind->addChild(resource);
                    iq.addChild(bind);
                    send(iq.xml());
                }
            }
            else if (tag->name() == "proceed" && tag->xmlns() == "urn:ietf:params:xml:ns:xmpp-tls") {
                ConnectionTLS* encryption_client = new ConnectionTLS(this, conn0, log_);
                encryption_client->registerTLSHandler(this);
                client_ = encryption_client;
                ConnectionError ret = encryption_client->connect();
                assert(ret == ConnNoError);
            }
            else if (tag->name() == "success" && tag->xmlns() == "urn:ietf:params:xml:ns:xmpp-sasl") {
                send("<stream:stream to=\"gmail.com\" xml:lang=\"en\" version=\"1.0\" xmlns:stream=\"http://etherx.jabber.org/streams\" xmlns=\"jabber:client\">\r\n");
            }
            else if (tag->name() == "iq") {
                if (tag->hasChild("bind", "xmlns", "urn:ietf:params:xml:ns:xmpp-bind")) {
                    resource_ = tag->findChild("bind")->findChild("jid")->cdata();
                    Tag iq("iq");
                    iq.addAttribute("type", "set");
                    iq.addAttribute("id", "1");
                    iq.addChild(new Tag("session", "xmlns", "urn:ietf:params:xml:ns:xmpp-session"));
                    send(iq.xml());

                    //Step 2: Subscribing for notifications
                    if (tag->hasAttribute("type", "result")) {
                        Tag iq("iq");
                        iq.addAttribute("type", "set");
                        iq.addAttribute("to", ""); //Specify Bare JID
                        iq.addAttribute("id", "3");
                        Tag *bind = new Tag("subscribe", "xmlns", "google:push");
                        Tag *resource = new Tag("item");
                        resource->addAttribute("channel", "cloudprint.google.com");
                        resource->addAttribute("from", "cloudprint.google.com");
                        bind->addChild(resource);
                        iq.addChild(bind);
                        send(iq.xml());
                    }
                }
            }
        }
    }

    virtual void handleEncryptedData(const TLSBase* tls,
            const string& data) {
        cout << "handleEncryptedData" << endl;
    }

    virtual void handleDecryptedData(const TLSBase* tls,
            const string& data) {
        cout << "handleDecryptedData" << endl;
    }

    virtual void handleHandshakeResult(const TLSBase* tls, bool,
            CertInfo& cert) {
        cout << "handleHandshakeResult" << endl;
    }

    virtual void handleDisconnect(const ConnectionBase* con, ConnectionError) {
        cout << "handleDisconnect" << endl;
    }

private:
    LogSink log_;
    string sid_;
    string resource_;
    Parser parser_;
    ConnectionBase *client_;

    void send(const string &data) {
        cerr << "[send] " << data << endl;
        client_->send(data);
    }

};

int main() {
        Bot bot;
}

关于c++ - 使用Gloox C/C++的XMPP握手流程,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31487427/

10-11 22:01