IT戦記

プログラミング、起業などについて書いているプログラマーのブログです😚

XMPP ライブラリ Gloox のトランスポート層を触る(1)

一日一回 XMPP 勉強中

とりあえず、 TLS のコネクション貼るところまでできた

#include <cassert>
#include <iostream>
#include <boost/make_shared.hpp>
#include <gloox/parser.h>
#include <gloox/connectiontcpclient.h>
#include <gloox/connectiontls.h>

class Bot : public gloox::ConnectionDataHandler, gloox::TagHandler, gloox::TLSHandler
{
public:
    Bot() :
        client_(new gloox::ConnectionTCPClient(this, log_, "talk.google.com", 5222)),
        raw_client_(client_),
        parser_(this)
    {
        gloox::ConnectionError ret = client_->connect();

        assert(ret == gloox::ConnNoError);

        client_->receive();
    }

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

        assert(pos < 0);
    }

    virtual void handleConnect(const gloox::ConnectionBase* con)
    {
        client_->send(
            "<?xml version='1.0' ?>"
            "<stream:stream "
                "xmlns:stream=\"http://etherx.jabber.org/streams\" "
                "version=\"1.0\" xmlns=\"jabber:client\" "
                "to=\"gmail.com\" "
                "xml:lang=\"en\" "
                "xmlns:xml=\"http://www.w3.org/XML/1998/namespace\" >");
    }

    virtual void handleTag(gloox::Tag* tag)
    {
        if (tag->name() == "stream" && tag->xmlns() == "http://etherx.jabber.org/streams") {
            sid_ = tag->findAttribute( "id" );
        }
        else {
            if(tag->name() == "features" && tag->xmlns() == "http://etherx.jabber.org/streams")
            {
                if(tag->hasChild("starttls", "xmlns", "urn:ietf:params:xml:ns:xmpp-tls") )
                {
                    client_->send(gloox::Tag("starttls", "xmlns", "urn:ietf:params:xml:ns:xmpp-tls").xml());
                }
            }

            if(tag->name() == "proceed" && tag->xmlns() == "urn:ietf:params:xml:ns:xmpp-tls")
            {
                gloox::ConnectionTLS* encryption_client = new gloox::ConnectionTLS(this, client_.get(), log_);
                client_.reset(encryption_client);
                encryption_client->registerTLSHandler(this);
                gloox::ConnectionError ret = client_->connect();
                assert(ret == gloox::ConnNoError);
            }
        }
    }

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

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

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

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

private:

    gloox::LogSink log_;

    boost::shared_ptr<gloox::ConnectionBase> client_;

    boost::shared_ptr<gloox::ConnectionBase> raw_client_;

    gloox::Parser parser_;

    std::string sid_;
};

int main()
{
    Bot bot;
}