Transmission框架解析



Transmission框架解析

一.概述

因工作需要,接触了一下transmission, 了解了一下它的框架,但是没有做进一步的开发,此处作为笔记打个标记。

transmission是开源的bt下载工具,可以兼容linuxwindows环境;

Bt协议可以参考网站:http://www.bittorrent.org/

transmission代码中使用了libevent的框架;

二.具体流程

2.1 tr_session数据结构

 

struct tr_session

{

……

   int         torrentCount;

tr_torrent*  torrentList;    //每创建一个tor实例都会挂载在这个链表里

……

}

 

2.2 tr_torrent数据结构

struct tr_torrent

{

……

tr_session *  session;     //tor 实例,反过来指向session

……

}

 

2.3 void tr_eventInit (tr_session * session)

该函数session =tr_sessionInit ("daemon", configDir, true, &settings)中被调用

2.3.1 struct tr_event_handle

typedef struct tr_event_handle

{

   uint8_t      die;

    int          fds[2];    //管道描述符

   tr_lock *    lock;

   tr_session *  session;

   tr_thread *  thread;

   struct event_base * base;

   struct event * pipeEvent;

}

2.3.2 tr_eventInit

该函数创建一个线程,该线程函数建立一个总的消息循环;

tr_eventInit (tr_session * session)

{

   tr_event_handle* eh;

   pipe (eh->fds)    //建立管道,很重要,创建执行函数时会用它来通信

   eh->thread= tr_threadNew (libeventThreadFunc, eh);

}

 

2.3.3 libeventThreadFunc

static void

libeventThreadFunc (void * veh)

{

   struct event_base * base;

   tr_event_handle * eh = veh;

 

#ifndef WIN32

   /* Don't exit when writing on a broken socket */

   signal (SIGPIPE, SIG_IGN);

#endif

 

   /* create the libevent bases */

   base = event_base_new ();

 

   /* set the struct's fields */

   eh->base = base;

   eh->session->event_base = base;

   eh->session->evdns_base = evdns_base_new (base, true);

   eh->session->events = eh;

 

    /* listen to thepipe's read fd */

  eh->pipeEvent = event_new (base,eh->fds[0], EV_READ | EV_PERSIST, readFromPipe, veh);

//readFromPipe(),注册的函数,读取管道中的信息,执行

   event_add (eh->pipeEvent, NULL);

   event_set_log_callback (logFunc);

 

   /* loop until all the events are done */

   while (!eh->die)

       event_base_dispatch (base);  //libevent主体的循环

 

   /* shut down the thread */

   tr_lockFree (eh->lock);

   event_base_free (base);

   eh->session->events = NULL;

   tr_free (eh);

   tr_logAddDebug ("Closing libevent thread");

}

 

2.3.4 readFromPipe

 

static void

readFromPipe (evutil_socket_t   fd,

              short             eventType,

              void            * veh)

{

   char              ch;

   int               ret;

   tr_event_handle * eh = veh;

 

   dbgmsg ("readFromPipe: eventType is %hd", eventType);

 

   /* read the command type */

   ch = '\0';

   do

    {

       ret = piperead (fd, &ch, 1);

    }

   while (!eh->die && ret < 0 && errno == EAGAIN);

 

   dbgmsg ("command is [%c], ret is %d, errno is %d", ch, ret,(int)errno);

 

   switch (ch)

    {

       case 'r': /* run in libevent thread */

       {

           struct tr_run_data data;

           const size_t       nwant = sizeof(data);

           const ssize_t      ngot = piperead(fd, &data, nwant);

           if (!eh->die && (ngot== (ssize_t)nwant))

           {

                dbgmsg ("invoking functionin libevent thread");

             (data.func)(data.user_data);

           }

           break;

       }

 

       case '\0': /* eof */

       {

           dbgmsg ("pipe eofreached... removing event listener");

           event_free (eh->pipeEvent);

           break;

       }

 

       default:

       {

           assert (0 && "unhandled command type!");

           break;

       }

    }

}

 

2.3.5 tr_runInEventThread

 

void

tr_runInEventThread (tr_session *session,    /*phicomm important*/

                     void func (void*), void *user_data)

