XMPP-gloox实现的文件传世协议分享

XMPP-gloox实现的文件传世协议分享

1.支持IBB传输

2.支持S5B传输

可以简单的改动即可传输二进制,在只做的过程中遇到一些很难理解的问题现在分享出来:

1.发送端使用s5b的时候,关于这句的理解new SOCKS5BytestreamServer(j->logInstance(), 25254, "0.0.0.0");如果按照例子提供的代码你说创建失败的,因为不传ip默认的af_inet就是AF_INET6,会返回10047的socket错误。

2.sock5代理服务器的使用流程是什么?

a。发送端首先需要监听本地端口,然后将本地监听的地址通过addStreamHost加入到sock5服务器候选(局域网或者本机传输就可以了,因为他会自动选中此端口作文文件传输端口),如果需要广域网传输文件那么你需要添加sock5服务器的ip,这里默认使用openfire的文件代理插件,此插件使用的端口是7777,我们将其添加到sock5候选即可

b。接收端相对简单只需要将代理服务器的地址加入候选即可,这里使用openfire的7777端口。

实现以上基本就可以成功了,以下给几张截图:

接收端:

XMPP-gloox实现的文件传世协议分享_第1张图片

发送端:

XMPP-gloox实现的文件传世协议分享_第2张图片

发送过程:

 XMPP-gloox实现的文件传世协议分享_第3张图片

接收过程:

ok已经成功运行了,下面放出源码:

头文件

#ifndef __XmppFileSend_H
#define __XmppFileSend_H

#include 
#include 
#include 
#include "client.h"
#include "connectionlistener.h"
#include "siprofilefthandler.h"
#include "bytestreamdatahandler.h"
#include "siprofileft.h"
#include "disco.h"

#pragma warning(disable:4996)

using stdstr = std::string;
using stdcstr = const std::string;
using ifstream = std::ifstream;

using namespace gloox;
class XmppFileSend : public LogHandler, ConnectionListener, SIProfileFTHandler, BytestreamDataHandler
{
public:
    XmppFileSend( stdcstr & filename , XmppTransFileObserver* observer = nullptr, int s5port = 7777);

    virtual ~XmppFileSend();

    bool SendFile();

    bool Start(const std::string& user ,
               const std::string& toUser,
               const std::string& pwd, 
               const std::string& serverip,
               WORD port,
               const std::string& domain);
    bool Start(Client* client);
    void Stop();

    void SetToUser(const std::string& toUser);

public:
    ConnectionError OnStreamRecv(int timeout);

public:
    virtual void onConnect();

    virtual void onDisconnect(ConnectionError e);

    virtual bool onTLSConnect(const CertInfo& info);

public:
    bool DoConnect();

protected:
    bool _initFileInfo();
    bool _readFile(stdstr& str);
    void _closeFile();
protected:
    bool _createStream();
protected:
    virtual void handleLog(LogLevel level, LogArea area, const std::string& message);

    virtual void handleFTRequest(const JID& from, const JID& /*to*/, const std::string& sid,
                                 const std::string& name, long size, const std::string& hash,
                                 const std::string& date, const std::string& mimetype,
                                 const std::string& desc, int /*stypes*/);

    //     virtual void handleFTRequestResult( const JID& /*from*/, const std::string& /*sid*/ )
    //     {
    //     }

    virtual void handleFTRequestError(const IQ& /*iq*/, const std::string& /*sid*/);

    virtual void handleFTBytestream(Bytestream* bs);

    virtual const std::string handleOOBRequestResult(const JID& /*from*/, const JID& /*to*/, const std::string& /*sid*/);;

    virtual void handleBytestreamData(Bytestream* /*bs*/, const std::string& data);

    virtual void handleBytestreamError(Bytestream* /*bs*/, const IQ& /*iq*/);

    virtual void handleBytestreamOpen(Bytestream* /*bs*/);

    virtual void handleBytestreamClose(Bytestream* /*bs*/);

private:
    Client* j;
    SIProfileFT* f;
    Bytestream* m_bs;
    SOCKS5BytestreamServer* m_server;
    JID m_to;
    std::string m_strtoName;
    std::string m_file;
    bool m_quit;
    int m_size;
    bool m_del;
    int m_s5b_port;

    stdstr m_filename;
    size_t m_filesize;
    ifstream m_ifs;
    size_t m_curReadCnt;
    XmppTransFileObserver* m_observer;
};


#endif //__XmppFileSend_H


、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

#include "pch.h"
#include "XmppFileSend.h"
#include "base64.h"
#include "socks5bytestreamserver.h"

#define F_PRINT(fmt,...) printf("\n[%s:%d]\t" fmt , __FUNCTION__,__LINE__ , ##__VA_ARGS__)

XmppFileSend::XmppFileSend(stdcstr& filename, XmppTransFileObserver* observer, int s5port) :
    m_bs(0), m_quit(false), m_del(true),
    m_filename(filename), m_filesize(0), m_curReadCnt(0),
    m_observer(observer), m_server(nullptr), f(nullptr), j(nullptr), m_size(0),
    m_s5b_port(s5port)
{
}

XmppFileSend::~XmppFileSend()
{
    Stop();
}

bool XmppFileSend::SendFile()
{
    bool bSend = true;
    if (m_bs && m_bs->isOpen())
    {
        stdstr sData;
        if (bSend = _readFile( sData )) {
            bSend = m_bs->send( sData );
        }
    }

    return bSend;
}

bool XmppFileSend::Start(const std::string& user, 
                         const std::string& toUser, 
                         const std::string& pwd, 
                         const std::string& serverip,
                         WORD port,
                         const std::string& domain)
{
    if (!_initFileInfo())
    {
        return false;
    }

    m_del = true;
    m_to = JID(toUser + "@" + domain + "/trans-file");

    JID jid(user + "@" + domain + "/trans-file");
    j = new Client(jid, pwd);
    j->setUsername(user);
    j->setPassword(pwd);
    j->setTls(TLSDisabled);
    j->setServer(serverip);
    j->setPort(port);
    j->disableRoster();


    j->registerConnectionListener(this);
    j->disco()->setVersion("trans-filesend", GLOOX_VERSION, "Linux");
    j->disco()->setIdentity("client", "bot");

    return DoConnect();
}

bool XmppFileSend::Start(Client* client)
{
    if (!_initFileInfo())
    {
        return false;
    }

    m_del = false;
    j = client;

    if (m_strtoName.find("@") == m_strtoName.npos)
    {
        std::string sUser = m_strtoName + "@" + client->jid().server() +
            (client->resource().size() ? "/" + client->resource() : "");
        m_to.setJID(sUser);
    }
    else
    {
        m_to.setJID(m_strtoName);
    }

    return true;
}

void XmppFileSend::Stop()
{
    m_quit = true;
    if (j) j->disconnect();

    std::this_thread::sleep_for(std::chrono::milliseconds(200));

    if (f)
    {
        if (m_bs)
        {
            m_bs->close();
            f->dispose(m_bs);
        }
        delete f;
        f = nullptr;
    }

    if (m_server)
    {
        delete m_server;
        m_server = nullptr;
    }

    if (j)
    {
        if(m_del)delete j;
        j = nullptr;
    }
}

void XmppFileSend::SetToUser(const std::string& peer)
{
    m_strtoName = peer;
}

gloox::ConnectionError XmppFileSend::OnStreamRecv(int timeout)
{
    if (m_server)
    {
        ConnectionError se = m_server->recv(timeout);
        if (se != ConnNoError)
        {
            return se;
        }
    }

    if (m_bs)
    {
        m_bs->recv(timeout);
    }
    else if (m_bs)
        m_bs->close();

    return ConnNoError;
}

void XmppFileSend::onConnect()
{
    //using namespace std::chrono;
    F_PRINT("connected!!!\n");
    std::string sFileName = m_filename;
    char* pBackSlash = strrchr(&m_filename[0], '\\');
    if (pBackSlash)
    {
        sFileName = pBackSlash + 1;
    }

    if (_createStream())
    {
        f->requestFT(m_to, Base64::encode64(sFileName), (int)m_filesize);
    }
}