{

 assert (tr_isSession (session));

 assert (session->events != NULL);

 

  if(tr_amInThread (session->events->thread))

    {

     (func)(user_data);

    }

 else

    {

     int fd;

     char ch;

     ssize_t res_1;

     ssize_t res_2;

     tr_event_handle * e = session->events;

     struct tr_run_data data;

 

     tr_lockLock (e->lock);

 

     fd = e->fds[1];

     ch = 'r';

     res_1 = pipewrite (fd, &ch, 1);

 

     data.func = func;

     data.user_data = user_data;

      res_2 = pipewrite (fd,&data, sizeof (data));

//将函数地址送入管道,由readFromPipe()读取后执行;

     tr_lockUnlock (e->lock);

 

     if ((res_1 == -1) || (res_2 == -1))

       tr_logAddError ("Unable to write to libtransmisison event queue:%s", tr_strerror(errno));

    }

}

 

2.4 tr_sessionInitImpl

tr_runInEventThread (session, tr_sessionInitImpl, &data);//很熟悉吧,就是上文的介绍,此处启动函数执行

 

Void tr_sessionInitImpl (void * vdata)

2.5 torrentInit

torrentInit (tr_torrent * tor, const tr_ctor * ctor)

一层一层的封装以后,会有

tr_runInEventThread (tor->session, torrentStartImpl, tor)

tr_peerMgrStartTorrent (tor);

ensureMgrTimersExist (s->manager);

bandwidthPulse

reconnectPulse

makeNewPeerConnections

initiateCandidateConnection

initiateConnection

 

2.6initiateConnection

initiateConnection (tr_peerMgr * mgr, tr_swarm * s, struct peer_atom* atom)

tr_peerIo*

tr_peerIoNewOutgoing (tr_session        * session,

                     tr_bandwidth      * parent,

                      consttr_address  * addr,

                     tr_port             port,

                      constuint8_t     * torrentHash,

                     bool                isSeed,

                     bool                utp)

 

static tr_peerIo*

tr_peerIoNew (tr_session      * session,// here add callback to read and write

             tr_bandwidth     * parent,

              const tr_address* addr,

              tr_port            port,

              constuint8_t    * torrentHash,

              bool               isIncoming,

              bool               isSeed,

              int                socket,

              struct UTPSocket* utp_socket)

{

……

if (io->socket >= 0) {

        io->event_read =event_new (session->event_base,

                                   io->socket, EV_READ, event_read_cb,io);        io->event_write =event_new (session->event_base,

                                     io->socket, EV_WRITE,event_write_cb, io);

……

}

 

 

static void

event_read_cb (evutil_socket_t fd, short event UNUSED, void * vio)

{

  res = evbuffer_read(io->inbuf, fd, (int)howmuch);  //IO读取数据

if (res > 0)

    {

        tr_peerIoSetEnabled(io, dir, true);

 

        /* Invoke the usercallback - must always be called last */

        canReadWrapper (io);   //调用回调处理,canRead()

    }

    else

    {

}

}

 

void

initiateConnection (tr_peerMgr * mgr,tr_swarm * s, struct peer_atom * atom)

{

  io= tr_peerIoNewOutgoing (mgr->session,//phicomm init socket

                            &mgr->session->bandwidth,

                            &atom->addr,

                             atom->port,

                            s->tor->info.hash,

                            s->tor->completeness == TR_SEED,

                             utp);

 

  if(io == NULL)

    {

     tordbg (s, "peerIo not created; marking peer %s asunreachable", tr_atomAddrStr (atom));

     atom->flags2 |= MYFLAG_UNREACHABLE;

     atom->numFails++;

    }

 else

    {

     tr_handshake * handshake = tr_handshakeNew (io,                   //phicomm

                                                 mgr->session->encryptionMode,

                                                 myHandshakeDoneCB,

                                                 mgr);

//此处完成握手后会在该函数中注册canRead

}

 

 

static bool

myHandshakeDoneCB (tr_handshake  * handshake,

                   tr_peerIo     * io,

                   bool            readAnythingFromPeer,

                   bool            isConnected,

                   const uint8_t * peer_id,

                   void          * vmanager)

{

createBitTorrentPeer (s->tor, io, atom,client);

}

 

static void

createBitTorrentPeer (tr_torrent       * tor,

                      struct tr_peerIo * io,

                      struct peer_atom * atom,

                      tr_quark           client)

{

peer = (tr_peer*) tr_peerMsgsNew (tor, io,peerCallbackFunc, swarm);

}

 

tr_peerMsgs *

tr_peerMsgsNew (struct tr_torrent    * torrent,

                struct tr_peerIo     * io,

                tr_peer_callback       callback,

                void                 * callbackData)

{

tr_peerIoSetIOFuncs (m->io, canRead,didWrite, gotError, m);

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值