void XmppFileSend::onDisconnect(ConnectionError e)
{
    F_PRINT("ft_send: disconnected: %d\n", e);
    if (e == ConnAuthenticationFailed)
        F_PRINT("auth failed. reason: %d\n", j->authError());
}

bool XmppFileSend::onTLSConnect(const CertInfo& info)
{
    time_t from(info.date_from);
    time_t to(info.date_to);

    F_PRINT("status: %d\nissuer: %s\npeer: %s\nprotocol: %s\nmac: %s\ncipher: %s\ncompression: %s\n",
           info.status, info.issuer.c_str(), info.server.c_str(),
           info.protocol.c_str(), info.mac.c_str(), info.cipher.c_str(),
           info.compression.c_str());
    F_PRINT("from: %s", ctime(&from));
    F_PRINT("to:   %s", ctime(&to));
    return true;
}

bool XmppFileSend::DoConnect()
{
    bool b = j->connect(false);
    m_quit = !b;

    if (b && m_del)
    {
        ConnectionError ce = ConnNoError;
        while (ce == ConnNoError)
        {
            if (m_quit) {
                j->disconnect();
                break;
            }

            ce = j->recv(1);
            if (!SendFile()) {
                m_quit = true;
            }

            if (ce == ConnNoError)
            {
                ce = OnStreamRecv(1);
            }
        }
        F_PRINT("ce: %d\n", ce);
    }

    return b;
}

bool XmppFileSend::_initFileInfo()
{
    m_curReadCnt = 0;
    m_ifs.open(m_filename,std::ios::binary|std::ios::in);
    if (m_ifs.is_open())
    {
        m_ifs.seekg(0, std::ios::end );
        m_filesize = m_ifs.tellg();
        m_ifs.seekg( 0, std::ios::beg );

        return m_filesize>0;
    }

    return false;
}

bool XmppFileSend::_readFile( stdstr& str )
{
    if (m_curReadCnt < m_filesize && m_ifs.good() && !m_ifs.eof())
    {
        char szBuf[1024];
        m_ifs.read( szBuf, 1024 );
        int nRealCnt = (int)m_ifs.gcount();
        if (nRealCnt>0)
        {
            str.assign( szBuf, nRealCnt );
            m_curReadCnt += nRealCnt;
            return true;
        }
    }

    return false;
}

void XmppFileSend::_closeFile()
{
    if (m_ifs.is_open())
    {
        m_ifs.close();
    }
}

bool XmppFileSend::_createStream()
{
    f = new SIProfileFT(j, this);

    if (m_s5b_port > 0)
    {
        //sock5
        m_server = new SOCKS5BytestreamServer(j->logInstance(), 25254, "0.0.0.0");
        ConnectionError ce = m_server->listen();
        if (ce != ConnNoError)
        {
            F_PRINT("sock5 listen fail");
            return false;
        }

        F_PRINT("sock5 listening");

        //注册sock5
        f->registerSOCKS5BytestreamServer(m_server);
        f->addStreamHost(j->jid(), "127.0.0.1", 25254);
        f->addStreamHost(JID("proxy." + j->jid().server()), j->server(), m_s5b_port);
        F_PRINT("SOCK5 Proxy File Transfer[proxy port=%d]",m_s5b_port);
    }
    else
    {
        F_PRINT("IBB File Transfer");
    }
    

    return true;
}

void XmppFileSend::handleLog(LogLevel level, LogArea area, const std::string& message)
{
    F_PRINT("\n: level: %d, area: %d, %s\n", level, area, message.c_str());
}

void XmppFileSend::handleFTRequest(const JID& from, const JID& /*to*/, const std::string& sid, const std::string& name, long size, const std::string& hash, const std::string& date, const std::string& mimetype, const std::string& desc, int /*stypes*/)
{
    F_PRINT("received ft request from %s: %s (%ld bytes, sid: %s). hash: %s, date: %s, mime-type: %s\n"
           "desc: %s\n",
           from.full().c_str(), name.c_str(), size, sid.c_str(), hash.c_str(), date.c_str(),
           mimetype.c_str(), desc.c_str());
    f->acceptFT(from, sid, SIProfileFT::FTTypeS5B);
}

void XmppFileSend::handleFTRequestError(const IQ& iq, const std::string& sid)
{
    F_PRINT("ft request error[%s]\n", __FUNCTION__);
    m_quit = true;
}

void XmppFileSend::handleFTBytestream(Bytestream* bs)
{
    F_PRINT("received bytestream of type: %s", bs->type() == Bytestream::S5B ? "s5b" : "ibb");
    m_bs = bs;
    m_bs->registerBytestreamDataHandler(this);
    if (m_bs->connect())
    {
        if (bs->type() == Bytestream::S5B)
            F_PRINT("ok! s5b connected to streamhost\n");
        else
            F_PRINT("ok! ibb sent request to remote entity\n");

        if (m_observer)
        {
            m_observer->OnBegin(m_filename, (int)m_filesize, this);
        }
    }
}

const std::string XmppFileSend::handleOOBRequestResult(const JID& /*from*/, const JID& /*to*/, const std::string& /*sid*/)
{
    return std::string();
}

void XmppFileSend::handleBytestreamData(Bytestream* /*bs*/, const std::string& data)
{
    //F_PRINT("received %zd bytes of data:\n%s\n", data.length(), data.c_str());
    if (m_observer)
    {
        m_observer->OnProgress(m_filename, (int)m_curReadCnt, (int)m_filesize, this);
    }
}

void XmppFileSend::handleBytestreamError(Bytestream* /*bs*/, const IQ& /*iq*/)
{
    F_PRINT("bytestream error\n");
}

void XmppFileSend::handleBytestreamOpen(Bytestream* /*bs*/)
{
    F_PRINT("bytestream opened\n");
}

void XmppFileSend::handleBytestreamClose(Bytestream* /*bs*/)
{
    F_PRINT("bytestream closed\n");
    m_quit = true;
    if (m_observer)
    {
        m_observer->OnEnd(m_filename, (int)m_curReadCnt, (int)m_filesize, this);
    }
}

#ifndef __XmppFileRecv_H
#define __XmppFileRecv_H

#include 
#include 
#include 
#include 
#include "client.h"
#include "connectionlistener.h"
#include "siprofilefthandler.h"
#include "bytestreamdatahandler.h"
#include "siprofileft.h"

#include 

using namespace gloox;

using stdstr = std::string;
using stdcstr = const std::string;
using std::ofstream;

struct RecvFileInfo {
    stdstr m_from;
    stdstr m_filename;
    size_t m_filesize = 0;
    ofstream m_ofs;
    size_t m_curCnt = 0;

    bool _initFileInfo(stdcstr& filename, int len) {
        m_filename = filename;
        m_filesize = len;
        m_ofs.open(filename, std::ios::out | std::ios::binary);
        m_curCnt = 0;
        std::cout << __FUNCTION__ << "写入文件:" << filename << "\r\n";
        return m_ofs.is_open();
    }
    bool _writeFile(stdcstr& str) {
        m_curCnt += str.size();
        if (m_ofs.is_open())
        {
            return m_ofs.write(str.data(), str.size()).good();
        }
        return false;
    }
    void _closeFile() {
        if (m_ofs.good())
        {
            m_ofs.close();
        }
    }
};

using MAP_RECV_FILES = std::map>;

class XmppFileRecv : 
    public LogHandler, 
    ConnectionListener, 
    SIProfileFTHandler, 
    BytestreamDataHandler
{
public:
    XmppFileRecv(XmppTransFileObserver* observer = nullptr, int s5port = 7777);

    virtual ~XmppFileRecv();

    bool Start(const std::string& user,
               const std::string& pwd, 
               const std::string& serverip,
               WORD port,
               const std::string& domain
               );
    bool Start(Client* client);
    void Stop();

    inline void SetSaveDir(stdcstr& saveDir) { m_saveDir = saveDir; };

    //bool SendData(const void* data, int len);

public:
    ConnectionError OnStreamRecv(int timeout);

public:
    virtual void onConnect();
    virtual void onDisconnect(ConnectionError e);
    virtual bool onTLSConnect(const CertInfo& info);

protected:
    bool DoConnect();
    bool _createStream();

protected:


protected:

    virtual void handleLog(LogLevel level, LogArea area, const std::string& message);

    virtual void handleFTRequest(const JID& from, const JID& /*to*/, const std::string& sid,
                                 const std::string& name, long size, const std::string& hash,
                                 const std::string& date, const std::string& mimetype,
                                 const std::string& desc, int /*stypes*/);

    //     virtual void handleFTRequestResult( const JID& /*from*/, const std::string& /*sid*/ )
    //     {
    //     }

    virtual void handleFTRequestError(const IQ& /*iq*/, const std::string& /*sid*/);

    virtual void handleFTBytestream(Bytestream* bs);

    virtual const std::string handleOOBRequestResult(const JID& /*from*/, const JID& /*to*/, const std::string& /*sid*/);;

    virtual void handleBytestreamData(Bytestream* /*s5b*/, const std::string& data);

    virtual void handleBytestreamError(Bytestream* /*s5b*/, const IQ& /*stanza*/);

    virtual void handleBytestreamOpen(Bytestream* /*s5b*/);

    virtual void handleBytestreamClose(Bytestream* /*s5b*/);

private:
    Client* j;
    SIProfileFT* f;
    std::list m_bs;
    bool m_quit;
    bool m_del;
    int m_s5b_port;

    stdstr m_saveDir;
    MAP_RECV_FILES m_recvFiles;
    XmppTransFileObserver* m_observer;
};

#endif //__XmppFileRecv_H



#include "pch.h"
#include "XmppFileRecv.h"
#include 
#include "disco.h"
#include "base64.h"
#include "socks5bytestreamserver.h"

#pragma warning(disable:4996)

#define F_PRINT(fmt,...) printf("\n[%s:%d]\t" fmt , __FUNCTION__,__LINE__ , ##__VA_ARGS__)

XmppFileRecv::XmppFileRecv(XmppTransFileObserver* observer, int s5port) :
    m_quit(false), m_del(true),
    m_observer(observer),
    m_s5b_port(s5port)
{
}

XmppFileRecv::~XmppFileRecv()
{
    Stop();
}

bool XmppFileRecv::_createStream()
{
    f = new SIProfileFT(j, this);

    if (m_s5b_port > 0)
    {
        //注册sock5
        f->addStreamHost(JID("proxy." + j->jid().server()), j->server(), m_s5b_port);
        F_PRINT("SOCK5 Proxy File Transfer[proxy port=%d]",m_s5b_port);
    }
    else
    {
        F_PRINT("IBB File Transfer");
    }

    return true;
}

bool XmppFileRecv::Start(const std::string& user, 
                         const std::string& pwd, 
                         const std::string& serverip, 
                         WORD port, 
                         const std::string& domain)
{
    m_del = true;
    JID jid(user + "@" + domain + "/trans-file");
    j = new Client(jid, pwd);
    j->setTls(TLSDisabled);
    j->setServer(serverip);
    j->setPort(port);
    j->disableRoster();

    j->registerConnectionListener(this);
    j->disco()->setVersion("ftTest", GLOOX_VERSION, "Linux");
    j->disco()->setIdentity("client", "bot");

    //j->logInstance().registerLogHandler(LogLevelDebug, LogAreaAll, this);

    //f = new SIProfileFT(j, this);

    _createStream();

    return DoConnect();
}

bool XmppFileRecv::Start(Client* client)
{
    m_del = false;
    j = client;
    //f = new SIProfileFT(j, this);

    _createStream();

    return true;
}

void XmppFileRecv::Stop()
{
    m_quit = true;
    if (j) j->disconnect();
    std::this_thread::sleep_for(std::chrono::milliseconds(200));

    if (f)
    {
        if (m_bs.size())
        {
            f->dispose(m_bs.front());
        }
        delete f;
        f = nullptr;
    }

    if (j)
    {
        if(m_del) delete j;
        j = nullptr;
    }
}

//bool XmppFileRecv::SendData(const void* data, int len)
//{
//    bool bSend = false;
//    if (len <= 0) return bSend;
//    
//    std::string t((char*)data, len);
//    std::list::iterator it = m_bs.begin();
//    for (; it != m_bs.end(); ++it) {
//        if ((*it)->isOpen())
//        {
//            if (!(bSend = (*it)->send(t))) {
//                m_quit = true;
//                break;
//            }
//        }
//        
//    }
//
//
//    return bSend;
//}

gloox::ConnectionError XmppFileRecv::OnStreamRecv(int timeout)
{
    std::list::iterator it = m_bs.begin();
    for (; it != m_bs.end(); ++it)
        (*it)->recv(timeout);

    return ConnNoError;
}

void XmppFileRecv::onConnect()
{
    F_PRINT("connected!!!\n");
}

void XmppFileRecv::onDisconnect(ConnectionError e)
{
    F_PRINT("message_test: disconnected: %d\n", e);
    if (e == ConnAuthenticationFailed)
        F_PRINT("auth failed. reason: %d\n", j->authError());
}

bool XmppFileRecv::onTLSConnect(const CertInfo& info)
{
    time_t from(info.date_from);
    time_t to(info.date_to);

    F_PRINT("status: %d\nissuer: %s\npeer: %s\nprotocol: %s\nmac: %s\ncipher: %s\ncompression: %s\n",
           info.status, info.issuer.c_str(), info.server.c_str(),
           info.protocol.c_str(), info.mac.c_str(), info.cipher.c_str(),
           info.compression.c_str());
    F_PRINT("from: %s", ctime(&from));
    F_PRINT("to:   %s", ctime(&to));
    return true;
}

bool XmppFileRecv::DoConnect()
{
    bool b = j->connect(false);
    m_quit = !b;

    if (b && m_del)
    {
        std::thread([this]() {
            ConnectionError ce = ConnNoError;
            while (ce == ConnNoError)
            {
                if (m_quit) {
                    j->disconnect();
                    break;
                }

                ce = j->recv(1);
                if (ce == ConnNoError)
                {
                    ce = OnStreamRecv(1);
                }
            }
            F_PRINT("ce: %d\n", ce);
        }).detach();
    }

    return b;
}

void XmppFileRecv::handleLog(LogLevel level, LogArea area, const std::string& message)
{
    F_PRINT("log: level: %d, area: %d, %s\n", level, area, message.c_str());
}

void XmppFileRecv::handleFTRequest(const JID& from, const JID& /*to*/, const std::string& sid, 
                                   const std::string& name, long size, const std::string& hash, 
                                   const std::string& date, const std::string& mimetype, 
                                   const std::string& desc, int /*stypes*/)
{
    std::string sFilename = Base64::decode64(name);
    F_PRINT("received ft request from %s: %s (%ld bytes, sid: %s). hash: %s, date: %s, mime-type: %s\n"
           "desc: %s\n",
           from.full().c_str(), sFilename.c_str(), size, sid.c_str(), hash.c_str(), date.c_str(),
           mimetype.c_str(), desc.c_str());

    int sty = (m_s5b_port > 0 ? SIProfileFT::FTTypeS5B : SIProfileFT::FTTypeIBB);
    f->acceptFT(from, sid, (SIProfileFT::StreamType)sty);

    m_recvFiles[sid] = std::make_unique();

    std::string savefile = m_saveDir +"/" + sFilename;
    m_recvFiles[sid]->_initFileInfo(savefile, size);
    m_recvFiles[sid]->m_from = from;

    if (m_observer)
    {
        m_observer->OnBegin(savefile, size,this);
    }
}

void XmppFileRecv::handleFTRequestError(const IQ& /*iq*/, const std::string& /*sid*/)
{
    F_PRINT("ft request error[%s]\n",__FUNCTION__);
}

void XmppFileRecv::handleFTBytestream(Bytestream* bs)
{
    F_PRINT("received bytestream of type: %s", bs->type() == Bytestream::S5B ? "s5b" : "ibb");
    m_bs.push_back(bs);
    bs->registerBytestreamDataHandler(this);
    
    if (bs->connect())
    {
        if (bs->type() == Bytestream::S5B)
        {
            F_PRINT("ok! s5b connected to streamhost\n");
        }
        else
            F_PRINT("ok! ibb sent request to remote entity\n");
    }
}

const std::string XmppFileRecv::handleOOBRequestResult(const JID& /*from*/, const JID& /*to*/, const std::string& /*sid*/)
{
    return std::string();
}

void XmppFileRecv::handleBytestreamData(Bytestream* stream, const std::string& data)
{
    //F_PRINT("received %zd bytes of data:\n%s\n", data.length(), data.c_str());
    auto& fileinfo = m_recvFiles[stream->sid()];
    fileinfo->_writeFile(data);
    if (m_observer)
    {
        m_observer->OnProgress(fileinfo->m_filename, (int)fileinfo->m_curCnt, (int)fileinfo->m_filesize, this);
        if ((int)fileinfo->m_curCnt == (int)fileinfo->m_filesize)
        {
            //SIManager::SIError error = SIManager::RequestRejected;
            //std::string from = m_recvFiles[stream->sid()]->m_from;
            //f->declineFT(JID(from), stream->sid(), error);
        
            auto& fileinfo = m_recvFiles[stream->sid()];
            m_observer->OnEnd(fileinfo->m_filename, (int)fileinfo->m_curCnt, (int)fileinfo->m_filesize, this);
            fileinfo->_closeFile();
        }
    }
}

void XmppFileRecv::handleBytestreamError(Bytestream* /*s5b*/, const IQ& /*stanza*/)
{
    F_PRINT("socks5 stream error\n");
}

void XmppFileRecv::handleBytestreamOpen(Bytestream* /*s5b*/)
{
    F_PRINT("stream opened\n");
}

void XmppFileRecv::handleBytestreamClose(Bytestream* stream)
{
    F_PRINT("stream closed\n");
    //m_quit = true;
    if (m_observer)
    {
        auto& fileinfo = m_recvFiles[stream->sid()];
        m_observer->OnEnd(fileinfo->m_filename, (int)fileinfo->m_curCnt, (int)fileinfo->m_filesize, this);
        fileinfo->_closeFile();
    }
}

调用例子

void TestFT()
{
    std::cout << "(1) Sender\n"
        << "(2) Reciever\n";

    int mode = 2;
    std::cin >> mode;
    if (mode != 1)
    {
        mode = 2;
    }

    std::cout << "s5 proxy port(0 use ibb):\n";
    int s5_port = 0;
    std::cin >> s5_port;

    //-------------------------------------------------------------------------------
    //文件传输测试
    XmppTransFileObserverImp filetransob;

    if (mode == 2)//接收端
    {
        static XmppFileRecv fileRecv((XmppTransFileObserver*)&filetransob, s5_port);

        fileRecv.SetSaveDir("d:\\111");
        fileRecv.Start(userA, pwd, ip, port, domain);
    }

    //-------------------------------------------------------------------------------
    std::string sData = "adasdsadsaasdsadascacascascascascsa\r\n";

    while (std::getline(std::cin, sData))
    {
        if (sData == "quit")
        {
            break;
        }
        //client1.SendMessage(userB, sData);
        //client1.SendCmd(userB, "ls");
        client2.SendCmd(userA,"return ls con");
        //se.SendData(sData.data(), (int)sData.length());

        if (mode == 1)
        {
            if (_access(sData.c_str(), 0) == 0)
            {
                XmppFileSend fileSend(sData, (XmppTransFileObserver*)&filetransob, s5_port);
                fileSend.Start(userB, userA, pwd, ip, port, domain);
            }
        }
    }
}

代理接口

/**
 * @brief 发送接收文件回调
*/
class XmppTransFileObserver
{
public:
    XmppTransFileObserver() = default;
    virtual ~XmppTransFileObserver() = default;
public:
    virtual void OnBegin(const std::string& filename, int len, void* pClient) = 0;
    virtual void OnProgress(const std::string& filename, int cur, int total, void* pClient) = 0;
    virtual void OnEnd(const std::string& filename, int cur, int total, void* pClient) = 0;
};

你可能感兴趣的:(src,商店,xmpp,ft文件传输,gloox文件传输)