Changeset 13954


Ignore:
Timestamp:
Feb 4, 2013, 4:23:33 PM (8 years ago)
Author:
jordan
Message:

(libT) make the class hierarchy between tr_peer, tr_peerMsgs, and tr_webseed a little less ad-hoc

Location:
trunk/libtransmission
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/clients.c

    r13625 r13954  
    144144}
    145145
    146 void
     146char *
    147147tr_clientForId (char * buf, size_t buflen, const void * id_in)
    148148{
     
    152152
    153153    if (!id)
    154         return;
     154        return buf;
    155155
    156156    /* Azureus-style */
     
    309309
    310310        if (*buf)
    311             return;
     311            return buf;
    312312    }
    313313
     
    332332
    333333        if (*buf)
    334             return;
     334            return buf;
    335335    }
    336336
     
    340340        if (*id=='M') mainline_style (buf, buflen, "BitTorrent", id);
    341341        if (*id=='Q') mainline_style (buf, buflen, "Queen Bee", id);
    342         if (*buf) return;
     342        if (*buf) return buf;
    343343    }
    344344
    345345    if (decodeBitCometClient (buf, buflen, id))
    346         return;
     346        return buf;
    347347
    348348    /* Clients with no version */
     
    441441            {
    442442                tr_snprintf (buf, buflen, "%s %d.%d.%d", name, a, b, c);
    443                 return;
     443                return buf;
    444444            }
    445445        }
     
    462462        tr_strlcpy (buf, out, buflen);
    463463    }
    464 }
     464
     465  return buf;
     466}
  • trunk/libtransmission/clients.h

    r13625 r13954  
    2222 * @ingroup utils
    2323 */
    24 void tr_clientForId (char * buf, size_t buflen, const void * peer_id);
     24char* tr_clientForId (char * buf, size_t buflen, const void * peer_id);
    2525
    2626#endif
  • trunk/libtransmission/peer-common.h

    r13949 r13954  
    2727 * @{
    2828 */
     29
     30struct tr_peer;
     31struct tr_swarm;
    2932
    3033enum
     
    7376extern const tr_peer_event TR_PEER_EVENT_INIT;
    7477
     78typedef void tr_peer_callback (struct tr_peer       * peer,
     79                               const tr_peer_event  * event,
     80                               void                 * client_data);
     81
     82/***
     83****
     84***/
     85
     86typedef void (*tr_peer_destruct_func)(struct tr_peer * peer);
     87typedef bool (*tr_peer_is_transferring_pieces_func)(const struct tr_peer * peer,
     88                                                    uint64_t now,
     89                                                    tr_direction direction,
     90                                                    unsigned int * Bps);
     91struct tr_peer_virtual_funcs
     92{
     93  tr_peer_destruct_func destruct;
     94  tr_peer_is_transferring_pieces_func is_transferring_pieces;
     95};
     96
    7597/**
    7698 * State information about a connected peer.
    7799 *
    78100 * @see struct peer_atom
    79  * @see tr_peermsgs
     101 * @see tr_peerMsgs
    80102 */
    81103typedef struct tr_peer
     
    84106     NOTE: private to peer-mgr.c */
    85107  bool doPurge;
    86 
    87   /* Whether or not we've choked this peer.
    88      Only applies to BitTorrent peers */
    89   bool peerIsChoked;
    90 
    91   /* whether or not the peer has indicated it will download from us.
    92      Only applies to BitTorrent peers */
    93   bool peerIsInterested;
    94 
    95   /* whether or the peer is choking us.
    96      Only applies to BitTorrent peers */
    97   bool clientIsChoked;
    98 
    99   /* whether or not we've indicated to the peer that we would download from them if unchoked.
    100      Only applies to BitTorrent peers */
    101   bool clientIsInterested;
    102108
    103109  /* number of bad pieces they've contributed to */
     
    110116  int pendingReqsToPeer;
    111117
    112   struct tr_peerIo * io;
    113 
    114118  /* Hook to private peer-mgr information */
    115119  struct peer_atom * atom;
     120
     121  struct tr_swarm * swarm;
    116122
    117123  /** how complete the peer's copy of the torrent is. [0.0...1.0] */
     
    125131  tr_quark client;
    126132
    127   time_t chokeChangedAt;
    128 
    129133  tr_recentHistory blocksSentToClient;
    130134  tr_recentHistory blocksSentToPeer;
     
    133137  tr_recentHistory cancelsSentToPeer;
    134138
    135   struct tr_peermsgs * msgs;
     139  const struct tr_peer_virtual_funcs * funcs;
    136140}
    137141tr_peer;
    138142
    139 typedef void tr_peer_callback (struct tr_peer       * peer,
    140                                const tr_peer_event  * event,
    141                                void                 * client_data);
     143
     144void tr_peerConstruct (struct tr_peer * peer, const tr_torrent * tor);
     145
     146void tr_peerDestruct  (struct tr_peer * peer);
     147
    142148
    143149/** Update the tr_peer.progress field based on the 'have' bitset. */
  • trunk/libtransmission/peer-io.h

    r13900 r13954  
    9191    tr_port               port;
    9292    int                   socket;
    93     struct UTPSocket      *utp_socket;
     93    struct UTPSocket    * utp_socket;
    9494
    9595    int                   refCount;
     
    139139                                  struct UTPSocket *        utp_socket);
    140140
    141 void tr_peerIoRefImpl         (const char              * file,
     141void tr_peerIoRefImpl            (const char              * file,
    142142                                  int                       line,
    143143                                  tr_peerIo               * io);
     
    145145#define tr_peerIoRef(io) tr_peerIoRefImpl (__FILE__, __LINE__, (io));
    146146
    147 void tr_peerIoUnrefImpl       (const char              * file,
     147void tr_peerIoUnrefImpl          (const char              * file,
    148148                                  int                       line,
    149149                                  tr_peerIo               * io);
  • trunk/libtransmission/peer-mgr.c

    r13903 r13954  
    115115 *
    116116 * @see tr_peer
    117  * @see tr_peermsgs
     117 * @see tr_peerMsgs
    118118 */
    119119struct peer_atom
     
    187187  tr_ptrArray                outgoingHandshakes; /* tr_handshake */
    188188  tr_ptrArray                pool; /* struct peer_atom */
    189   tr_ptrArray                peers; /* tr_peer */
     189  tr_ptrArray                peers; /* tr_peerMsgs */
    190190  tr_ptrArray                webseeds; /* tr_webseed */
    191191
     
    193193  struct tr_peerMgr        * manager;
    194194
    195   tr_peer                  * optimistic; /* the optimistic peer, or NULL if none */
     195  tr_peerMsgs              * optimistic; /* the optimistic peer, or NULL if none */
    196196  int                        optimisticUnchokeTimeScaler;
    197197
     
    253253
    254254/**
    255 ***
     255*** tr_peer virtual functions
    256256**/
    257257
    258 static inline void
    259 managerLock (const struct tr_peerMgr * manager)
    260 {
    261   tr_sessionLock (manager->session);
    262 }
    263 
    264 static inline void
    265 managerUnlock (const struct tr_peerMgr * manager)
    266 {
    267   tr_sessionUnlock (manager->session);
    268 }
    269 
    270 static inline void
    271 swarmLock (tr_swarm * swarm)
    272 {
    273   managerLock (swarm->manager);
    274 }
    275 
    276 static inline void
    277 swarmUnlock (tr_swarm * swarm)
    278 {
    279   managerUnlock (swarm->manager);
    280 }
    281 
    282 static inline int
    283 swarmIsLocked (const tr_swarm * swarm)
    284 {
    285   return tr_sessionIsLocked (swarm->manager->session);
     258static bool
     259tr_peerIsTransferringPieces (const tr_peer * peer,
     260                             uint64_t        now,
     261                             tr_direction    direction,
     262                             unsigned int  * Bps)
     263{
     264  assert (peer != NULL);
     265  assert (peer->funcs != NULL);
     266
     267  return (*peer->funcs->is_transferring_pieces)(peer, now, direction, Bps);
     268}
     269
     270unsigned int
     271tr_peerGetPieceSpeed_Bps (const tr_peer    * peer,
     272                          uint64_t           now,
     273                          tr_direction       direction)
     274{
     275  unsigned int Bps = 0;
     276  tr_peerIsTransferringPieces (peer, now, direction, &Bps);
     277  return Bps;
     278}
     279
     280static void
     281tr_peerFree (tr_peer * peer)
     282{
     283  assert (peer != NULL);
     284  assert (peer->funcs != NULL);
     285
     286  (*peer->funcs->destruct)(peer);
     287
     288  tr_free (peer);
     289}
     290
     291void
     292tr_peerConstruct (tr_peer * peer, const tr_torrent * tor)
     293{
     294  assert (peer != NULL);
     295  assert (tr_isTorrent (tor));
     296
     297  memset (peer, 0, sizeof (tr_peer));
     298
     299  peer->client = TR_KEY_NONE;
     300  peer->swarm = tor->swarm;
     301  tr_bitfieldConstruct (&peer->have, tor->info.pieceCount);
     302  tr_bitfieldConstruct (&peer->blame, tor->blockCount);
     303}
     304
     305static void peerDeclinedAllRequests (tr_swarm *, const tr_peer *);
     306
     307void
     308tr_peerDestruct (tr_peer * peer)
     309{
     310  assert (peer != NULL);
     311
     312  if (peer->swarm != NULL)
     313    peerDeclinedAllRequests (peer->swarm, peer);
     314
     315  tr_bitfieldDestruct (&peer->have);
     316  tr_bitfieldDestruct (&peer->blame);
     317
     318  if (peer->atom)
     319    peer->atom->peer = NULL;
    286320}
    287321
     
    290324**/
    291325
    292 static int
    293 handshakeCompareToAddr (const void * va, const void * vb)
    294 {
    295   const tr_handshake * a = va;
    296 
    297   return tr_address_compare (tr_handshakeGetAddr (a, NULL), vb);
    298 }
    299 
    300 static int
    301 handshakeCompare (const void * a, const void * b)
    302 {
    303   return handshakeCompareToAddr (a, tr_handshakeGetAddr (b, NULL));
    304 }
    305 
    306 static inline tr_handshake*
    307 getExistingHandshake (tr_ptrArray * handshakes, const tr_address * addr)
    308 {
    309   if (tr_ptrArrayEmpty (handshakes))
    310     return NULL;
    311 
    312   return tr_ptrArrayFindSorted (handshakes, addr, handshakeCompareToAddr);
    313 }
    314 
    315 static int
    316 comparePeerAtomToAddress (const void * va, const void * vb)
    317 {
    318   const struct peer_atom * a = va;
    319 
    320   return tr_address_compare (&a->addr, vb);
    321 }
    322 
    323 static int
    324 compareAtomsByAddress (const void * va, const void * vb)
    325 {
    326   const struct peer_atom * b = vb;
    327 
    328   assert (tr_isAtom (b));
    329 
    330   return comparePeerAtomToAddress (va, &b->addr);
     326static inline void
     327managerLock (const struct tr_peerMgr * manager)
     328{
     329  tr_sessionLock (manager->session);
     330}
     331
     332static inline void
     333managerUnlock (const struct tr_peerMgr * manager)
     334{
     335  tr_sessionUnlock (manager->session);
     336}
     337
     338static inline void
     339swarmLock (tr_swarm * swarm)
     340{
     341  managerLock (swarm->manager);
     342}
     343
     344static inline void
     345swarmUnlock (tr_swarm * swarm)
     346{
     347  managerUnlock (swarm->manager);
     348}
     349
     350static inline int
     351swarmIsLocked (const tr_swarm * swarm)
     352{
     353  return tr_sessionIsLocked (swarm->manager->session);
    331354}
    332355
     
    335358**/
    336359
     360static int
     361handshakeCompareToAddr (const void * va, const void * vb)
     362{
     363  const tr_handshake * a = va;
     364
     365  return tr_address_compare (tr_handshakeGetAddr (a, NULL), vb);
     366}
     367
     368static int
     369handshakeCompare (const void * a, const void * b)
     370{
     371  return handshakeCompareToAddr (a, tr_handshakeGetAddr (b, NULL));
     372}
     373
     374static inline tr_handshake*
     375getExistingHandshake (tr_ptrArray * handshakes, const tr_address * addr)
     376{
     377  if (tr_ptrArrayEmpty (handshakes))
     378    return NULL;
     379
     380  return tr_ptrArrayFindSorted (handshakes, addr, handshakeCompareToAddr);
     381}
     382
     383static int
     384comparePeerAtomToAddress (const void * va, const void * vb)
     385{
     386  const struct peer_atom * a = va;
     387
     388  return tr_address_compare (&a->addr, vb);
     389}
     390
     391static int
     392compareAtomsByAddress (const void * va, const void * vb)
     393{
     394  const struct peer_atom * b = vb;
     395
     396  assert (tr_isAtom (b));
     397
     398  return comparePeerAtomToAddress (va, &b->addr);
     399}
     400
     401/**
     402***
     403**/
     404
    337405const tr_address *
    338406tr_peerAddress (const tr_peer * peer)
     
    376444}
    377445
    378 void
    379 tr_peerConstruct (tr_peer * peer)
    380 {
    381   memset (peer, 0, sizeof (tr_peer));
    382 
    383   peer->have = TR_BITFIELD_INIT;
    384 }
    385 
    386 static tr_peer*
    387 peerNew (struct peer_atom * atom)
    388 {
    389   tr_peer * peer = tr_new (tr_peer, 1);
    390   tr_peerConstruct (peer);
    391 
    392   peer->atom = atom;
    393   atom->peer = peer;
    394 
    395   return peer;
    396 }
    397 
    398 static tr_peer*
    399 getPeer (tr_swarm * s, struct peer_atom * atom)
    400 {
    401   tr_peer * peer;
    402 
    403   assert (swarmIsLocked (s));
    404 
    405   peer = atom->peer;
    406 
    407   if (peer == NULL)
    408     {
    409       peer = peerNew (atom);
    410       tr_bitfieldConstruct (&peer->have, s->tor->info.pieceCount);
    411       tr_bitfieldConstruct (&peer->blame, s->tor->blockCount);
    412       tr_ptrArrayInsertSorted (&s->peers, peer, peerCompare);
    413     }
    414 
    415   return peer;
    416 }
    417 
    418 static void peerDeclinedAllRequests (tr_swarm *, const tr_peer *);
    419 
    420 void
    421 tr_peerDestruct (tr_torrent * tor, tr_peer * peer)
    422 {
    423   assert (peer != NULL);
    424 
    425   peerDeclinedAllRequests (tor->swarm, peer);
    426 
    427   if (peer->msgs != NULL)
    428     tr_peerMsgsFree (peer->msgs);
    429 
    430   if (peer->io)
    431     {
    432       tr_peerIoClear (peer->io);
    433       tr_peerIoUnref (peer->io); /* balanced by the ref in handshakeDoneCB () */
    434     }
    435 
    436   tr_bitfieldDestruct (&peer->have);
    437   tr_bitfieldDestruct (&peer->blame);
    438 
    439   if (peer->atom)
    440     peer->atom->peer = NULL;
    441 }
    442 
    443 static void
    444 peerDelete (tr_swarm * s, tr_peer * peer)
    445 {
    446   tr_peerDestruct (s->tor, peer);
    447   tr_free (peer);
    448 }
    449 
    450446static inline bool
    451447replicationExists (const tr_swarm * s)
     
    467463  tr_piece_index_t piece_i;
    468464  const tr_piece_index_t piece_count = s->tor->info.pieceCount;
    469   tr_peer ** peers = (tr_peer**) tr_ptrArrayBase (&s->peers);
    470   const int peer_count = tr_ptrArraySize (&s->peers);
     465  const int n = tr_ptrArraySize (&s->peers);
    471466
    472467  assert (!replicationExists (s));
     
    480475      uint16_t r = 0;
    481476
    482       for (peer_i=0; peer_i<peer_count; ++peer_i)
    483         if (tr_bitfieldHas (&peers[peer_i]->have, piece_i))
    484           ++r;
     477      for (peer_i=0; peer_i<n; ++peer_i)
     478        {
     479          tr_peer * peer = tr_ptrArrayNth (&s->peers, peer_i);
     480          if (tr_bitfieldHas (&peer->have, piece_i))
     481            ++r;
     482        }
    485483
    486484      s->pieceReplication[piece_i] = r;
     
    499497  assert (tr_ptrArrayEmpty (&s->peers));
    500498
    501   tr_ptrArrayDestruct (&s->webseeds, (PtrArrayForeachFunc)tr_webseedFree);
     499  tr_ptrArrayDestruct (&s->webseeds, (PtrArrayForeachFunc)tr_peerFree);
    502500  tr_ptrArrayDestruct (&s->pool, (PtrArrayForeachFunc)tr_free);
    503501  tr_ptrArrayDestruct (&s->outgoingHandshakes, NULL);
     
    520518
    521519  /* clear the array */
    522   tr_ptrArrayDestruct (&s->webseeds, (PtrArrayForeachFunc)tr_webseedFree);
     520  tr_ptrArrayDestruct (&s->webseeds, (PtrArrayForeachFunc)tr_peerFree);
    523521  s->webseeds = TR_PTR_ARRAY_INIT;
    524522
    525523  /* repopulate it */
    526   for (i = 0; i < inf->webseedCount; ++i)
     524  for (i=0; i<inf->webseedCount; ++i)
    527525    {
    528526      tr_webseed * w = tr_webseedNew (tor, inf->webseeds[i], peerCallbackFunc, s);
     
    599597
    600598static int
    601 clientIsDownloadingFrom (const tr_torrent * tor, const tr_peer * peer)
     599clientIsDownloadingFrom (const tr_torrent * tor, const tr_peerMsgs * p)
    602600{
    603601  if (!tr_torrentHasMetadata (tor))
    604602    return true;
    605603
    606   return peer->clientIsInterested && !peer->clientIsChoked;
     604  return tr_peerMsgsIsClientInterested (p) && !tr_peerMsgsIsClientChoked (p);
    607605}
    608606
    609607static int
    610 clientIsUploadingTo (const tr_peer * peer)
    611 {
    612   return peer->peerIsInterested && !peer->peerIsChoked;
     608clientIsUploadingTo (const tr_peerMsgs * p)
     609{
     610  return tr_peerMsgsIsPeerInterested (p) && !tr_peerMsgsIsPeerChoked (p);
    613611}
    614612
     
    869867
    870868static int
    871 countActiveWebseeds (const tr_swarm * s)
    872 {
     869countActiveWebseeds (tr_swarm * s)
     870{
     871  int i;
    873872  int activeCount = 0;
    874   const tr_webseed ** w = (const tr_webseed **) tr_ptrArrayBase (&s->webseeds);
    875   const tr_webseed ** const wend = w + tr_ptrArraySize (&s->webseeds);
    876 
    877   for (; w!=wend; ++w)
    878     if (tr_webseedIsActive (*w))
     873  const int n = tr_ptrArraySize (&s->webseeds);
     874  const uint64_t now = tr_time_msec ();
     875
     876  for (i=0; i<n; ++i)
     877    if (tr_peerIsTransferringPieces (tr_ptrArrayNth(&s->webseeds,i), now, TR_DOWN, NULL))
    879878      ++activeCount;
    880879
     
    903902  else if (!s->endgame) /* only recalculate when endgame first begins */
    904903    {
     904      int i;
    905905      int numDownloading = 0;
    906       const tr_peer ** p = (const tr_peer **) tr_ptrArrayBase (&s->peers);
    907       const tr_peer ** const pend = p + tr_ptrArraySize (&s->peers);
     906      const int n = tr_ptrArraySize (&s->peers);
    908907
    909908      /* add the active bittorrent peers... */
    910       for (; p!=pend; ++p)
    911         if ((*p)->pendingReqsToPeer > 0)
    912           ++numDownloading;
     909      for (i=0; i<n; ++i)
     910        {
     911          const tr_peer * p = tr_ptrArrayNth (&s->peers, i);
     912          if (p->pendingReqsToPeer > 0)
     913            ++numDownloading;
     914        }
    913915
    914916      /* add the active webseeds... */
     
    13411343  /* sanity clause */
    13421344  assert (tr_isTorrent (tor));
    1343   assert (peer->clientIsInterested);
    1344   assert (!peer->clientIsChoked);
    13451345  assert (numwant > 0);
    13461346
     
    15161516            for (it=s->requests, end=it+n; it!=end; ++it)
    15171517            {
    1518                 if ((it->sentAt <= too_old) && it->peer->msgs && !tr_peerMsgsIsReadingBlock (it->peer->msgs, it->block))
     1518                tr_peerMsgs * msgs = PEER_MSGS(it->peer);
     1519
     1520                if ((msgs !=NULL) && (it->sentAt <= too_old) && !tr_peerMsgsIsReadingBlock (msgs, it->block))
    15191521                    cancel[cancelCount++] = *it;
    15201522                else
     
    15301532
    15311533            /* send cancel messages for all the "cancel" ones */
    1532             for (it=cancel, end=it+cancelCount; it!=end; ++it) {
    1533                 if ((it->peer != NULL) && (it->peer->msgs != NULL)) {
    1534                     tr_historyAdd (&it->peer->cancelsSentToPeer, now, 1);
    1535                     tr_peerMsgsCancel (it->peer->msgs, it->block);
    1536                     decrementPendingReqCount (it);
     1534            for (it=cancel, end=it+cancelCount; it!=end; ++it)
     1535            {
     1536              tr_peerMsgs * msgs = PEER_MSGS(it->peer);
     1537
     1538              if (msgs != NULL)
     1539                {
     1540                  tr_historyAdd (&it->peer->cancelsSentToPeer, now, 1);
     1541                  tr_peerMsgsCancel (msgs, it->block);
     1542                  decrementPendingReqCount (it);
    15371543                }
    15381544            }
     
    16561662      tr_peer * p = peers[i];
    16571663
    1658       if ((p != no_notify) && (p->msgs != NULL))
     1664      if ((p != no_notify) && (p != NULL))
    16591665        {
    16601666          tr_historyAdd (&p->cancelsSentToPeer, tr_time (), 1);
    1661           tr_peerMsgsCancel (p->msgs, block);
     1667          tr_peerMsgsCancel (PEER_MSGS(p), block);
    16621668        }
    16631669
     
    16711677tr_peerMgrPieceCompleted (tr_torrent * tor, tr_piece_index_t p)
    16721678{
     1679  int i;
    16731680  bool pieceCameFromPeers = false;
    16741681  tr_swarm * const s = tor->swarm;
    1675   const tr_peer ** peer = (const tr_peer **) tr_ptrArrayBase (&s->peers);
    1676   const tr_peer ** const pend = peer + tr_ptrArraySize (&s->peers);
     1682  const int n = tr_ptrArraySize (&s->peers);
    16771683
    16781684  /* walk through our peers */
    1679   for ( ; peer!=pend; ++peer)
    1680     {
     1685  for (i=0; i<n; ++i)
     1686    {
     1687      tr_peer * peer = tr_ptrArrayNth (&s->peers, i);
     1688
    16811689      /* notify the peer that we now have this piece */
    1682       tr_peerMsgsHave ((*peer)->msgs, p);
     1690      tr_peerMsgsHave (PEER_MSGS(peer), p);
    16831691
    16841692      if (!pieceCameFromPeers)
    1685         pieceCameFromPeers = tr_bitfieldHas (&(*peer)->blame, p);
     1693        pieceCameFromPeers = tr_bitfieldHas (&peer->blame, p);
    16861694    }
    16871695
     
    19021910}
    19031911
     1912
     1913static void
     1914createBitTorrentPeer (tr_torrent       * tor,
     1915                      struct tr_peerIo * io,
     1916                      struct peer_atom * atom,
     1917                      tr_quark           client)
     1918{
     1919  tr_peer * peer;
     1920  tr_swarm * swarm;
     1921
     1922  assert (atom != NULL);
     1923  assert (tr_isTorrent (tor));
     1924  assert (tor->swarm != NULL);
     1925
     1926  swarm = tor->swarm;
     1927
     1928  peer = (tr_peer*) tr_peerMsgsNew (tor, io, peerCallbackFunc, swarm);
     1929  peer->atom = atom;
     1930  peer->client = client;
     1931  atom->peer = peer;
     1932
     1933  tr_ptrArrayInsertSorted (&swarm->peers, peer, peerCompare);
     1934}
     1935
     1936
    19041937/* FIXME: this is kind of a mess. */
    19051938static bool
     
    19982031          else
    19992032            {
    2000               peer = getPeer (s, atom);
    2001 
    2002               if (!peer_id)
    2003                 peer->client = TR_KEY_NONE;
     2033              tr_quark client;
     2034              tr_peerIo * io;
     2035              char buf[128];
     2036
     2037              if (peer_id != NULL)
     2038                client = tr_quark_new (tr_clientForId (buf, sizeof (buf), peer_id), -1);
    20042039              else
    2005                 {
    2006                   char client[128];
    2007                   tr_clientForId (client, sizeof (client), peer_id);
    2008                   peer->client = tr_quark_new (client, -1);
    2009                 }
    2010 
    2011               peer->io = tr_handshakeStealIO (handshake); /* this steals its refcount too, which is
    2012                                                                 balanced by our unref in peerDelete ()  */
    2013               tr_peerIoSetParent (peer->io, &s->tor->bandwidth);
    2014               tr_peerMsgsNew (s->tor, peer, peerCallbackFunc, s);
     2040                client = TR_KEY_NONE;
     2041
     2042              io = tr_handshakeStealIO (handshake); /* this steals its refcount too, which is
     2043                                                       balanced by our unref in peerDelete ()  */
     2044              tr_peerIoSetParent (io, &s->tor->bandwidth);
     2045              createBitTorrentPeer (s->tor, io, atom, client);
    20152046
    20162047              success = true;
     
    24012432  /* disconnect the peers. */
    24022433  while ((peer = tr_ptrArrayPop (&swarm->peers)))
    2403     peerDelete (swarm, peer);
     2434    tr_peerFree (peer);
    24042435
    24052436  /* disconnect the handshakes. handshakeAbort calls handshakeDoneCB (),
     
    25342565peerIsSeed (const tr_peer * peer)
    25352566{
    2536     if (peer->progress >= 1.0)
    2537         return true;
    2538 
    2539     if (peer->atom && atomIsSeed (peer->atom))
    2540         return true;
    2541 
    2542     return false;
     2567  if (peer->progress >= 1.0)
     2568    return true;
     2569
     2570  if (peer->atom && atomIsSeed (peer->atom))
     2571    return true;
     2572
     2573  return false;
    25432574}
    25442575
     
    25962627{
    25972628  int i;
    2598   int size;
     2629  int n;
    25992630  tr_swarm * s;
    2600   const tr_peer ** peers;
    26012631
    26022632  assert (tr_isTorrent (tor));
     
    26082638
    26092639  s = tor->swarm;
    2610   size = tr_ptrArraySize (&s->peers);
    2611   peers = (const tr_peer **) tr_ptrArrayBase (&s->peers);
     2640  n = tr_ptrArraySize (&s->peers);
    26122641
    26132642  for (i=0; i<TR_PEER_FROM__MAX; ++i)
    26142643    setmePeersFrom[i] = 0;
    26152644
    2616   for (i=0; i<size; ++i)
    2617     {
    2618       const tr_peer * peer = peers[i];
     2645  for (i=0; i<n; ++i)
     2646    {
     2647      tr_peer * peer = tr_ptrArrayNth (&s->peers, i);
     2648      tr_peerMsgs * msgs = PEER_MSGS (peer);
    26192649      const struct peer_atom * atom = peer->atom;
    26202650
    2621       if (peer->io == NULL) /* not connected */
    2622         continue;
     2651      assert (msgs != NULL);
    26232652
    26242653      ++*setmePeersConnected;
     
    26262655      ++setmePeersFrom[atom->fromFirst];
    26272656
    2628       if (clientIsDownloadingFrom (tor, peer))
     2657      if (clientIsDownloadingFrom (tor, msgs))
    26292658        ++*setmePeersSendingToUs;
    26302659
    2631       if (clientIsUploadingTo (peer))
     2660      if (clientIsUploadingTo (msgs))
    26322661        ++*setmePeersGettingFromUs;
    26332662    }
     
    26402669{
    26412670  unsigned int i;
    2642   unsigned int webseedCount;
    2643   const tr_swarm * s;
    2644   const tr_webseed ** webseeds;
     2671  tr_swarm * s;
     2672  unsigned int n;
    26452673  double * ret = NULL;
    26462674  const uint64_t now = tr_time_msec ();
     
    26492677
    26502678  s = tor->swarm;
    2651   webseedCount = tr_ptrArraySize (&s->webseeds);
    2652   webseeds = (const tr_webseed**) tr_ptrArrayBase (&s->webseeds);
    2653   ret = tr_new0 (double, webseedCount);
     2679  n = tr_ptrArraySize (&s->webseeds);
     2680  ret = tr_new0 (double, n);
    26542681
    26552682  assert (s->manager != NULL);
    2656   assert (webseedCount == tor->info.webseedCount);
    2657 
    2658   for (i=0; i<webseedCount; ++i)
    2659     {
    2660       unsigned int Bps;
    2661       if (tr_webseedGetSpeed_Bps (webseeds[i], now, &Bps))
     2683  assert (n == tor->info.webseedCount);
     2684
     2685  for (i=0; i<n; ++i)
     2686    {
     2687      unsigned int Bps = 0;
     2688      if (tr_peerIsTransferringPieces (tr_ptrArrayNth(&s->webseeds,i), now, TR_DOWN, &Bps))
    26622689        ret[i] = Bps / (double)tr_speed_K;
    26632690      else
     
    26662693
    26672694  return ret;
    2668 }
    2669 
    2670 unsigned int
    2671 tr_peerGetPieceSpeed_Bps (const tr_peer * peer, uint64_t now, tr_direction direction)
    2672 {
    2673   return peer->io ? tr_peerIoGetPieceSpeed_Bps (peer->io, now, direction) : 0.0;
    26742695}
    26752696
     
    26812702  tr_peer_stat * ret;
    26822703  const tr_swarm * s;
    2683   const tr_peer ** peers;
     2704  tr_peer ** peers;
    26842705  const time_t now = tr_time ();
    26852706  const uint64_t now_msec = tr_time_msec ();
     
    26892710
    26902711  s = tor->swarm;
    2691   peers = (const tr_peer**) tr_ptrArrayBase (&s->peers);
     2712  peers = (tr_peer**) tr_ptrArrayBase (&s->peers);
    26922713  size = tr_ptrArraySize (&s->peers);
    26932714  ret = tr_new0 (tr_peer_stat, size);
     
    26962717    {
    26972718      char *                   pch;
    2698       const tr_peer *          peer = peers[i];
     2719      tr_peer *                peer = peers[i];
     2720      tr_peerMsgs *            msgs = PEER_MSGS (peer);
    26992721      const struct peer_atom * atom = peer->atom;
    27002722      tr_peer_stat *           stat = ret + i;
     
    27052727      stat->from                = atom->fromFirst;
    27062728      stat->progress            = peer->progress;
    2707       stat->isUTP               = peer->io->utp_socket != NULL;
    2708       stat->isEncrypted         = tr_peerIoIsEncrypted (peer->io) ? 1 : 0;
     2729      stat->isUTP               = tr_peerMsgsIsUtpConnection (msgs);
     2730      stat->isEncrypted         = tr_peerMsgsIsEncrypted (msgs);
    27092731      stat->rateToPeer_KBps     = toSpeedKBps (tr_peerGetPieceSpeed_Bps (peer, now_msec, TR_CLIENT_TO_PEER));
    27102732      stat->rateToClient_KBps   = toSpeedKBps (tr_peerGetPieceSpeed_Bps (peer, now_msec, TR_PEER_TO_CLIENT));
    2711       stat->peerIsChoked        = peer->peerIsChoked;
    2712       stat->peerIsInterested    = peer->peerIsInterested;
    2713       stat->clientIsChoked      = peer->clientIsChoked;
    2714       stat->clientIsInterested  = peer->clientIsInterested;
    2715       stat->isIncoming          = tr_peerIoIsIncoming (peer->io);
    2716       stat->isDownloadingFrom   = clientIsDownloadingFrom (tor, peer);
    2717       stat->isUploadingTo       = clientIsUploadingTo (peer);
     2733      stat->peerIsChoked        = tr_peerMsgsIsPeerChoked (msgs);
     2734      stat->peerIsInterested    = tr_peerMsgsIsPeerInterested (msgs);
     2735      stat->clientIsChoked      = tr_peerMsgsIsClientChoked (msgs);
     2736      stat->clientIsInterested  = tr_peerMsgsIsClientInterested (msgs);
     2737      stat->isIncoming          = tr_peerMsgsIsIncomingConnection (msgs);
     2738      stat->isDownloadingFrom   = clientIsDownloadingFrom (tor, msgs);
     2739      stat->isUploadingTo       = clientIsUploadingTo (msgs);
    27182740      stat->isSeed              = peerIsSeed (peer);
    27192741
     
    27282750      pch = stat->flagStr;
    27292751      if (stat->isUTP) *pch++ = 'T';
    2730       if (s->optimistic == peer) *pch++ = 'O';
     2752      if (s->optimistic == msgs) *pch++ = 'O';
    27312753      if (stat->isDownloadingFrom) *pch++ = 'D';
    27322754      else if (stat->clientIsInterested) *pch++ = 'd';
     
    27622784
    27632785  for (i=0; i<peerCount; ++i)
    2764     {
    2765       const tr_peer * peer = tr_ptrArrayNth (&s->peers, i);
    2766       tr_peerMsgsSetInterested (peer->msgs, false);
    2767     }
     2786    tr_peerMsgsSetInterested (tr_ptrArrayNth (&s->peers, i), false);
    27682787}
    27692788
     
    29212940          if (!isPeerInteresting (s->tor, piece_is_interesting, peer))
    29222941            {
    2923               tr_peerMsgsSetInterested (peer->msgs, false);
     2942              tr_peerMsgsSetInterested (PEER_MSGS(peer), false);
    29242943            }
    29252944          else
     
    29582977  s->interestedCount = MIN (maxPeers, rechoke_count);
    29592978  for (i=0; i<rechoke_count; ++i)
    2960     tr_peerMsgsSetInterested (rechoke[i].peer->msgs, i<s->interestedCount);
     2979    tr_peerMsgsSetInterested (PEER_MSGS(rechoke[i].peer), i<s->interestedCount);
    29612980
    29622981  /* cleanup */
     
    29702989struct ChokeData
    29712990{
    2972   bool      isInterested;
    2973   bool      wasChoked;
    2974   bool      isChoked;
    2975   int       rate;
    2976   int       salt;
    2977   tr_peer * peer;
     2991  bool          isInterested;
     2992  bool          wasChoked;
     2993  bool          isChoked;
     2994  int           rate;
     2995  int           salt;
     2996  tr_peerMsgs * msgs;
    29782997};
    29792998
     
    29973016
    29983017/* is this a new connection? */
    2999 static int
    3000 isNew (const tr_peer * peer)
    3001 {
    3002   return peer && peer->io && tr_peerIoGetAge (peer->io) < 45;
     3018static bool
     3019isNew (const tr_peerMsgs * msgs)
     3020{
     3021  return (msgs != NULL) && (tr_peerMsgsGetConnectionAge (msgs) < 45);
    30033022}
    30043023
     
    30663085    {
    30673086      tr_peer * peer = peers[i];
     3087      tr_peerMsgs * msgs = PEER_MSGS (peer);
     3088
    30683089      struct peer_atom * atom = peer->atom;
    30693090
    30703091      if (peerIsSeed (peer)) /* choke seeds and partial seeds */
    30713092        {
    3072           tr_peerMsgsSetChoke (peer->msgs, true);
     3093          tr_peerMsgsSetChoke (PEER_MSGS(peer), true);
    30733094        }
    30743095      else if (chokeAll) /* choke everyone if we're not uploading */
    30753096        {
    3076           tr_peerMsgsSetChoke (peer->msgs, true);
     3097          tr_peerMsgsSetChoke (PEER_MSGS(peer), true);
    30773098        }
    3078       else if (peer != s->optimistic)
     3099      else if (msgs != s->optimistic)
    30793100        {
    30803101          struct ChokeData * n = &choke[size++];
    3081           n->peer         = peer;
    3082           n->isInterested = peer->peerIsInterested;
    3083           n->wasChoked    = peer->peerIsChoked;
     3102          n->msgs         = msgs;
     3103          n->isInterested = tr_peerMsgsIsPeerInterested (msgs);
     3104          n->wasChoked    = tr_peerMsgsIsPeerChoked (msgs);
    30843105          n->rate         = getRate (s->tor, atom, now);
    30853106          n->salt         = tr_cryptoWeakRandInt (INT_MAX);
     
    31243145          if (choke[i].isInterested)
    31253146            {
    3126               const tr_peer * peer = choke[i].peer;
     3147              const tr_peerMsgs * msgs = choke[i].msgs;
    31273148              int x = 1, y;
    3128               if (isNew (peer)) x *= 3;
     3149              if (isNew (msgs)) x *= 3;
    31293150              for (y=0; y<x; ++y)
    31303151                tr_ptrArrayAppend (&randPool, &choke[i]);
     
    31363157          c = tr_ptrArrayNth (&randPool, tr_cryptoWeakRandInt (n));
    31373158          c->isChoked = false;
    3138           s->optimistic = c->peer;
     3159          s->optimistic = c->msgs;
    31393160          s->optimisticUnchokeTimeScaler = OPTIMISTIC_UNCHOKE_MULTIPLIER;
    31403161        }
     
    31443165
    31453166  for (i=0; i<size; ++i)
    3146     tr_peerMsgsSetChoke (choke[i].peer->msgs, choke[i].isChoked);
     3167    tr_peerMsgsSetChoke (choke[i].msgs, choke[i].isChoked);
    31473168
    31483169  /* cleanup */
     
    33063327
    33073328  assert (removed == peer);
    3308   peerDelete (s, removed);
     3329  tr_peerFree (removed);
    33093330}
    33103331
     
    33333354    }
    33343355
    3335   tordbg (s, "removing bad peer %s", tr_peerIoGetAddrStr (peer->io));
     3356  tordbg (s, "removing bad peer %s", tr_atomAddrStr (peer->atom));
    33363357  removePeer (s, peer);
    33373358}
     
    35553576
    35563577      for (j=0; j<tr_ptrArraySize (&s->peers); ++j)
    3557         {
    3558           tr_peer * peer = tr_ptrArrayNth (&s->peers, j);
    3559           tr_peerMsgsPulse (peer->msgs);
    3560         }
     3578        tr_peerMsgsPulse (tr_ptrArrayNth (&s->peers, j));
    35613579    }
    35623580}
  • trunk/libtransmission/peer-mgr.h

    r13948 r13954  
    6666tr_pex;
    6767
    68 
     68struct peer_atom;
    6969struct tr_peerIo;
    70 struct tr_peermsgs;
    71 
    72 /* opaque forward declaration */
    73 struct peer_atom;
    74 
    75 void tr_peerConstruct (struct tr_peer * peer);
    76 
    77 void tr_peerDestruct (tr_torrent * tor, struct tr_peer * peer);
    78 
     70struct tr_peerMsgs;
     71struct tr_swarm;
    7972
    8073static inline bool
    8174tr_isPex (const tr_pex * pex)
    8275{
    83     return pex && tr_address_is_valid (&pex->addr);
     76  return pex && tr_address_is_valid (&pex->addr);
    8477}
    8578
     
    8881int tr_pexCompare (const void * a, const void * b);
    8982
    90 tr_peerMgr* tr_peerMgrNew (tr_session *);
    91 
    92 void tr_peerMgrFree (tr_peerMgr * manager);
    93 
    94 bool tr_peerMgrPeerIsSeed (const tr_torrent * tor,
    95                            const tr_address * addr);
    96 
    97 void tr_peerMgrSetUtpSupported (tr_torrent       * tor,
    98                                 const tr_address * addr);
    99 
    100 void tr_peerMgrSetUtpFailed (tr_torrent *tor,
    101                              const tr_address *addr,
    102                              bool failed);
    103 
    104 void tr_peerMgrGetNextRequests (tr_torrent          * torrent,
    105                                 tr_peer             * peer,
    106                                 int                   numwant,
    107                                 tr_block_index_t    * setme,
    108                                 int                 * numgot,
    109                                 bool                  get_intervals);
    110 
    111 bool tr_peerMgrDidPeerRequest (const tr_torrent  * torrent,
    112                                const tr_peer     * peer,
    113                                tr_block_index_t    block);
    114 
    115 void tr_peerMgrRebuildRequests (tr_torrent * torrent);
    116 
    117 void tr_peerMgrAddIncoming (tr_peerMgr  * manager,
    118                             tr_address  * addr,
    119                             tr_port       port,
    120                             int           socket,
    121                             struct UTPSocket *utp_socket);
    122 
    123 tr_pex * tr_peerMgrCompactToPex (const void    * compact,
    124                                  size_t          compactLen,
    125                                  const uint8_t * added_f,
    126                                  size_t          added_f_len,
    127                                  size_t        * setme_pex_count);
    128 
    129 tr_pex * tr_peerMgrCompact6ToPex (const void    * compact,
    130                                   size_t          compactLen,
    131                                   const uint8_t * added_f,
    132                                   size_t          added_f_len,
    133                                   size_t        * pexCount);
    134 
    135 tr_pex * tr_peerMgrArrayToPex (const void * array,
    136                                size_t       arrayLen,
    137                                size_t      * setme_pex_count);
     83tr_peerMgr * tr_peerMgrNew                  (tr_session          * session);
     84
     85void         tr_peerMgrFree                 (tr_peerMgr          * manager);
     86
     87bool         tr_peerMgrPeerIsSeed           (const tr_torrent    * tor,
     88                                             const tr_address    * addr);
     89
     90void         tr_peerMgrSetUtpSupported      (tr_torrent          * tor,
     91                                             const tr_address    * addr);
     92
     93void         tr_peerMgrSetUtpFailed         (tr_torrent          * tor,
     94                                             const tr_address    * addr,
     95                                             bool                  failed);
     96
     97void         tr_peerMgrGetNextRequests      (tr_torrent          * torrent,
     98                                             tr_peer             * peer,
     99                                             int                   numwant,
     100                                             tr_block_index_t    * setme,
     101                                             int                 * numgot,
     102                                             bool                  get_intervals);
     103
     104bool         tr_peerMgrDidPeerRequest       (const tr_torrent    * torrent,
     105                                             const tr_peer       * peer,
     106                                             tr_block_index_t      block);
     107
     108void         tr_peerMgrRebuildRequests      (tr_torrent          * torrent);
     109
     110void         tr_peerMgrAddIncoming          (tr_peerMgr          * manager,
     111                                             tr_address          * addr,
     112                                             tr_port               port,
     113                                             int                   socket,
     114                                             struct UTPSocket    * utp_socket);
     115
     116tr_pex *     tr_peerMgrCompactToPex         (const void          * compact,
     117                                             size_t                compactLen,
     118                                             const uint8_t      * added_f,
     119                                             size_t                added_f_len,
     120                                             size_t              * setme_pex_count);
     121
     122tr_pex *     tr_peerMgrCompact6ToPex        (const void          * compact,
     123                                             size_t                compactLen,
     124                                             const uint8_t      * added_f,
     125                                             size_t                added_f_len,
     126                                             size_t              * pexCount);
     127
     128tr_pex *     tr_peerMgrArrayToPex           (const void          * array,
     129                                             size_t                arrayLen,
     130                                             size_t              * setme_pex_count);
    138131
    139132/**
    140133 * @param seedProbability [0..100] for likelihood that the peer is a seed; -1 for unknown
    141134 */
    142 void tr_peerMgrAddPex (tr_torrent     * tor,
    143                        uint8_t          from,
    144                        const tr_pex   * pex,
    145                        int8_t           seedProbability);
    146 
    147 void tr_peerMgrMarkAllAsSeeds (tr_torrent * tor);
     135void         tr_peerMgrAddPex               (tr_torrent          * tor,
     136                                             uint8_t               from,
     137                                             const tr_pex        * pex,
     138                                             int8_t                seedProbability);
     139
     140void         tr_peerMgrMarkAllAsSeeds       (tr_torrent          * tor);
    148141
    149142enum
    150143{
    151     TR_PEERS_CONNECTED,
    152     TR_PEERS_INTERESTING
     144  TR_PEERS_CONNECTED,
     145  TR_PEERS_INTERESTING
    153146};
    154147
    155 int  tr_peerMgrGetPeers (tr_torrent      * tor,
    156                          tr_pex         ** setme_pex,
    157                          uint8_t           address_type,
    158                          uint8_t           peer_list_mode,
    159                          int               max_peer_count);
    160 
    161 void tr_peerMgrStartTorrent (tr_torrent * tor);
    162 
    163 void tr_peerMgrStopTorrent (tr_torrent * tor);
    164 
    165 void tr_peerMgrAddTorrent (tr_peerMgr         * manager,
    166                            struct tr_torrent  * tor);
    167 
    168 void tr_peerMgrRemoveTorrent (tr_torrent * tor);
    169 
    170 void tr_peerMgrTorrentAvailability (const tr_torrent   * tor,
    171                                     int8_t             * tab,
    172                                     unsigned int         tabCount);
    173 
    174 uint64_t tr_peerMgrGetDesiredAvailable (const tr_torrent * tor);
    175 
    176 void tr_peerMgrOnTorrentGotMetainfo (tr_torrent * tor);
    177 
    178 void tr_peerMgrOnBlocklistChanged (tr_peerMgr * manager);
    179 
    180 void tr_peerMgrTorrentStats (tr_torrent * tor,
    181                              int * setmePeersConnected,
    182                              int * setmeWebseedsSendingToUs,
    183                              int * setmePeersSendingToUs,
    184                              int * setmePeersGettingFromUs,
    185                              int * setmePeersFrom); /* TR_PEER_FROM__MAX */
    186 
    187 struct tr_peer_stat* tr_peerMgrPeerStats (const tr_torrent * tor,
    188                                           int              * setmeCount);
    189 
    190 double* tr_peerMgrWebSpeeds_KBps (const tr_torrent * tor);
    191 
    192 
    193 unsigned int tr_peerGetPieceSpeed_Bps (const tr_peer    * peer,
    194                                        uint64_t           now,
    195                                        tr_direction       direction);
    196 
    197 void tr_peerMgrClearInterest (tr_torrent * tor);
    198 
    199 void tr_peerMgrGotBadPiece (tr_torrent * tor, tr_piece_index_t pieceIndex);
    200 
    201 void tr_peerMgrPieceCompleted (tr_torrent * tor, tr_piece_index_t pieceIndex);
     148int          tr_peerMgrGetPeers             (tr_torrent          * tor,
     149                                             tr_pex             ** setme_pex,
     150                                             uint8_t               address_type,
     151                                             uint8_t               peer_list_mode,
     152                                             int                   max_peer_count);
     153
     154void         tr_peerMgrStartTorrent         (tr_torrent          * tor);
     155
     156void         tr_peerMgrStopTorrent          (tr_torrent          * tor);
     157
     158void         tr_peerMgrAddTorrent           (tr_peerMgr          * manager,
     159                                             struct tr_torrent   * tor);
     160
     161void         tr_peerMgrRemoveTorrent        (tr_torrent          * tor);
     162
     163void         tr_peerMgrTorrentAvailability  (const tr_torrent    * tor,
     164                                             int8_t              * tab,
     165                                             unsigned int          tabCount);
     166
     167uint64_t     tr_peerMgrGetDesiredAvailable  (const tr_torrent    * tor);
     168
     169void         tr_peerMgrOnTorrentGotMetainfo (tr_torrent         * tor);
     170
     171void         tr_peerMgrOnBlocklistChanged   (tr_peerMgr         * manager);
     172
     173void         tr_peerMgrTorrentStats         (tr_torrent         * tor,
     174                                             int                * setmePeersConnected,
     175                                             int                * setmeWebseedsSendingToUs,
     176                                             int                * setmePeersSendingToUs,
     177                                             int                * setmePeersGettingFromUs,
     178                                             int                * setmePeersFrom); /* TR_PEER_FROM__MAX */
     179
     180struct tr_peer_stat * tr_peerMgrPeerStats   (const tr_torrent   * tor,
     181                                             int                * setmeCount);
     182
     183double *     tr_peerMgrWebSpeeds_KBps       (const tr_torrent   * tor);
     184
     185unsigned int tr_peerGetPieceSpeed_Bps       (const tr_peer      * peer,
     186                                             uint64_t             now,
     187                                             tr_direction         direction);
     188
     189void         tr_peerMgrClearInterest        (tr_torrent         * tor);
     190
     191void         tr_peerMgrGotBadPiece          (tr_torrent         * tor,
     192                                             tr_piece_index_t     pieceIndex);
     193
     194void         tr_peerMgrPieceCompleted       (tr_torrent         * tor,
     195                                             tr_piece_index_t     pieceIndex);
    202196 
    203197
  • trunk/libtransmission/peer-msgs.c

    r13949 r13954  
    4343enum
    4444{
    45     BT_CHOKE                = 0,
    46     BT_UNCHOKE              = 1,
    47     BT_INTERESTED           = 2,
    48     BT_NOT_INTERESTED       = 3,
    49     BT_HAVE                 = 4,
    50     BT_BITFIELD             = 5,
    51     BT_REQUEST              = 6,
    52     BT_PIECE                = 7,
    53     BT_CANCEL               = 8,
    54     BT_PORT                 = 9,
    55 
    56     BT_FEXT_SUGGEST         = 13,
    57     BT_FEXT_HAVE_ALL        = 14,
    58     BT_FEXT_HAVE_NONE       = 15,
    59     BT_FEXT_REJECT          = 16,
    60     BT_FEXT_ALLOWED_FAST    = 17,
    61 
    62     BT_LTEP                 = 20,
    63 
    64     LTEP_HANDSHAKE          = 0,
    65 
    66     UT_PEX_ID               = 1,
    67     UT_METADATA_ID          = 3,
    68 
    69     MAX_PEX_PEER_COUNT      = 50,
    70 
    71     MIN_CHOKE_PERIOD_SEC    = 10,
    72 
    73     /* idle seconds before we send a keepalive */
    74     KEEPALIVE_INTERVAL_SECS = 100,
    75 
    76     PEX_INTERVAL_SECS       = 90, /* sec between sendPex () calls */
    77 
    78     REQQ                    = 512,
    79 
    80     METADATA_REQQ           = 64,
    81 
    82     /* used in lowering the outMessages queue period */
    83     IMMEDIATE_PRIORITY_INTERVAL_SECS = 0,
    84     HIGH_PRIORITY_INTERVAL_SECS = 2,
    85     LOW_PRIORITY_INTERVAL_SECS = 10,
    86 
    87     /* number of pieces we'll allow in our fast set */
    88     MAX_FAST_SET_SIZE = 3,
    89 
    90     /* how many blocks to keep prefetched per peer */
    91     PREFETCH_SIZE = 18,
    92 
    93     /* when we're making requests from another peer,
    94        batch them together to send enough requests to
    95        meet our bandwidth goals for the next N seconds */
    96     REQUEST_BUF_SECS = 10,
    97 
    98     /* defined in BEP #9 */
    99     METADATA_MSG_TYPE_REQUEST = 0,
    100     METADATA_MSG_TYPE_DATA = 1,
    101     METADATA_MSG_TYPE_REJECT = 2
     45  BT_CHOKE                = 0,
     46  BT_UNCHOKE              = 1,
     47  BT_INTERESTED           = 2,
     48  BT_NOT_INTERESTED       = 3,
     49  BT_HAVE                 = 4,
     50  BT_BITFIELD             = 5,
     51  BT_REQUEST              = 6,
     52  BT_PIECE                = 7,
     53  BT_CANCEL               = 8,
     54  BT_PORT                 = 9,
     55
     56  BT_FEXT_SUGGEST         = 13,
     57  BT_FEXT_HAVE_ALL        = 14,
     58  BT_FEXT_HAVE_NONE       = 15,
     59  BT_FEXT_REJECT          = 16,
     60  BT_FEXT_ALLOWED_FAST    = 17,
     61
     62  BT_LTEP                 = 20,
     63
     64  LTEP_HANDSHAKE          = 0,
     65
     66  UT_PEX_ID               = 1,
     67  UT_METADATA_ID          = 3,
     68
     69  MAX_PEX_PEER_COUNT      = 50,
     70
     71  MIN_CHOKE_PERIOD_SEC    = 10,
     72
     73  /* idle seconds before we send a keepalive */
     74  KEEPALIVE_INTERVAL_SECS = 100,
     75
     76  PEX_INTERVAL_SECS       = 90, /* sec between sendPex () calls */
     77
     78  REQQ                    = 512,
     79
     80  METADATA_REQQ           = 64,
     81
     82  MAGIC_NUMBER            = 21549,
     83
     84  /* used in lowering the outMessages queue period */
     85  IMMEDIATE_PRIORITY_INTERVAL_SECS = 0,
     86  HIGH_PRIORITY_INTERVAL_SECS = 2,
     87  LOW_PRIORITY_INTERVAL_SECS = 10,
     88
     89  /* number of pieces we'll allow in our fast set */
     90  MAX_FAST_SET_SIZE = 3,
     91
     92  /* how many blocks to keep prefetched per peer */
     93  PREFETCH_SIZE = 18,
     94
     95  /* when we're making requests from another peer,
     96     batch them together to send enough requests to
     97     meet our bandwidth goals for the next N seconds */
     98  REQUEST_BUF_SECS = 10,
     99
     100  /* defined in BEP #9 */
     101  METADATA_MSG_TYPE_REQUEST = 0,
     102  METADATA_MSG_TYPE_DATA = 1,
     103  METADATA_MSG_TYPE_REJECT = 2
    102104};
    103105
    104106enum
    105107{
    106     AWAITING_BT_LENGTH,
    107     AWAITING_BT_ID,
    108     AWAITING_BT_MESSAGE,
    109     AWAITING_BT_PIECE
     108  AWAITING_BT_LENGTH,
     109  AWAITING_BT_ID,
     110  AWAITING_BT_MESSAGE,
     111  AWAITING_BT_PIECE
    110112};
    111113
     
    118120encryption_preference_t;
    119121
    120 
    121 
    122122/**
    123123***
     
    126126struct peer_request
    127127{
    128     uint32_t    index;
    129     uint32_t    offset;
    130     uint32_t    length;
     128  uint32_t index;
     129  uint32_t offset;
     130  uint32_t length;
    131131};
    132132
     
    136136            struct peer_request  * setme)
    137137{
    138     tr_torrentGetBlockLocation (tor, block, &setme->index,
    139                                             &setme->offset,
    140                                             &setme->length);
     138  tr_torrentGetBlockLocation (tor, block, &setme->index,
     139                                          &setme->offset,
     140                                          &setme->length);
    141141}
    142142
     
    149149struct tr_incoming
    150150{
    151     uint8_t                id;
    152     uint32_t               length; /* includes the +1 for id length */
    153     struct peer_request    blockReq; /* metadata for incoming blocks */
    154     struct evbuffer *      block; /* piece data for incoming blocks */
     151  uint8_t                id;
     152  uint32_t               length; /* includes the +1 for id length */
     153  struct peer_request    blockReq; /* metadata for incoming blocks */
     154  struct evbuffer      * block; /* piece data for incoming blocks */
    155155};
    156156
     
    169169 * @see tr_peer
    170170 */
    171 struct tr_peermsgs
    172 {
    173     bool            peerSupportsPex;
    174     bool            peerSupportsMetadataXfer;
    175     bool            clientSentLtepHandshake;
    176     bool            peerSentLtepHandshake;
    177 
    178     /*bool          haveFastSet;*/
    179 
    180     int             desiredRequestCount;
    181 
    182     int             prefetchCount;
    183 
    184     /* how long the outMessages batch should be allowed to grow before
    185      * it's flushed -- some messages (like requests >:) should be sent
    186      * very quickly; others aren't as urgent. */
    187     int8_t          outMessagesBatchPeriod;
    188 
    189     uint8_t         state;
    190     uint8_t         ut_pex_id;
    191     uint8_t         ut_metadata_id;
    192     uint16_t        pexCount;
    193     uint16_t        pexCount6;
    194 
    195     tr_port         dht_port;
    196 
    197     encryption_preference_t  encryption_preference;
    198 
    199     size_t                   metadata_size_hint;
     171struct tr_peerMsgs
     172{
     173  struct tr_peer peer; /* parent */
     174
     175  uint16_t magic_number;
     176
     177  /* Whether or not we've choked this peer. */
     178  bool peer_is_choked;
     179
     180  /* whether or not the peer has indicated it will download from us. */
     181  bool peer_is_interested;
     182
     183  /* whether or the peer is choking us. */
     184  bool client_is_choked;
     185
     186  /* whether or not we've indicated to the peer that we would download from them if unchoked. */
     187  bool client_is_interested;
     188
     189
     190  bool peerSupportsPex;
     191  bool peerSupportsMetadataXfer;
     192  bool clientSentLtepHandshake;
     193  bool peerSentLtepHandshake;
     194
     195  /*bool haveFastSet;*/
     196
     197  int desiredRequestCount;
     198
     199  int prefetchCount;
     200
     201  /* how long the outMessages batch should be allowed to grow before
     202   * it's flushed -- some messages (like requests >:) should be sent
     203   * very quickly; others aren't as urgent. */
     204  int8_t          outMessagesBatchPeriod;
     205
     206  uint8_t         state;
     207  uint8_t         ut_pex_id;
     208  uint8_t         ut_metadata_id;
     209  uint16_t        pexCount;
     210  uint16_t        pexCount6;
     211
     212  tr_port         dht_port;
     213
     214  encryption_preference_t  encryption_preference;
     215
     216  size_t                   metadata_size_hint;
    200217#if 0
    201     size_t                 fastsetSize;
    202     tr_piece_index_t       fastset[MAX_FAST_SET_SIZE];
     218  size_t                 fastsetSize;
     219  tr_piece_index_t       fastset[MAX_FAST_SET_SIZE];
    203220#endif
    204221
    205     tr_peer *              peer;
    206 
    207     tr_torrent *           torrent;
    208 
    209     tr_peer_callback      * callback;
    210     void                  * callbackData;
    211 
    212     struct evbuffer *      outMessages; /* all the non-piece messages */
    213 
    214     struct peer_request    peerAskedFor[REQQ];
    215 
    216     int                    peerAskedForMetadata[METADATA_REQQ];
    217     int                    peerAskedForMetadataCount;
    218 
    219     tr_pex               * pex;
    220     tr_pex               * pex6;
    221 
    222     /*time_t                 clientSentPexAt;*/
    223     time_t                 clientSentAnythingAt;
    224 
    225     /* when we started batching the outMessages */
    226     time_t                outMessagesBatchedAt;
    227 
    228     struct tr_incoming    incoming;
    229 
    230     /* if the peer supports the Extension Protocol in BEP 10 and
    231        supplied a reqq argument, it's stored here. Otherwise, the
    232        value is zero and should be ignored. */
    233     int64_t               reqq;
    234 
    235     struct event        * pexTimer;
     222  tr_torrent *           torrent;
     223
     224  tr_peer_callback      * callback;
     225  void                  * callbackData;
     226
     227  struct evbuffer *      outMessages; /* all the non-piece messages */
     228
     229  struct peer_request    peerAskedFor[REQQ];
     230
     231  int peerAskedForMetadata[METADATA_REQQ];
     232  int peerAskedForMetadataCount;
     233
     234  tr_pex * pex;
     235  tr_pex * pex6;
     236
     237  /*time_t clientSentPexAt;*/
     238  time_t clientSentAnythingAt;
     239
     240  time_t chokeChangedAt;
     241
     242  /* when we started batching the outMessages */
     243  time_t outMessagesBatchedAt;
     244
     245  struct tr_incoming    incoming;
     246
     247  /* if the peer supports the Extension Protocol in BEP 10 and
     248     supplied a reqq argument, it's stored here. Otherwise, the
     249     value is zero and should be ignored. */
     250  int64_t reqq;
     251
     252  struct event * pexTimer;
     253
     254  struct tr_peerIo * io;
    236255};
    237256
     
    241260
    242261static inline tr_session*
    243 getSession (struct tr_peermsgs * msgs)
    244 {
    245     return msgs->torrent->session;
     262getSession (struct tr_peerMsgs * msgs)
     263{
     264  return msgs->torrent->session;
    246265}
    247266
     
    252271static void
    253272myDebug (const char * file, int line,
    254          const struct tr_peermsgs * msgs,
     273         const struct tr_peerMsgs * msgs,
    255274         const char * fmt, ...)
    256275{
    257     FILE * fp = tr_logGetFile ();
    258 
    259     if (fp)
    260     {
    261         va_list           args;
    262         char              timestr[64];
    263         struct evbuffer * buf = evbuffer_new ();
    264         char *            base = tr_basename (file);
    265         char *            message;
    266 
    267         evbuffer_add_printf (buf, "[%s] %s - %s [%s]: ",
    268                              tr_logGetTimeStr (timestr, sizeof (timestr)),
    269                              tr_torrentName (msgs->torrent),
    270                              tr_peerIoGetAddrStr (msgs->peer->io),
    271                              tr_quark_get_string (msgs->peer->client, NULL));
    272         va_start (args, fmt);
    273         evbuffer_add_vprintf (buf, fmt, args);
    274         va_end (args);
    275         evbuffer_add_printf (buf, " (%s:%d)\n", base, line);
    276 
    277         message = evbuffer_free_to_str (buf);
    278         fputs (message, fp);
    279 
    280         tr_free (base);
    281         tr_free (message);
     276  FILE * fp = tr_logGetFile ();
     277
     278  if (fp)
     279    {
     280      va_list           args;
     281      char              timestr[64];
     282      struct evbuffer * buf = evbuffer_new ();
     283      char *            base = tr_basename (file);
     284      char *            message;
     285
     286      evbuffer_add_printf (buf, "[%s] %s - %s [%s]: ",
     287                           tr_logGetTimeStr (timestr, sizeof (timestr)),
     288                           tr_torrentName (msgs->torrent),
     289                           tr_peerIoGetAddrStr (msgs->io),
     290                           tr_quark_get_string (msgs->peer.client, NULL));
     291      va_start (args, fmt);
     292      evbuffer_add_vprintf (buf, fmt, args);
     293      va_end (args);
     294      evbuffer_add_printf (buf, " (%s:%d)\n", base, line);
     295
     296      message = evbuffer_free_to_str (buf);
     297      fputs (message, fp);
     298
     299      tr_free (base);
     300      tr_free (message);
    282301    }
    283302}
     
    296315
    297316static void
    298 pokeBatchPeriod (tr_peermsgs * msgs, int interval)
    299 {
    300     if (msgs->outMessagesBatchPeriod > interval)
    301     {
    302         msgs->outMessagesBatchPeriod = interval;
    303         dbgmsg (msgs, "lowering batch interval to %d seconds", interval);
    304     }
    305 }
    306 
    307 static void
    308 dbgOutMessageLen (tr_peermsgs * msgs)
    309 {
    310     dbgmsg (msgs, "outMessage size is now %zu", evbuffer_get_length (msgs->outMessages));
    311 }
    312 
    313 static void
    314 protocolSendReject (tr_peermsgs * msgs, const struct peer_request * req)
    315 {
    316     struct evbuffer * out = msgs->outMessages;
    317 
    318     assert (tr_peerIoSupportsFEXT (msgs->peer->io));
    319 
    320     evbuffer_add_uint32 (out, sizeof (uint8_t) + 3 * sizeof (uint32_t));
    321     evbuffer_add_uint8 (out, BT_FEXT_REJECT);
    322     evbuffer_add_uint32 (out, req->index);
    323     evbuffer_add_uint32 (out, req->offset);
    324     evbuffer_add_uint32 (out, req->length);
    325 
    326     dbgmsg (msgs, "rejecting %u:%u->%u...", req->index, req->offset, req->length);
    327     dbgOutMessageLen (msgs);
    328 }
    329 
    330 static void
    331 protocolSendRequest (tr_peermsgs * msgs, const struct peer_request * req)
    332 {
    333     struct evbuffer * out = msgs->outMessages;
    334 
    335     evbuffer_add_uint32 (out, sizeof (uint8_t) + 3 * sizeof (uint32_t));
    336     evbuffer_add_uint8 (out, BT_REQUEST);
    337     evbuffer_add_uint32 (out, req->index);
    338     evbuffer_add_uint32 (out, req->offset);
    339     evbuffer_add_uint32 (out, req->length);
    340 
    341     dbgmsg (msgs, "requesting %u:%u->%u...", req->index, req->offset, req->length);
    342     dbgOutMessageLen (msgs);
    343     pokeBatchPeriod (msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS);
    344 }
    345 
    346 static void
    347 protocolSendCancel (tr_peermsgs * msgs, const struct peer_request * req)
    348 {
    349     struct evbuffer * out = msgs->outMessages;
    350 
    351     evbuffer_add_uint32 (out, sizeof (uint8_t) + 3 * sizeof (uint32_t));
    352     evbuffer_add_uint8 (out, BT_CANCEL);
    353     evbuffer_add_uint32 (out, req->index);
    354     evbuffer_add_uint32 (out, req->offset);
    355     evbuffer_add_uint32 (out, req->length);
    356 
    357     dbgmsg (msgs, "cancelling %u:%u->%u...", req->index, req->offset, req->length);
    358     dbgOutMessageLen (msgs);
    359     pokeBatchPeriod (msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS);
    360 }
    361 
    362 static void
    363 protocolSendPort (tr_peermsgs *msgs, uint16_t port)
    364 {
    365     struct evbuffer * out = msgs->outMessages;
    366 
    367     dbgmsg (msgs, "sending Port %u", port);
    368     evbuffer_add_uint32 (out, 3);
    369     evbuffer_add_uint8 (out, BT_PORT);
    370     evbuffer_add_uint16 (out, port);
    371 }
    372 
    373 static void
    374 protocolSendHave (tr_peermsgs * msgs, uint32_t index)
    375 {
    376     struct evbuffer * out = msgs->outMessages;
    377 
    378     evbuffer_add_uint32 (out, sizeof (uint8_t) + sizeof (uint32_t));
    379     evbuffer_add_uint8 (out, BT_HAVE);
    380     evbuffer_add_uint32 (out, index);
    381 
    382     dbgmsg (msgs, "sending Have %u", index);
    383     dbgOutMessageLen (msgs);
    384     pokeBatchPeriod (msgs, LOW_PRIORITY_INTERVAL_SECS);
     317pokeBatchPeriod (tr_peerMsgs * msgs, int interval)
     318{
     319  if (msgs->outMessagesBatchPeriod > interval)
     320    {
     321      msgs->outMessagesBatchPeriod = interval;
     322      dbgmsg (msgs, "lowering batch interval to %d seconds", interval);
     323    }
     324}
     325
     326static void
     327dbgOutMessageLen (tr_peerMsgs * msgs)
     328{
     329  dbgmsg (msgs, "outMessage size is now %zu", evbuffer_get_length (msgs->outMessages));
     330}
     331
     332static void
     333protocolSendReject (tr_peerMsgs * msgs, const struct peer_request * req)
     334{
     335  struct evbuffer * out = msgs->outMessages;
     336
     337  assert (tr_peerIoSupportsFEXT (msgs->io));
     338
     339  evbuffer_add_uint32 (out, sizeof (uint8_t) + 3 * sizeof (uint32_t));
     340  evbuffer_add_uint8 (out, BT_FEXT_REJECT);
     341  evbuffer_add_uint32 (out, req->index);
     342  evbuffer_add_uint32 (out, req->offset);
     343  evbuffer_add_uint32 (out, req->length);
     344
     345  dbgmsg (msgs, "rejecting %u:%u->%u...", req->index, req->offset, req->length);
     346  dbgOutMessageLen (msgs);
     347}
     348
     349static void
     350protocolSendRequest (tr_peerMsgs * msgs, const struct peer_request * req)
     351{
     352  struct evbuffer * out = msgs->outMessages;
     353
     354  evbuffer_add_uint32 (out, sizeof (uint8_t) + 3 * sizeof (uint32_t));
     355  evbuffer_add_uint8 (out, BT_REQUEST);
     356  evbuffer_add_uint32 (out, req->index);
     357  evbuffer_add_uint32 (out, req->offset);
     358  evbuffer_add_uint32 (out, req->length);
     359
     360  dbgmsg (msgs, "requesting %u:%u->%u...", req->index, req->offset, req->length);
     361  dbgOutMessageLen (msgs);
     362  pokeBatchPeriod (msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS);
     363}
     364
     365static void
     366protocolSendCancel (tr_peerMsgs * msgs, const struct peer_request * req)
     367{
     368  struct evbuffer * out = msgs->outMessages;
     369
     370  evbuffer_add_uint32 (out, sizeof (uint8_t) + 3 * sizeof (uint32_t));
     371  evbuffer_add_uint8 (out, BT_CANCEL);
     372  evbuffer_add_uint32 (out, req->index);
     373  evbuffer_add_uint32 (out, req->offset);
     374  evbuffer_add_uint32 (out, req->length);
     375
     376  dbgmsg (msgs, "cancelling %u:%u->%u...", req->index, req->offset, req->length);
     377  dbgOutMessageLen (msgs);
     378  pokeBatchPeriod (msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS);
     379}
     380
     381static void
     382protocolSendPort (tr_peerMsgs *msgs, uint16_t port)
     383{
     384  struct evbuffer * out = msgs->outMessages;
     385
     386  dbgmsg (msgs, "sending Port %u", port);
     387  evbuffer_add_uint32 (out, 3);
     388  evbuffer_add_uint8 (out, BT_PORT);
     389  evbuffer_add_uint16 (out, port);
     390}
     391
     392static void
     393protocolSendHave (tr_peerMsgs * msgs, uint32_t index)
     394{
     395  struct evbuffer * out = msgs->outMessages;
     396
     397  evbuffer_add_uint32 (out, sizeof (uint8_t) + sizeof (uint32_t));
     398  evbuffer_add_uint8 (out, BT_HAVE);
     399  evbuffer_add_uint32 (out, index);
     400
     401  dbgmsg (msgs, "sending Have %u", index);
     402  dbgOutMessageLen (msgs);
     403  pokeBatchPeriod (msgs, LOW_PRIORITY_INTERVAL_SECS);
    385404}
    386405
    387406#if 0
    388407static void
    389 protocolSendAllowedFast (tr_peermsgs * msgs, uint32_t pieceIndex)
    390 {
    391     tr_peerIo       * io  = msgs->peer->io;
    392     struct evbuffer * out = msgs->outMessages;
    393 
    394     assert (tr_peerIoSupportsFEXT (msgs->peer->io));
    395 
    396     evbuffer_add_uint32 (io, out, sizeof (uint8_t) + sizeof (uint32_t));
    397     evbuffer_add_uint8 (io, out, BT_FEXT_ALLOWED_FAST);
    398     evbuffer_add_uint32 (io, out, pieceIndex);
    399 
    400     dbgmsg (msgs, "sending Allowed Fast %u...", pieceIndex);
    401     dbgOutMessageLen (msgs);
     408protocolSendAllowedFast (tr_peerMsgs * msgs, uint32_t pieceIndex)
     409{
     410  tr_peerIo       * io  = msgs->io;
     411  struct evbuffer * out = msgs->outMessages;
     412
     413  assert (tr_peerIoSupportsFEXT (msgs->io));
     414
     415  evbuffer_add_uint32 (io, out, sizeof (uint8_t) + sizeof (uint32_t));
     416  evbuffer_add_uint8 (io, out, BT_FEXT_ALLOWED_FAST);
     417  evbuffer_add_uint32 (io, out, pieceIndex);
     418
     419  dbgmsg (msgs, "sending Allowed Fast %u...", pieceIndex);
     420  dbgOutMessageLen (msgs);
    402421}
    403422#endif
    404423
    405424static void
    406 protocolSendChoke (tr_peermsgs * msgs, int choke)
    407 {
    408     struct evbuffer * out = msgs->outMessages;
    409 
    410     evbuffer_add_uint32 (out, sizeof (uint8_t));
    411     evbuffer_add_uint8 (out, choke ? BT_CHOKE : BT_UNCHOKE);
    412 
    413     dbgmsg (msgs, "sending %s...", choke ? "Choke" : "Unchoke");
    414     dbgOutMessageLen (msgs);
    415     pokeBatchPeriod (msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS);
    416 }
    417 
    418 static void
    419 protocolSendHaveAll (tr_peermsgs * msgs)
    420 {
    421     struct evbuffer * out = msgs->outMessages;
    422 
    423     assert (tr_peerIoSupportsFEXT (msgs->peer->io));
    424 
    425     evbuffer_add_uint32 (out, sizeof (uint8_t));
    426     evbuffer_add_uint8 (out, BT_FEXT_HAVE_ALL);
    427 
    428     dbgmsg (msgs, "sending HAVE_ALL...");
    429     dbgOutMessageLen (msgs);
    430     pokeBatchPeriod (msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS);
    431 }
    432 
    433 static void
    434 protocolSendHaveNone (tr_peermsgs * msgs)
    435 {
    436     struct evbuffer * out = msgs->outMessages;
    437 
    438     assert (tr_peerIoSupportsFEXT (msgs->peer->io));
    439 
    440     evbuffer_add_uint32 (out, sizeof (uint8_t));
    441     evbuffer_add_uint8 (out, BT_FEXT_HAVE_NONE);
    442 
    443     dbgmsg (msgs, "sending HAVE_NONE...");
    444     dbgOutMessageLen (msgs);
    445     pokeBatchPeriod (msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS);
     425protocolSendChoke (tr_peerMsgs * msgs, int choke)
     426{
     427  struct evbuffer * out = msgs->outMessages;
     428
     429  evbuffer_add_uint32 (out, sizeof (uint8_t));
     430  evbuffer_add_uint8 (out, choke ? BT_CHOKE : BT_UNCHOKE);
     431
     432  dbgmsg (msgs, "sending %s...", choke ? "Choke" : "Unchoke");
     433  dbgOutMessageLen (msgs);
     434  pokeBatchPeriod (msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS);
     435}
     436
     437static void
     438protocolSendHaveAll (tr_peerMsgs * msgs)
     439{
     440  struct evbuffer * out = msgs->outMessages;
     441
     442  assert (tr_peerIoSupportsFEXT (msgs->io));
     443
     444  evbuffer_add_uint32 (out, sizeof (uint8_t));
     445  evbuffer_add_uint8 (out, BT_FEXT_HAVE_ALL);
     446
     447  dbgmsg (msgs, "sending HAVE_ALL...");
     448  dbgOutMessageLen (msgs);
     449  pokeBatchPeriod (msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS);
     450}
     451
     452static void
     453protocolSendHaveNone (tr_peerMsgs * msgs)
     454{
     455  struct evbuffer * out = msgs->outMessages;
     456
     457  assert (tr_peerIoSupportsFEXT (msgs->io));
     458
     459  evbuffer_add_uint32 (out, sizeof (uint8_t));
     460  evbuffer_add_uint8 (out, BT_FEXT_HAVE_NONE);
     461
     462  dbgmsg (msgs, "sending HAVE_NONE...");
     463  dbgOutMessageLen (msgs);
     464  pokeBatchPeriod (msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS);
    446465}
    447466
     
    451470
    452471static void
    453 publish (tr_peermsgs * msgs, tr_peer_event * e)
    454 {
    455     assert (msgs->peer);
    456     assert (msgs->peer->msgs == msgs);
    457 
    458     if (msgs->callback != NULL)
    459         msgs->callback (msgs->peer, e, msgs->callbackData);
    460 }
    461 
    462 static void
    463 fireError (tr_peermsgs * msgs, int err)
    464 {
    465     tr_peer_event e = TR_PEER_EVENT_INIT;
    466     e.eventType = TR_PEER_ERROR;
    467     e.err = err;
    468     publish (msgs, &e);
    469 }
    470 
    471 static void
    472 fireGotBlock (tr_peermsgs * msgs, const struct peer_request * req)
    473 {
    474     tr_peer_event e = TR_PEER_EVENT_INIT;
    475     e.eventType = TR_PEER_CLIENT_GOT_BLOCK;
    476     e.pieceIndex = req->index;
    477     e.offset = req->offset;
    478     e.length = req->length;
    479     publish (msgs, &e);
    480 }
    481 
    482 static void
    483 fireGotRej (tr_peermsgs * msgs, const struct peer_request * req)
    484 {
    485     tr_peer_event e = TR_PEER_EVENT_INIT;
    486     e.eventType = TR_PEER_CLIENT_GOT_REJ;
    487     e.pieceIndex = req->index;
    488     e.offset = req->offset;
    489     e.length = req->length;
    490     publish (msgs, &e);
    491 }
    492 
    493 static void
    494 fireGotChoke (tr_peermsgs * msgs)
    495 {
    496     tr_peer_event e = TR_PEER_EVENT_INIT;
    497     e.eventType = TR_PEER_CLIENT_GOT_CHOKE;
    498     publish (msgs, &e);
    499 }
    500 
    501 static void
    502 fireClientGotHaveAll (tr_peermsgs * msgs)
    503 {
    504     tr_peer_event e = TR_PEER_EVENT_INIT;
    505     e.eventType = TR_PEER_CLIENT_GOT_HAVE_ALL;
    506     publish (msgs, &e);
    507 }
    508 
    509 static void
    510 fireClientGotHaveNone (tr_peermsgs * msgs)
    511 {
    512     tr_peer_event e = TR_PEER_EVENT_INIT;
    513     e.eventType = TR_PEER_CLIENT_GOT_HAVE_NONE;
    514     publish (msgs, &e);
    515 }
    516 
    517 static void
    518 fireClientGotPieceData (tr_peermsgs * msgs, uint32_t length)
    519 {
    520     tr_peer_event e = TR_PEER_EVENT_INIT;
    521     e.length = length;
    522     e.eventType = TR_PEER_CLIENT_GOT_PIECE_DATA;
    523     publish (msgs, &e);
    524 }
    525 
    526 static void
    527 firePeerGotPieceData (tr_peermsgs * msgs, uint32_t length)
    528 {
    529     tr_peer_event e = TR_PEER_EVENT_INIT;
    530     e.length = length;
    531     e.eventType = TR_PEER_PEER_GOT_PIECE_DATA;
    532     publish (msgs, &e);
    533 }
    534 
    535 static void
    536 fireClientGotSuggest (tr_peermsgs * msgs, uint32_t pieceIndex)
    537 {
    538     tr_peer_event e = TR_PEER_EVENT_INIT;
    539     e.eventType = TR_PEER_CLIENT_GOT_SUGGEST;
    540     e.pieceIndex = pieceIndex;
    541     publish (msgs, &e);
    542 }
    543 
    544 static void
    545 fireClientGotPort (tr_peermsgs * msgs, tr_port port)
    546 {
    547     tr_peer_event e = TR_PEER_EVENT_INIT;
    548     e.eventType = TR_PEER_CLIENT_GOT_PORT;
    549     e.port = port;
    550     publish (msgs, &e);
    551 }
    552 
    553 static void
    554 fireClientGotAllowedFast (tr_peermsgs * msgs, uint32_t pieceIndex)
    555 {
    556     tr_peer_event e = TR_PEER_EVENT_INIT;
    557     e.eventType = TR_PEER_CLIENT_GOT_ALLOWED_FAST;
    558     e.pieceIndex = pieceIndex;
    559     publish (msgs, &e);
    560 }
    561 
    562 static void
    563 fireClientGotBitfield (tr_peermsgs * msgs, tr_bitfield * bitfield)
    564 {
    565     tr_peer_event e = TR_PEER_EVENT_INIT;
    566     e.eventType = TR_PEER_CLIENT_GOT_BITFIELD;
    567     e.bitfield = bitfield;
    568     publish (msgs, &e);
    569 }
    570 
    571 static void
    572 fireClientGotHave (tr_peermsgs * msgs, tr_piece_index_t index)
    573 {
    574     tr_peer_event e = TR_PEER_EVENT_INIT;
    575     e.eventType = TR_PEER_CLIENT_GOT_HAVE;
    576     e.pieceIndex = index;
    577     publish (msgs, &e);
     472publish (tr_peerMsgs * msgs, tr_peer_event * e)
     473{
     474  if (msgs->callback != NULL)
     475    msgs->callback (&msgs->peer, e, msgs->callbackData);
     476}
     477
     478static void
     479fireError (tr_peerMsgs * msgs, int err)
     480{
     481  tr_peer_event e = TR_PEER_EVENT_INIT;
     482  e.eventType = TR_PEER_ERROR;
     483  e.err = err;
     484  publish (msgs, &e);
     485}
     486
     487static void
     488fireGotBlock (tr_peerMsgs * msgs, const struct peer_request * req)
     489{
     490  tr_peer_event e = TR_PEER_EVENT_INIT;
     491  e.eventType = TR_PEER_CLIENT_GOT_BLOCK;
     492  e.pieceIndex = req->index;
     493  e.offset = req->offset;
     494  e.length = req->length;
     495  publish (msgs, &e);
     496}
     497
     498static void
     499fireGotRej (tr_peerMsgs * msgs, const struct peer_request * req)
     500{
     501  tr_peer_event e = TR_PEER_EVENT_INIT;
     502  e.eventType = TR_PEER_CLIENT_GOT_REJ;
     503  e.pieceIndex = req->index;
     504  e.offset = req->offset;
     505  e.length = req->length;
     506  publish (msgs, &e);
     507}
     508
     509static void
     510fireGotChoke (tr_peerMsgs * msgs)
     511{
     512  tr_peer_event e = TR_PEER_EVENT_INIT;
     513  e.eventType = TR_PEER_CLIENT_GOT_CHOKE;
     514  publish (msgs, &e);
     515}
     516
     517static void
     518fireClientGotHaveAll (tr_peerMsgs * msgs)
     519{
     520  tr_peer_event e = TR_PEER_EVENT_INIT;
     521  e.eventType = TR_PEER_CLIENT_GOT_HAVE_ALL;
     522  publish (msgs, &e);
     523}
     524
     525static void
     526fireClientGotHaveNone (tr_peerMsgs * msgs)
     527{
     528  tr_peer_event e = TR_PEER_EVENT_INIT;
     529  e.eventType = TR_PEER_CLIENT_GOT_HAVE_NONE;
     530  publish (msgs, &e);
     531}
     532
     533static void
     534fireClientGotPieceData (tr_peerMsgs * msgs, uint32_t length)
     535{
     536  tr_peer_event e = TR_PEER_EVENT_INIT;
     537  e.length = length;
     538  e.eventType = TR_PEER_CLIENT_GOT_PIECE_DATA;
     539  publish (msgs, &e);
     540}
     541
     542static void
     543firePeerGotPieceData (tr_peerMsgs * msgs, uint32_t length)
     544{
     545  tr_peer_event e = TR_PEER_EVENT_INIT;
     546  e.length = length;
     547  e.eventType = TR_PEER_PEER_GOT_PIECE_DATA;
     548  publish (msgs, &e);
     549}
     550
     551static void
     552fireClientGotSuggest (tr_peerMsgs * msgs, uint32_t pieceIndex)
     553{
     554  tr_peer_event e = TR_PEER_EVENT_INIT;
     555  e.eventType = TR_PEER_CLIENT_GOT_SUGGEST;
     556  e.pieceIndex = pieceIndex;
     557  publish (msgs, &e);
     558}
     559
     560static void
     561fireClientGotPort (tr_peerMsgs * msgs, tr_port port)
     562{
     563  tr_peer_event e = TR_PEER_EVENT_INIT;
     564  e.eventType = TR_PEER_CLIENT_GOT_PORT;
     565  e.port = port;
     566  publish (msgs, &e);
     567}
     568
     569static void
     570fireClientGotAllowedFast (tr_peerMsgs * msgs, uint32_t pieceIndex)
     571{
     572  tr_peer_event e = TR_PEER_EVENT_INIT;
     573  e.eventType = TR_PEER_CLIENT_GOT_ALLOWED_FAST;
     574  e.pieceIndex = pieceIndex;
     575  publish (msgs, &e);
     576}
     577
     578static void
     579fireClientGotBitfield (tr_peerMsgs * msgs, tr_bitfield * bitfield)
     580{
     581  tr_peer_event e = TR_PEER_EVENT_INIT;
     582  e.eventType = TR_PEER_CLIENT_GOT_BITFIELD;
     583  e.bitfield = bitfield;
     584  publish (msgs, &e);
     585}
     586
     587static void
     588fireClientGotHave (tr_peerMsgs * msgs, tr_piece_index_t index)
     589{
     590  tr_peer_event e = TR_PEER_EVENT_INIT;
     591  e.eventType = TR_PEER_CLIENT_GOT_HAVE;
     592  e.pieceIndex = index;
     593  publish (msgs, &e);
    578594}
    579595
     
    640656
    641657static void
    642 updateFastSet (tr_peermsgs * msgs UNUSED)
    643 {
    644     const bool fext = tr_peerIoSupportsFEXT (msgs->peer->io);
     658updateFastSet (tr_peerMsgs * msgs UNUSED)
     659{
     660    const bool fext = tr_peerIoSupportsFEXT (msgs->io);
    645661    const int peerIsNeedy = msgs->peer->progress < 0.10;
    646662
     
    648664    {
    649665        size_t i;
    650         const struct tr_address * addr = tr_peerIoGetAddress (msgs->peer->io, NULL);
     666        const struct tr_address * addr = tr_peerIoGetAddress (msgs->io, NULL);
    651667        const tr_info * inf = &msgs->torrent->info;
    652668        const size_t numwant = MIN (MAX_FAST_SET_SIZE, inf->pieceCount);
     
    668684
    669685static void
    670 sendInterest (tr_peermsgs * msgs, bool clientIsInterested)
    671 {
    672     struct evbuffer * out = msgs->outMessages;
    673 
    674     assert (msgs);
    675     assert (tr_isBool (clientIsInterested));
    676 
    677     msgs->peer->clientIsInterested = clientIsInterested;
    678     dbgmsg (msgs, "Sending %s", clientIsInterested ? "Interested" : "Not Interested");
    679     evbuffer_add_uint32 (out, sizeof (uint8_t));
    680     evbuffer_add_uint8 (out, clientIsInterested ? BT_INTERESTED : BT_NOT_INTERESTED);
    681 
    682     pokeBatchPeriod (msgs, HIGH_PRIORITY_INTERVAL_SECS);
    683     dbgOutMessageLen (msgs);
    684 }
    685 
    686 static void
    687 updateInterest (tr_peermsgs * msgs UNUSED)
     686sendInterest (tr_peerMsgs * msgs, bool b)
     687{
     688  struct evbuffer * out = msgs->outMessages;
     689
     690  assert (msgs);
     691  assert (tr_isBool (b));
     692
     693  msgs->client_is_interested = b;
     694  dbgmsg (msgs, "Sending %s", b ? "Interested" : "Not Interested");
     695  evbuffer_add_uint32 (out, sizeof (uint8_t));
     696  evbuffer_add_uint8 (out, b ? BT_INTERESTED : BT_NOT_INTERESTED);
     697
     698  pokeBatchPeriod (msgs, HIGH_PRIORITY_INTERVAL_SECS);
     699  dbgOutMessageLen (msgs);
     700}
     701
     702static void
     703updateInterest (tr_peerMsgs * msgs UNUSED)
    688704{
    689705    /* FIXME -- might need to poke the mgr on startup */
     
    691707
    692708void
    693 tr_peerMsgsSetInterested (tr_peermsgs * msgs, bool clientIsInterested)
    694 {
    695     assert (tr_isBool (clientIsInterested));
    696 
    697     if (clientIsInterested != msgs->peer->clientIsInterested)
    698         sendInterest (msgs, clientIsInterested);
     709tr_peerMsgsSetInterested (tr_peerMsgs * msgs, bool b)
     710{
     711  assert (tr_isBool (b));
     712
     713  if (msgs->client_is_interested != b)
     714    sendInterest (msgs, b);
    699715}
    700716
    701717static bool
    702 popNextMetadataRequest (tr_peermsgs * msgs, int * piece)
    703 {
    704     if (msgs->peerAskedForMetadataCount == 0)
    705         return false;
    706 
    707     *piece = msgs->peerAskedForMetadata[0];
    708 
    709     tr_removeElementFromArray (msgs->peerAskedForMetadata, 0, sizeof (int),
    710                                msgs->peerAskedForMetadataCount--);
    711 
    712     return true;
     718popNextMetadataRequest (tr_peerMsgs * msgs, int * piece)
     719{
     720  if (msgs->peerAskedForMetadataCount == 0)
     721    return false;
     722
     723  *piece = msgs->peerAskedForMetadata[0];
     724
     725  tr_removeElementFromArray (msgs->peerAskedForMetadata, 0, sizeof (int),
     726                             msgs->peerAskedForMetadataCount--);
     727
     728  return true;
    713729}
    714730
    715731static bool
    716 popNextRequest (tr_peermsgs * msgs, struct peer_request * setme)
    717 {
    718     if (msgs->peer->pendingReqsToClient == 0)
    719         return false;
    720 
    721     *setme = msgs->peerAskedFor[0];
    722 
    723     tr_removeElementFromArray (msgs->peerAskedFor, 0, sizeof (struct peer_request),
    724                                msgs->peer->pendingReqsToClient--);
    725 
    726     return true;
    727 }
    728 
    729 static void
    730 cancelAllRequestsToClient (tr_peermsgs * msgs)
    731 {
    732     struct peer_request req;
    733     const int mustSendCancel = tr_peerIoSupportsFEXT (msgs->peer->io);
    734 
    735     while (popNextRequest (msgs, &req))
    736         if (mustSendCancel)
    737             protocolSendReject (msgs, &req);
     732popNextRequest (tr_peerMsgs * msgs, struct peer_request * setme)
     733{
     734  if (msgs->peer.pendingReqsToClient == 0)
     735    return false;
     736
     737  *setme = msgs->peerAskedFor[0];
     738
     739  tr_removeElementFromArray (msgs->peerAskedFor,
     740                             0,
     741                             sizeof (struct peer_request),
     742                             msgs->peer.pendingReqsToClient--);
     743
     744  return true;
     745}
     746
     747static void
     748cancelAllRequestsToClient (tr_peerMsgs * msgs)
     749{
     750  struct peer_request req;
     751  const int mustSendCancel = tr_peerIoSupportsFEXT (msgs->io);
     752
     753  while (popNextRequest (msgs, &req))
     754    if (mustSendCancel)
     755      protocolSendReject (msgs, &req);
    738756}
    739757
    740758void
    741 tr_peerMsgsSetChoke (tr_peermsgs * msgs, bool peerIsChoked)
    742 {
    743     const time_t now = tr_time ();
    744     const time_t fibrillationTime = now - MIN_CHOKE_PERIOD_SEC;
    745 
    746     assert (msgs);
    747     assert (msgs->peer);
    748     assert (tr_isBool (peerIsChoked));
    749 
    750     if (msgs->peer->chokeChangedAt > fibrillationTime)
    751     {
    752         dbgmsg (msgs, "Not changing choke to %d to avoid fibrillation", peerIsChoked);
    753     }
    754     else if (msgs->peer->peerIsChoked != peerIsChoked)
    755     {
    756         msgs->peer->peerIsChoked = peerIsChoked;
    757         if (peerIsChoked)
    758             cancelAllRequestsToClient (msgs);
    759         protocolSendChoke (msgs, peerIsChoked);
    760         msgs->peer->chokeChangedAt = now;
     759tr_peerMsgsSetChoke (tr_peerMsgs * msgs, bool peer_is_choked)
     760{
     761  const time_t now = tr_time ();
     762  const time_t fibrillationTime = now - MIN_CHOKE_PERIOD_SEC;
     763
     764  assert (msgs != NULL);
     765  assert (tr_isBool (peer_is_choked));
     766
     767  if (msgs->chokeChangedAt > fibrillationTime)
     768    {
     769      dbgmsg (msgs, "Not changing choke to %d to avoid fibrillation", peer_is_choked);
     770    }
     771  else if (msgs->peer_is_choked != peer_is_choked)
     772    {
     773      msgs->peer_is_choked = peer_is_choked;
     774      if (peer_is_choked)
     775        cancelAllRequestsToClient (msgs);
     776      protocolSendChoke (msgs, peer_is_choked);
     777      msgs->chokeChangedAt = now;
    761778    }
    762779}
     
    767784
    768785void
    769 tr_peerMsgsHave (tr_peermsgs * msgs, uint32_t index)
    770 {
    771     protocolSendHave (msgs, index);
    772 
    773     /* since we have more pieces now, we might not be interested in this peer */
    774     updateInterest (msgs);
     786tr_peerMsgsHave (tr_peerMsgs * msgs, uint32_t index)
     787{
     788  protocolSendHave (msgs, index);
     789
     790  /* since we have more pieces now, we might not be interested in this peer */
     791  updateInterest (msgs);
    775792}
    776793
     
    780797
    781798static bool
    782 reqIsValid (const tr_peermsgs * peer,
     799reqIsValid (const tr_peerMsgs * peer,
    783800            uint32_t            index,
    784801            uint32_t            offset,
     
    789806
    790807static bool
    791 requestIsValid (const tr_peermsgs * msgs, const struct peer_request * req)
     808requestIsValid (const tr_peerMsgs * msgs, const struct peer_request * req)
    792809{
    793810    return reqIsValid (msgs, req->index, req->offset, req->length);
     
    795812
    796813void
    797 tr_peerMsgsCancel (tr_peermsgs * msgs, tr_block_index_t block)
     814tr_peerMsgsCancel (tr_peerMsgs * msgs, tr_block_index_t block)
    798815{
    799816    struct peer_request req;
     
    808825
    809826static void
    810 sendLtepHandshake (tr_peermsgs * msgs)
     827sendLtepHandshake (tr_peerMsgs * msgs)
    811828{
    812829    tr_variant val;
     
    875892
    876893static void
    877 parseLtepHandshake (tr_peermsgs * msgs, int len, struct evbuffer * inbuf)
     894parseLtepHandshake (tr_peerMsgs * msgs, int len, struct evbuffer * inbuf)
    878895{
    879896    int64_t   i;
     
    887904    memset (&pex, 0, sizeof (tr_pex));
    888905
    889     tr_peerIoReadBytes (msgs->peer->io, inbuf, tmp, len);
     906    tr_peerIoReadBytes (msgs->io, inbuf, tmp, len);
    890907    msgs->peerSentLtepHandshake = 1;
    891908
     
    926943               it implies support for µTP, so use it to indicate that. */
    927944            tr_peerMgrSetUtpFailed (msgs->torrent,
    928                                     tr_peerIoGetAddress (msgs->peer->io, NULL),
     945                                    tr_peerIoGetAddress (msgs->io, NULL),
    929946                                    false);
    930947        }
     
    948965    }
    949966
    950     if (tr_peerIoIsIncoming (msgs->peer->io)
     967    if (tr_peerIoIsIncoming (msgs->io)
    951968        && tr_variantDictFindRaw (&val, TR_KEY_ipv4, &addr, &addr_len)
    952969        && (addr_len == 4))
     
    957974    }
    958975
    959     if (tr_peerIoIsIncoming (msgs->peer->io)
     976    if (tr_peerIoIsIncoming (msgs->io)
    960977        && tr_variantDictFindRaw (&val, TR_KEY_ipv6, &addr, &addr_len)
    961978        && (addr_len == 16))
     
    975992
    976993static void
    977 parseUtMetadata (tr_peermsgs * msgs, int msglen, struct evbuffer * inbuf)
     994parseUtMetadata (tr_peerMsgs * msgs, int msglen, struct evbuffer * inbuf)
    978995{
    979996    tr_variant dict;
     
    9851002    uint8_t * tmp = tr_new (uint8_t, msglen);
    9861003
    987     tr_peerIoReadBytes (msgs->peer->io, inbuf, tmp, msglen);
     1004    tr_peerIoReadBytes (msgs->io, inbuf, tmp, msglen);
    9881005    msg_end = (char*)tmp + msglen;
    9891006
     
    10521069
    10531070static void
    1054 parseUtPex (tr_peermsgs * msgs, int msglen, struct evbuffer * inbuf)
     1071parseUtPex (tr_peerMsgs * msgs, int msglen, struct evbuffer * inbuf)
    10551072{
    10561073    int loaded = 0;
     
    10611078    size_t added_len;
    10621079
    1063     tr_peerIoReadBytes (msgs->peer->io, inbuf, tmp, msglen);
     1080    tr_peerIoReadBytes (msgs->io, inbuf, tmp, msglen);
    10641081
    10651082    if (tr_torrentAllowsPex (tor)
     
    11141131}
    11151132
    1116 static void sendPex (tr_peermsgs * msgs);
    1117 
    1118 static void
    1119 parseLtep (tr_peermsgs * msgs, int msglen, struct evbuffer  * inbuf)
     1133static void sendPex (tr_peerMsgs * msgs);
     1134
     1135static void
     1136parseLtep (tr_peerMsgs * msgs, int msglen, struct evbuffer  * inbuf)
    11201137{
    11211138    uint8_t ltep_msgid;
    11221139
    1123     tr_peerIoReadUint8 (msgs->peer->io, inbuf, &ltep_msgid);
     1140    tr_peerIoReadUint8 (msgs->io, inbuf, &ltep_msgid);
    11241141    msglen--;
    11251142
     
    11281145        dbgmsg (msgs, "got ltep handshake");
    11291146        parseLtepHandshake (msgs, msglen, inbuf);
    1130         if (tr_peerIoSupportsLTEP (msgs->peer->io))
     1147        if (tr_peerIoSupportsLTEP (msgs->io))
    11311148        {
    11321149            sendLtepHandshake (msgs);
     
    11541171
    11551172static int
    1156 readBtLength (tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen)
     1173readBtLength (tr_peerMsgs * msgs, struct evbuffer * inbuf, size_t inlen)
    11571174{
    11581175    uint32_t len;
     
    11611178        return READ_LATER;
    11621179
    1163     tr_peerIoReadUint32 (msgs->peer->io, inbuf, &len);
     1180    tr_peerIoReadUint32 (msgs->io, inbuf, &len);
    11641181
    11651182    if (len == 0) /* peer sent us a keepalive message */
     
    11741191}
    11751192
    1176 static int readBtMessage (tr_peermsgs *, struct evbuffer *, size_t);
     1193static int readBtMessage (tr_peerMsgs *, struct evbuffer *, size_t);
    11771194
    11781195static int
    1179 readBtId (tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen)
     1196readBtId (tr_peerMsgs * msgs, struct evbuffer * inbuf, size_t inlen)
    11801197{
    11811198    uint8_t id;
     
    11841201        return READ_LATER;
    11851202
    1186     tr_peerIoReadUint8 (msgs->peer->io, inbuf, &id);
     1203    tr_peerIoReadUint8 (msgs->io, inbuf, &id);
    11871204    msgs->incoming.id = id;
    11881205    dbgmsg (msgs, "msgs->incoming.id is now %d; msgs->incoming.length is %zu", id, (size_t)msgs->incoming.length);
     
    12021219
    12031220static void
    1204 updatePeerProgress (tr_peermsgs * msgs)
    1205 {
    1206     tr_peerUpdateProgress (msgs->torrent, msgs->peer);
    1207 
    1208     /*updateFastSet (msgs);*/
    1209     updateInterest (msgs);
    1210 }
    1211 
    1212 static void
    1213 prefetchPieces (tr_peermsgs *msgs)
    1214 {
    1215     int i;
    1216 
    1217     if (!getSession (msgs)->isPrefetchEnabled)
    1218         return;
    1219 
    1220     for (i=msgs->prefetchCount; i<msgs->peer->pendingReqsToClient && i<PREFETCH_SIZE; ++i)
    1221     {
    1222         const struct peer_request * req = msgs->peerAskedFor + i;
    1223         if (requestIsValid (msgs, req))
     1221updatePeerProgress (tr_peerMsgs * msgs)
     1222{
     1223  tr_peerUpdateProgress (msgs->torrent, &msgs->peer);
     1224
     1225  /*updateFastSet (msgs);*/
     1226  updateInterest (msgs);
     1227}
     1228
     1229static void
     1230prefetchPieces (tr_peerMsgs *msgs)
     1231{
     1232  int i;
     1233
     1234  if (!getSession (msgs)->isPrefetchEnabled)
     1235    return;
     1236
     1237  for (i=msgs->prefetchCount; i<msgs->peer.pendingReqsToClient && i<PREFETCH_SIZE; ++i)
     1238    {
     1239      const struct peer_request * req = msgs->peerAskedFor + i;
     1240      if (requestIsValid (msgs, req))
    12241241        {
    1225             tr_cachePrefetchBlock (getSession (msgs)->cache, msgs->torrent, req->index, req->offset, req->length);
    1226             ++msgs->prefetchCount;
     1242          tr_cachePrefetchBlock (getSession (msgs)->cache, msgs->torrent, req->index, req->offset, req->length);
     1243          ++msgs->prefetchCount;
    12271244        }
    12281245    }
     
    12301247
    12311248static void
    1232 peerMadeRequest (tr_peermsgs * msgs, const struct peer_request * req)
    1233 {
    1234     const bool fext = tr_peerIoSupportsFEXT (msgs->peer->io);
     1249peerMadeRequest (tr_peerMsgs * msgs, const struct peer_request * req)
     1250{
     1251    const bool fext = tr_peerIoSupportsFEXT (msgs->io);
    12351252    const int reqIsValid = requestIsValid (msgs, req);
    12361253    const int clientHasPiece = reqIsValid && tr_cpPieceIsComplete (&msgs->torrent->completion, req->index);
    1237     const int peerIsChoked = msgs->peer->peerIsChoked;
     1254    const int peerIsChoked = msgs->peer_is_choked;
    12381255
    12391256    int allow = false;
     
    12451262    else if (peerIsChoked)
    12461263        dbgmsg (msgs, "rejecting request from choked peer");
    1247     else if (msgs->peer->pendingReqsToClient + 1 >= REQQ)
     1264    else if (msgs->peer.pendingReqsToClient + 1 >= REQQ)
    12481265        dbgmsg (msgs, "rejecting request ... reqq is full");
    12491266    else
     
    12511268
    12521269    if (allow) {
    1253         msgs->peerAskedFor[msgs->peer->pendingReqsToClient++] = *req;
     1270        msgs->peerAskedFor[msgs->peer.pendingReqsToClient++] = *req;
    12541271        prefetchPieces (msgs);
    12551272    } else if (fext) {
     
    12591276
    12601277static bool
    1261 messageLengthIsCorrect (const tr_peermsgs * msg, uint8_t id, uint32_t len)
     1278messageLengthIsCorrect (const tr_peerMsgs * msg, uint8_t id, uint32_t len)
    12621279{
    12631280    switch (id)
     
    13041321}
    13051322
    1306 static int clientGotBlock (tr_peermsgs *               msgs,
     1323static int clientGotBlock (tr_peerMsgs *               msgs,
    13071324                           struct evbuffer *           block,
    13081325                           const struct peer_request * req);
    13091326
    13101327static int
    1311 readBtPiece (tr_peermsgs      * msgs,
     1328readBtPiece (tr_peerMsgs      * msgs,
    13121329             struct evbuffer  * inbuf,
    13131330             size_t             inlen,
     
    13241341            return READ_LATER;
    13251342
    1326         tr_peerIoReadUint32 (msgs->peer->io, inbuf, &req->index);
    1327         tr_peerIoReadUint32 (msgs->peer->io, inbuf, &req->offset);
     1343        tr_peerIoReadUint32 (msgs->io, inbuf, &req->index);
     1344        tr_peerIoReadUint32 (msgs->io, inbuf, &req->offset);
    13281345        req->length = msgs->incoming.length - 9;
    13291346        dbgmsg (msgs, "got incoming block header %u:%u->%u", req->index, req->offset, req->length);
     
    13451362        n = MIN (nLeft, inlen);
    13461363
    1347         tr_peerIoReadBytesToBuf (msgs->peer->io, inbuf, block_buffer, n);
     1364        tr_peerIoReadBytesToBuf (msgs->io, inbuf, block_buffer, n);
    13481365
    13491366        fireClientGotPieceData (msgs, n);
     
    13661383}
    13671384
    1368 static void updateDesiredRequestCount (tr_peermsgs * msgs);
     1385static void updateDesiredRequestCount (tr_peerMsgs * msgs);
    13691386
    13701387static int
    1371 readBtMessage (tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen)
     1388readBtMessage (tr_peerMsgs * msgs, struct evbuffer * inbuf, size_t inlen)
    13721389{
    13731390    uint32_t      ui32;
     
    13771394    const size_t  startBufLen = evbuffer_get_length (inbuf);
    13781395#endif
    1379     const bool fext = tr_peerIoSupportsFEXT (msgs->peer->io);
     1396    const bool fext = tr_peerIoSupportsFEXT (msgs->io);
    13801397
    13811398    --msglen; /* id length */
     
    13971414        case BT_CHOKE:
    13981415            dbgmsg (msgs, "got Choke");
    1399             msgs->peer->clientIsChoked = 1;
     1416            msgs->client_is_choked = true;
    14001417            if (!fext)
    14011418                fireGotChoke (msgs);
     
    14041421        case BT_UNCHOKE:
    14051422            dbgmsg (msgs, "got Unchoke");
    1406             msgs->peer->clientIsChoked = 0;
     1423            msgs->client_is_choked = false;
    14071424            updateDesiredRequestCount (msgs);
    14081425            break;
     
    14101427        case BT_INTERESTED:
    14111428            dbgmsg (msgs, "got Interested");
    1412             msgs->peer->peerIsInterested = 1;
     1429            msgs->peer_is_interested = true;
    14131430            break;
    14141431
    14151432        case BT_NOT_INTERESTED:
    14161433            dbgmsg (msgs, "got Not Interested");
    1417             msgs->peer->peerIsInterested = 0;
     1434            msgs->peer_is_interested = false;
    14181435            break;
    14191436
    14201437        case BT_HAVE:
    1421             tr_peerIoReadUint32 (msgs->peer->io, inbuf, &ui32);
     1438            tr_peerIoReadUint32 (msgs->io, inbuf, &ui32);
    14221439            dbgmsg (msgs, "got Have: %u", ui32);
    14231440            if (tr_torrentHasMetadata (msgs->torrent)
     
    14291446
    14301447            /* a peer can send the same HAVE message twice... */
    1431             if (!tr_bitfieldHas (&msgs->peer->have, ui32)) {
    1432                 tr_bitfieldAdd (&msgs->peer->have, ui32);
     1448            if (!tr_bitfieldHas (&msgs->peer.have, ui32)) {
     1449                tr_bitfieldAdd (&msgs->peer.have, ui32);
    14331450                fireClientGotHave (msgs, ui32);
    14341451            }
     
    14391456            uint8_t * tmp = tr_new (uint8_t, msglen);
    14401457            dbgmsg (msgs, "got a bitfield");
    1441             tr_peerIoReadBytes (msgs->peer->io, inbuf, tmp, msglen);
    1442             tr_bitfieldSetRaw (&msgs->peer->have, tmp, msglen, tr_torrentHasMetadata (msgs->torrent));
    1443             fireClientGotBitfield (msgs, &msgs->peer->have);
     1458            tr_peerIoReadBytes (msgs->io, inbuf, tmp, msglen);
     1459            tr_bitfieldSetRaw (&msgs->peer.have, tmp, msglen, tr_torrentHasMetadata (msgs->torrent));
     1460            fireClientGotBitfield (msgs, &msgs->peer.have);
    14441461            updatePeerProgress (msgs);
    14451462            tr_free (tmp);
     
    14501467        {
    14511468            struct peer_request r;
    1452             tr_peerIoReadUint32 (msgs->peer->io, inbuf, &r.index);
    1453             tr_peerIoReadUint32 (msgs->peer->io, inbuf, &r.offset);
    1454             tr_peerIoReadUint32 (msgs->peer->io, inbuf, &r.length);
     1469            tr_peerIoReadUint32 (msgs->io, inbuf, &r.index);
     1470            tr_peerIoReadUint32 (msgs->io, inbuf, &r.offset);
     1471            tr_peerIoReadUint32 (msgs->io, inbuf, &r.length);
    14551472            dbgmsg (msgs, "got Request: %u:%u->%u", r.index, r.offset, r.length);
    14561473            peerMadeRequest (msgs, &r);
     
    14621479            int i;
    14631480            struct peer_request r;
    1464             tr_peerIoReadUint32 (msgs->peer->io, inbuf, &r.index);
    1465             tr_peerIoReadUint32 (msgs->peer->io, inbuf, &r.offset);
    1466             tr_peerIoReadUint32 (msgs->peer->io, inbuf, &r.length);
    1467             tr_historyAdd (&msgs->peer->cancelsSentToClient, tr_time (), 1);
     1481            tr_peerIoReadUint32 (msgs->io, inbuf, &r.index);
     1482            tr_peerIoReadUint32 (msgs->io, inbuf, &r.offset);
     1483            tr_peerIoReadUint32 (msgs->io, inbuf, &r.length);
     1484            tr_historyAdd (&msgs->peer.cancelsSentToClient, tr_time (), 1);
    14681485            dbgmsg (msgs, "got a Cancel %u:%u->%u", r.index, r.offset, r.length);
    14691486
    1470             for (i=0; i<msgs->peer->pendingReqsToClient; ++i) {
     1487            for (i=0; i<msgs->peer.pendingReqsToClient; ++i) {
    14711488                const struct peer_request * req = msgs->peerAskedFor + i;
    14721489                if ((req->index == r.index) && (req->offset == r.offset) && (req->length == r.length))
     
    14741491            }
    14751492
    1476             if (i < msgs->peer->pendingReqsToClient)
     1493            if (i < msgs->peer.pendingReqsToClient)
    14771494                tr_removeElementFromArray (msgs->peerAskedFor, i, sizeof (struct peer_request),
    1478                                            msgs->peer->pendingReqsToClient--);
     1495                                           msgs->peer.pendingReqsToClient--);
    14791496            break;
    14801497        }
     
    14861503        case BT_PORT:
    14871504            dbgmsg (msgs, "Got a BT_PORT");
    1488             tr_peerIoReadUint16 (msgs->peer->io, inbuf, &msgs->dht_port);
     1505            tr_peerIoReadUint16 (msgs->io, inbuf, &msgs->dht_port);
    14891506            if (msgs->dht_port > 0)
    14901507                tr_dhtAddNode (getSession (msgs),
    1491                                tr_peerAddress (msgs->peer),
     1508                               tr_peerAddress (&msgs->peer),
    14921509                               msgs->dht_port, 0);
    14931510            break;
     
    14951512        case BT_FEXT_SUGGEST:
    14961513            dbgmsg (msgs, "Got a BT_FEXT_SUGGEST");
    1497             tr_peerIoReadUint32 (msgs->peer->io, inbuf, &ui32);
     1514            tr_peerIoReadUint32 (msgs->io, inbuf, &ui32);
    14981515            if (fext)
    14991516                fireClientGotSuggest (msgs, ui32);
     
    15061523        case BT_FEXT_ALLOWED_FAST:
    15071524            dbgmsg (msgs, "Got a BT_FEXT_ALLOWED_FAST");
    1508             tr_peerIoReadUint32 (msgs->peer->io, inbuf, &ui32);
     1525            tr_peerIoReadUint32 (msgs->io, inbuf, &ui32);
    15091526            if (fext)
    15101527                fireClientGotAllowedFast (msgs, ui32);
     
    15181535            dbgmsg (msgs, "Got a BT_FEXT_HAVE_ALL");
    15191536            if (fext) {
    1520                 tr_bitfieldSetHasAll (&msgs->peer->have);
    1521 assert (tr_bitfieldHasAll (&msgs->peer->have));
     1537                tr_bitfieldSetHasAll (&msgs->peer.have);
     1538assert (tr_bitfieldHasAll (&msgs->peer.have));
    15221539                fireClientGotHaveAll (msgs);
    15231540                updatePeerProgress (msgs);
     
    15311548            dbgmsg (msgs, "Got a BT_FEXT_HAVE_NONE");
    15321549            if (fext) {
    1533                 tr_bitfieldSetHasNone (&msgs->peer->have);
     1550                tr_bitfieldSetHasNone (&msgs->peer.have);
    15341551                fireClientGotHaveNone (msgs);
    15351552                updatePeerProgress (msgs);
     
    15441561            struct peer_request r;
    15451562            dbgmsg (msgs, "Got a BT_FEXT_REJECT");
    1546             tr_peerIoReadUint32 (msgs->peer->io, inbuf, &r.index);
    1547             tr_peerIoReadUint32 (msgs->peer->io, inbuf, &r.offset);
    1548             tr_peerIoReadUint32 (msgs->peer->io, inbuf, &r.length);
     1563            tr_peerIoReadUint32 (msgs->io, inbuf, &r.index);
     1564            tr_peerIoReadUint32 (msgs->io, inbuf, &r.offset);
     1565            tr_peerIoReadUint32 (msgs->io, inbuf, &r.length);
    15491566            if (fext)
    15501567                fireGotRej (msgs, &r);
     
    15631580        default:
    15641581            dbgmsg (msgs, "peer sent us an UNKNOWN: %d", (int)id);
    1565             tr_peerIoDrain (msgs->peer->io, inbuf, msglen);
     1582            tr_peerIoDrain (msgs->io, inbuf, msglen);
    15661583            break;
    15671584    }
     
    15761593/* returns 0 on success, or an errno on failure */
    15771594static int
    1578 clientGotBlock (tr_peermsgs                * msgs,
     1595clientGotBlock (tr_peerMsgs                * msgs,
    15791596                struct evbuffer            * data,
    15801597                const struct peer_request  * req)
     
    15951612    dbgmsg (msgs, "got block %u:%u->%u", req->index, req->offset, req->length);
    15961613
    1597     if (!tr_peerMgrDidPeerRequest (msgs->torrent, msgs->peer, block)) {
     1614    if (!tr_peerMgrDidPeerRequest (msgs->torrent, &msgs->peer, block)) {
    15981615        dbgmsg (msgs, "we didn't ask for this message...");
    15991616        return 0;
     
    16111628        return err;
    16121629
    1613     tr_bitfieldAdd (&msgs->peer->blame, req->index);
     1630    tr_bitfieldAdd (&msgs->peer.blame, req->index);
    16141631    fireGotBlock (msgs, req);
    16151632    return 0;
     
    16211638didWrite (tr_peerIo * io UNUSED, size_t bytesWritten, bool wasPieceData, void * vmsgs)
    16221639{
    1623     tr_peermsgs * msgs = vmsgs;
     1640    tr_peerMsgs * msgs = vmsgs;
    16241641
    16251642    if (wasPieceData)
     
    16341651{
    16351652    ReadState         ret;
    1636     tr_peermsgs *     msgs = vmsgs;
     1653    tr_peerMsgs *     msgs = vmsgs;
    16371654    struct evbuffer * in = tr_peerIoGetReadBuffer (io);
    16381655    const size_t      inlen = evbuffer_get_length (in);
     
    16701687
    16711688int
    1672 tr_peerMsgsIsReadingBlock (const tr_peermsgs * msgs, tr_block_index_t block)
     1689tr_peerMsgsIsReadingBlock (const tr_peerMsgs * msgs, tr_block_index_t block)
    16731690{
    16741691    if (msgs->state != AWAITING_BT_PIECE)
     
    16851702
    16861703static void
    1687 updateDesiredRequestCount (tr_peermsgs * msgs)
     1704updateDesiredRequestCount (tr_peerMsgs * msgs)
    16881705{
    16891706    tr_torrent * const torrent = msgs->torrent;
     
    16911708    /* there are lots of reasons we might not want to request any blocks... */
    16921709    if (tr_torrentIsSeed (torrent) || !tr_torrentHasMetadata (torrent)
    1693                                     || msgs->peer->clientIsChoked
    1694                                     || !msgs->peer->clientIsInterested)
     1710                                    || msgs->client_is_choked
     1711                                    || !msgs->client_is_interested)
    16951712    {
    16961713        msgs->desiredRequestCount = 0;
     
    17071724        /* Get the rate limit we should use.
    17081725         * FIXME: this needs to consider all the other peers as well... */
    1709         rate_Bps = tr_peerGetPieceSpeed_Bps (msgs->peer, now, TR_PEER_TO_CLIENT);
     1726        rate_Bps = tr_peerGetPieceSpeed_Bps (&msgs->peer, now, TR_PEER_TO_CLIENT);
    17101727        if (tr_torrentUsesSpeedLimit (torrent, TR_PEER_TO_CLIENT))
    17111728            rate_Bps = MIN (rate_Bps, tr_torrentGetSpeedLimit_Bps (torrent, TR_PEER_TO_CLIENT));
     
    17291746
    17301747static void
    1731 updateMetadataRequests (tr_peermsgs * msgs, time_t now)
     1748updateMetadataRequests (tr_peerMsgs * msgs, time_t now)
    17321749{
    17331750    int piece;
     
    17631780
    17641781static void
    1765 updateBlockRequests (tr_peermsgs * msgs)
     1782updateBlockRequests (tr_peerMsgs * msgs)
    17661783{
    17671784    if (tr_torrentIsPieceTransferAllowed (msgs->torrent, TR_PEER_TO_CLIENT)
    17681785        && (msgs->desiredRequestCount > 0)
    1769         && (msgs->peer->pendingReqsToPeer <= (msgs->desiredRequestCount * 0.66)))
     1786        && (msgs->peer.pendingReqsToPeer <= (msgs->desiredRequestCount * 0.66)))
    17701787    {
    17711788        int i;
    17721789        int n;
    1773         const int numwant = msgs->desiredRequestCount - msgs->peer->pendingReqsToPeer;
    1774         tr_block_index_t * blocks = tr_new (tr_block_index_t, numwant);
    1775 
    1776         tr_peerMgrGetNextRequests (msgs->torrent, msgs->peer, numwant, blocks, &n, false);
     1790        tr_block_index_t * blocks;
     1791        const int numwant = msgs->desiredRequestCount - msgs->peer.pendingReqsToPeer;
     1792
     1793        assert (tr_peerMsgsIsClientInterested (msgs));
     1794        assert (!tr_peerMsgsIsClientChoked (msgs));
     1795
     1796        blocks = tr_new (tr_block_index_t, numwant);
     1797        tr_peerMgrGetNextRequests (msgs->torrent, &msgs->peer, numwant, blocks, &n, false);
    17771798
    17781799        for (i=0; i<n; ++i)
     
    17881809
    17891810static size_t
    1790 fillOutputBuffer (tr_peermsgs * msgs, time_t now)
     1811fillOutputBuffer (tr_peerMsgs * msgs, time_t now)
    17911812{
    17921813    int piece;
     
    17941815    struct peer_request req;
    17951816    const bool haveMessages = evbuffer_get_length (msgs->outMessages) != 0;
    1796     const bool fext = tr_peerIoSupportsFEXT (msgs->peer->io);
     1817    const bool fext = tr_peerIoSupportsFEXT (msgs->io);
    17971818
    17981819    /**
     
    18091830        const size_t len = evbuffer_get_length (msgs->outMessages);
    18101831        /* flush the protocol messages */
    1811         dbgmsg (msgs, "flushing outMessages... to %p (length is %zu)", msgs->peer->io, len);
    1812         tr_peerIoWriteBuf (msgs->peer->io, msgs->outMessages, false);
     1832        dbgmsg (msgs, "flushing outMessages... to %p (length is %zu)", msgs->io, len);
     1833        tr_peerIoWriteBuf (msgs->io, msgs->outMessages, false);
    18131834        msgs->clientSentAnythingAt = now;
    18141835        msgs->outMessagesBatchedAt = 0;
     
    18211842    **/
    18221843
    1823     if ((tr_peerIoGetWriteBufferSpace (msgs->peer->io, now) >= METADATA_PIECE_SIZE)
     1844    if ((tr_peerIoGetWriteBufferSpace (msgs->io, now) >= METADATA_PIECE_SIZE)
    18241845        && popNextMetadataRequest (msgs, &piece))
    18251846    {
     
    18871908    **/
    18881909
    1889     if ((tr_peerIoGetWriteBufferSpace (msgs->peer->io, now) >= msgs->torrent->blockSize)
     1910    if ((tr_peerIoGetWriteBufferSpace (msgs->io, now) >= msgs->torrent->blockSize)
    18901911        && popNextRequest (msgs, &req))
    18911912    {
     
    19281949                dbgmsg (msgs, "sending block %u:%u->%u", req.index, req.offset, req.length);
    19291950                assert (n == msglen);
    1930                 tr_peerIoWriteBuf (msgs->peer->io, out, true);
     1951                tr_peerIoWriteBuf (msgs->io, out, true);
    19311952                bytesWritten += n;
    19321953                msgs->clientSentAnythingAt = now;
    1933                 tr_historyAdd (&msgs->peer->blocksSentToPeer, tr_time (), 1);
     1954                tr_historyAdd (&msgs->peer.blocksSentToPeer, tr_time (), 1);
    19341955            }
    19351956
     
    19701991peerPulse (void * vmsgs)
    19711992{
    1972     tr_peermsgs * msgs = vmsgs;
     1993    tr_peerMsgs * msgs = vmsgs;
    19731994    const time_t  now = tr_time ();
    19741995
    1975     if (tr_isPeerIo (msgs->peer->io)) {
     1996    if (tr_isPeerIo (msgs->io)) {
    19761997        updateDesiredRequestCount (msgs);
    19771998        updateBlockRequests (msgs);
     
    19872008
    19882009void
    1989 tr_peerMsgsPulse (tr_peermsgs * msgs)
     2010tr_peerMsgsPulse (tr_peerMsgs * msgs)
    19902011{
    19912012    if (msgs != NULL)
     
    20052026
    20062027static void
    2007 sendBitfield (tr_peermsgs * msgs)
     2028sendBitfield (tr_peerMsgs * msgs)
    20082029{
    20092030    void * bytes;
     
    20242045
    20252046static void
    2026 tellPeerWhatWeHave (tr_peermsgs * msgs)
    2027 {
    2028     const bool fext = tr_peerIoSupportsFEXT (msgs->peer->io);
     2047tellPeerWhatWeHave (tr_peerMsgs * msgs)
     2048{
     2049    const bool fext = tr_peerIoSupportsFEXT (msgs->io);
    20292050
    20302051    if (fext && tr_cpHasAll (&msgs->torrent->completion))
     
    21652186
    21662187static void
    2167 sendPex (tr_peermsgs * msgs)
     2188sendPex (tr_peerMsgs * msgs)
    21682189{
    21692190    if (msgs->peerSupportsPex && tr_torrentAllowsPex (msgs->torrent))
     
    23342355pexPulse (int foo UNUSED, short bar UNUSED, void * vmsgs)
    23352356{
    2336     struct tr_peermsgs * msgs = vmsgs;
     2357    struct tr_peerMsgs * msgs = vmsgs;
    23372358
    23382359    sendPex (msgs);
     
    23422363}
    23432364
    2344 /**
    2345 ***
    2346 **/
    2347 
    2348 tr_peermsgs*
     2365/***
     2366****  tr_peer virtual functions
     2367***/
     2368
     2369static bool
     2370peermsgs_is_transferring_pieces (const struct tr_peer * peer,
     2371                                 uint64_t               now,
     2372                                 tr_direction           direction,
     2373                                 unsigned int         * setme_Bps)
     2374{
     2375  unsigned int Bps = 0;
     2376
     2377  if (tr_isPeerMsgs (peer))
     2378    {
     2379      const tr_peerMsgs * msgs = (const tr_peerMsgs *) peer;
     2380      Bps = tr_peerIoGetPieceSpeed_Bps (msgs->io, now, direction);
     2381    }
     2382
     2383  if (setme_Bps != NULL)
     2384    *setme_Bps = Bps;
     2385
     2386  return Bps > 0;
     2387}
     2388
     2389static void
     2390peermsgs_destruct (tr_peer * peer)
     2391{
     2392  tr_peerMsgs * msgs = PEER_MSGS (peer);
     2393
     2394  assert (msgs != NULL);
     2395
     2396  if (msgs->pexTimer != NULL)
     2397    event_free (msgs->pexTimer);
     2398
     2399  if (msgs->incoming.block != NULL)
     2400    evbuffer_free (msgs->incoming.block);
     2401
     2402  if (msgs->io)
     2403    {
     2404      tr_peerIoClear (msgs->io);
     2405      tr_peerIoUnref (msgs->io); /* balanced by the ref in handshakeDoneCB () */
     2406    }
     2407
     2408  evbuffer_free (msgs->outMessages);
     2409  tr_free (msgs->pex6);
     2410  tr_free (msgs->pex);
     2411
     2412  tr_peerDestruct (&msgs->peer);
     2413
     2414  memset (msgs, ~0, sizeof (tr_peerMsgs));
     2415}
     2416
     2417static const struct tr_peer_virtual_funcs my_funcs =
     2418{
     2419  .destruct = peermsgs_destruct,
     2420  .is_transferring_pieces = peermsgs_is_transferring_pieces
     2421};
     2422
     2423/***
     2424****
     2425***/
     2426
     2427time_t
     2428tr_peerMsgsGetConnectionAge (const tr_peerMsgs * msgs)
     2429{
     2430  assert (tr_isPeerMsgs (msgs));
     2431
     2432  return tr_peerIoGetAge (msgs->io);
     2433}
     2434
     2435bool
     2436tr_peerMsgsIsPeerChoked (const tr_peerMsgs * msgs)
     2437{
     2438  assert (tr_isPeerMsgs (msgs));
     2439
     2440  return msgs->peer_is_choked;
     2441}
     2442
     2443bool
     2444tr_peerMsgsIsPeerInterested (const tr_peerMsgs * msgs)
     2445{
     2446  assert (tr_isPeerMsgs (msgs));
     2447
     2448  return msgs->peer_is_interested;
     2449}
     2450
     2451bool
     2452tr_peerMsgsIsClientChoked (const tr_peerMsgs * msgs)
     2453{
     2454  assert (tr_isPeerMsgs (msgs));
     2455
     2456  return msgs->client_is_choked;
     2457}
     2458
     2459bool
     2460tr_peerMsgsIsClientInterested (const tr_peerMsgs * msgs)
     2461{
     2462  assert (tr_isPeerMsgs (msgs));
     2463
     2464  return msgs->client_is_interested;
     2465}
     2466
     2467bool
     2468tr_peerMsgsIsUtpConnection (const tr_peerMsgs * msgs)
     2469{
     2470  assert (tr_isPeerMsgs (msgs));
     2471
     2472  return msgs->io->utp_socket != NULL;
     2473}
     2474
     2475bool
     2476tr_peerMsgsIsEncrypted (const tr_peerMsgs * msgs)
     2477{
     2478  assert (tr_isPeerMsgs (msgs));
     2479
     2480  return tr_peerIoIsEncrypted (msgs->io);
     2481}
     2482
     2483bool
     2484tr_peerMsgsIsIncomingConnection (const tr_peerMsgs * msgs)
     2485{
     2486  assert (tr_isPeerMsgs (msgs));
     2487
     2488  return tr_peerIoIsIncoming (msgs->io);
     2489}
     2490
     2491/***
     2492****
     2493***/
     2494
     2495bool
     2496tr_isPeerMsgs (const void * msgs)
     2497{
     2498  /* FIXME: this is pretty crude */
     2499  return (msgs != NULL)
     2500      && (((struct tr_peerMsgs*)msgs)->magic_number == MAGIC_NUMBER);
     2501}
     2502
     2503tr_peerMsgs *
     2504tr_peerMsgsCast (void * vm)
     2505{
     2506  return tr_isPeerMsgs(vm) ? vm : NULL;
     2507}
     2508
     2509tr_peerMsgs *
    23492510tr_peerMsgsNew (struct tr_torrent    * torrent,
    2350                 struct tr_peer       * peer,
     2511                struct tr_peerIo     * io,
    23512512                tr_peer_callback     * callback,
    23522513                void                 * callbackData)
    23532514{
    2354     tr_peermsgs * m;
    2355 
    2356     assert (peer);
    2357     assert (peer->io);
    2358 
    2359     m = tr_new0 (tr_peermsgs, 1);
    2360     m->callback = callback;
    2361     m->callbackData = callbackData;
    2362     m->peer = peer;
    2363     m->torrent = torrent;
    2364     m->peer->clientIsChoked = 1;
    2365     m->peer->peerIsChoked = 1;
    2366     m->peer->clientIsInterested = 0;
    2367     m->peer->peerIsInterested = 0;
    2368     m->state = AWAITING_BT_LENGTH;
    2369     m->outMessages = evbuffer_new ();
    2370     m->outMessagesBatchedAt = 0;
    2371     m->outMessagesBatchPeriod = LOW_PRIORITY_INTERVAL_SECS;
    2372     peer->msgs = m;
    2373 
    2374     if (tr_torrentAllowsPex (torrent)) {
    2375         m->pexTimer = evtimer_new (torrent->session->event_base, pexPulse, m);
    2376         tr_timerAdd (m->pexTimer, PEX_INTERVAL_SECS, 0);
    2377     }
    2378 
    2379     if (tr_peerIoSupportsUTP (peer->io)) {
    2380         const tr_address * addr = tr_peerIoGetAddress (peer->io, NULL);
    2381         tr_peerMgrSetUtpSupported (torrent, addr);
    2382         tr_peerMgrSetUtpFailed (torrent, addr, false);
    2383     }
    2384 
    2385     if (tr_peerIoSupportsLTEP (peer->io))
    2386         sendLtepHandshake (m);
    2387 
    2388     tellPeerWhatWeHave (m);
    2389 
    2390     if (tr_dhtEnabled (torrent->session) && tr_peerIoSupportsDHT (peer->io))
    2391     {
    2392         /* Only send PORT over IPv6 when the IPv6 DHT is running (BEP-32). */
    2393         const struct tr_address *addr = tr_peerIoGetAddress (peer->io, NULL);
    2394         if (addr->type == TR_AF_INET || tr_globalIPv6 ()) {
    2395             protocolSendPort (m, tr_dhtPort (torrent->session));
    2396         }
    2397     }
    2398 
    2399     tr_peerIoSetIOFuncs (m->peer->io, canRead, didWrite, gotError, m);
    2400     updateDesiredRequestCount (m);
    2401 
    2402     return m;
    2403 }
    2404 
    2405 void
    2406 tr_peerMsgsFree (tr_peermsgs* msgs)
    2407 {
    2408     if (msgs)
    2409     {
    2410         if (msgs->pexTimer != NULL)
    2411             event_free (msgs->pexTimer);
    2412 
    2413         if (msgs->incoming.block != NULL)
    2414             evbuffer_free (msgs->incoming.block);
    2415 
    2416         evbuffer_free (msgs->outMessages);
    2417         tr_free (msgs->pex6);
    2418         tr_free (msgs->pex);
    2419 
    2420         memset (msgs, ~0, sizeof (tr_peermsgs));
    2421         tr_free (msgs);
    2422     }
    2423 }
     2515  tr_peerMsgs * m;
     2516
     2517  assert (io != NULL);
     2518
     2519  m = tr_new0 (tr_peerMsgs, 1);
     2520
     2521  tr_peerConstruct (&m->peer, torrent);
     2522  m->peer.funcs = &my_funcs;
     2523
     2524  m->magic_number = MAGIC_NUMBER;
     2525  m->client_is_choked = true;
     2526  m->peer_is_choked = true;
     2527  m->client_is_interested = false;
     2528  m->peer_is_interested = false;
     2529  m->callback = callback;
     2530  m->callbackData = callbackData;
     2531  m->io = io;
     2532  m->torrent = torrent;
     2533  m->state = AWAITING_BT_LENGTH;
     2534  m->outMessages = evbuffer_new ();
     2535  m->outMessagesBatchedAt = 0;
     2536  m->outMessagesBatchPeriod = LOW_PRIORITY_INTERVAL_SECS;
     2537
     2538  if (tr_torrentAllowsPex (torrent))
     2539    {
     2540      m->pexTimer = evtimer_new (torrent->session->event_base, pexPulse, m);
     2541      tr_timerAdd (m->pexTimer, PEX_INTERVAL_SECS, 0);
     2542    }
     2543
     2544  if (tr_peerIoSupportsUTP (m->io))
     2545    {
     2546      const tr_address * addr = tr_peerIoGetAddress (m->io, NULL);
     2547      tr_peerMgrSetUtpSupported (torrent, addr);
     2548      tr_peerMgrSetUtpFailed (torrent, addr, false);
     2549    }
     2550
     2551  if (tr_peerIoSupportsLTEP (m->io))
     2552    sendLtepHandshake (m);
     2553
     2554  tellPeerWhatWeHave (m);
     2555
     2556  if (tr_dhtEnabled (torrent->session) && tr_peerIoSupportsDHT (m->io))
     2557    {
     2558      /* Only send PORT over IPv6 when the IPv6 DHT is running (BEP-32). */
     2559      const struct tr_address *addr = tr_peerIoGetAddress (m->io, NULL);
     2560      if (addr->type == TR_AF_INET || tr_globalIPv6 ())
     2561        protocolSendPort (m, tr_dhtPort (torrent->session));
     2562    }
     2563
     2564  tr_peerIoSetIOFuncs (m->io, canRead, didWrite, gotError, m);
     2565  updateDesiredRequestCount (m);
     2566
     2567  return m;
     2568}
  • trunk/libtransmission/peer-msgs.h

    r13936 r13954  
    1212
    1313#ifndef __TRANSMISSION__
    14 #error only libtransmission should #include this header.
     14 #error only libtransmission should #include this header.
    1515#endif
    1616
     
    2424struct tr_bitfield;
    2525struct tr_peer;
     26struct tr_peerIo;
    2627struct tr_torrent;
    2728
     
    3132 */
    3233
    33 typedef struct tr_peermsgs tr_peermsgs;
     34typedef struct tr_peerMsgs tr_peerMsgs;
    3435
    35 tr_peermsgs* tr_peerMsgsNew              (struct tr_torrent        * torrent,
    36                                           struct tr_peer           * peer,
    37                                           tr_peer_callback         * callback,
    38                                           void                     * callback_data);
     36#define PEER_MSGS(o) (tr_peerMsgsCast(o))
    3937
    40 void         tr_peerMsgsSetChoke         (tr_peermsgs              * msgs,
    41                                           bool                       peerIsChoked);
     38bool         tr_isPeerMsgs                   (const void               * msgs);
    4239
    43 int          tr_peerMsgsIsReadingBlock   (const tr_peermsgs        * msgs,
    44                                           tr_block_index_t           block);
     40tr_peerMsgs* tr_peerMsgsCast                 (void                     * msgs);
    4541
    46 void         tr_peerMsgsSetInterested    (tr_peermsgs              * msgs,
    47                                           bool                       clientIsInterested);
     42tr_peerMsgs* tr_peerMsgsNew                  (struct tr_torrent        * torrent,
     43                                              struct tr_peerIo         * io,
     44                                              tr_peer_callback         * callback,
     45                                              void                     * callback_data);
    4846
    49 void         tr_peerMsgsHave             (tr_peermsgs              * msgs,
    50                                           uint32_t                   pieceIndex);
     47bool         tr_peerMsgsIsPeerChoked         (const tr_peerMsgs        * msgs);
    5148
    52 void         tr_peerMsgsPulse            (tr_peermsgs              * msgs);
     49bool         tr_peerMsgsIsPeerInterested     (const tr_peerMsgs        * msgs);
    5350
    54 void         tr_peerMsgsCancel           (tr_peermsgs              * msgs,
    55                                           tr_block_index_t           block);
     51bool         tr_peerMsgsIsClientChoked       (const tr_peerMsgs        * msgs);
    5652
    57 void         tr_peerMsgsFree             (tr_peermsgs              * msgs);
     53bool         tr_peerMsgsIsClientInterested   (const tr_peerMsgs        * msgs);
    5854
    59 size_t       tr_generateAllowedSet       (tr_piece_index_t         * setmePieces,
    60                                           size_t                     desiredSetSize,
    61                                           size_t                     pieceCount,
    62                                           const uint8_t            * infohash,
    63                                           const struct tr_address  * addr);
     55time_t       tr_peerMsgsGetConnectionAge     (const tr_peerMsgs        * msgs);
     56
     57bool         tr_peerMsgsIsUtpConnection      (const tr_peerMsgs        * msgs);
     58
     59bool         tr_peerMsgsIsEncrypted          (const tr_peerMsgs        * msgs);
     60
     61bool         tr_peerMsgsIsIncomingConnection (const tr_peerMsgs        * msgs);
     62
     63void         tr_peerMsgsSetChoke             (tr_peerMsgs              * msgs,
     64                                              bool                       peerIsChoked);
     65
     66int          tr_peerMsgsIsReadingBlock       (const tr_peerMsgs        * msgs,
     67                                              tr_block_index_t           block);
     68
     69void         tr_peerMsgsSetInterested        (tr_peerMsgs              * msgs,
     70                                              bool                       clientIsInterested);
     71
     72void         tr_peerMsgsHave                 (tr_peerMsgs              * msgs,
     73                                              uint32_t                   pieceIndex);
     74
     75void         tr_peerMsgsPulse                (tr_peerMsgs              * msgs);
     76
     77void         tr_peerMsgsCancel               (tr_peerMsgs              * msgs,
     78                                              tr_block_index_t           block);
     79
     80size_t       tr_generateAllowedSet           (tr_piece_index_t         * setmePieces,
     81                                              size_t                     desiredSetSize,
     82                                              size_t                     pieceCount,
     83                                              const uint8_t            * infohash,
     84                                              const struct tr_address  * addr);
    6485
    6586
  • trunk/libtransmission/webseed.c

    r13900 r13954  
    3030struct tr_webseed_task
    3131{
    32     struct evbuffer    * content;
    33     struct tr_webseed  * webseed;
    34     tr_block_index_t     block;
    35     tr_piece_index_t     piece_index;
    36     uint32_t             piece_offset;
    37     uint32_t             length;
    38     tr_block_index_t     blocks_done;
    39     uint32_t             block_size;
    40     struct tr_web_task * web_task;
    41     long                 response_code;
     32  bool                 dead;
     33  struct evbuffer    * content;
     34  struct tr_webseed  * webseed;
     35  tr_session         * session;
     36  tr_block_index_t     block;
     37  tr_piece_index_t     piece_index;
     38  uint32_t             piece_offset;
     39  uint32_t             length;
     40  tr_block_index_t     blocks_done;
     41  uint32_t             block_size;
     42  struct tr_web_task * web_task;
     43  long                 response_code;
    4244};
    4345
    4446struct tr_webseed
    4547{
    46     tr_peer              parent;
    47     tr_bandwidth         bandwidth;
    48     tr_session         * session;
    49     tr_peer_callback   * callback;
    50     void               * callback_data;
    51     tr_list            * tasks;
    52     struct event       * timer;
    53     char               * base_url;
    54     size_t               base_url_len;
    55     int                  torrent_id;
    56     bool                 is_stopping;
    57     int                  consecutive_failures;
    58     int                  retry_tickcount;
    59     int                  retry_challenge;
    60     int                  idle_connections;
    61     int                  active_transfers;
    62     char              ** file_urls;
     48  tr_peer              parent;
     49  tr_bandwidth         bandwidth;
     50  tr_session         * session;
     51  tr_peer_callback   * callback;
     52  void               * callback_data;
     53  tr_list            * tasks;
     54  struct event       * timer;
     55  char               * base_url;
     56  size_t               base_url_len;
     57  int                  torrent_id;
     58  int                  consecutive_failures;
     59  int                  retry_tickcount;
     60  int                  retry_challenge;
     61  int                  idle_connections;
     62  int                  active_transfers;
     63  char              ** file_urls;
    6364};
    6465
    6566enum
    6667{
    67     TR_IDLE_TIMER_MSEC = 2000,
    68 
    69     FAILURE_RETRY_INTERVAL = 150,
    70 
    71     MAX_CONSECUTIVE_FAILURES = 5,
    72 
    73     MAX_WEBSEED_CONNECTIONS = 4
     68  TR_IDLE_TIMER_MSEC = 2000,
     69
     70  FAILURE_RETRY_INTERVAL = 150,
     71
     72  MAX_CONSECUTIVE_FAILURES = 5,
     73
     74  MAX_WEBSEED_CONNECTIONS = 4
    7475};
    75 
    76 static void
    77 webseed_free (struct tr_webseed * w)
    78 {
    79     tr_torrent * tor = tr_torrentFindFromId (w->session, w->torrent_id);
    80     const tr_info * inf = tr_torrentInfo (tor);
    81     tr_file_index_t i;
    82 
    83     /* if we have an array of file URLs, free it */
    84     if (w->file_urls != NULL) {
    85         for (i=0; i<inf->fileCount; ++i)
    86             tr_free (w->file_urls[i]);
    87         tr_free (w->file_urls);
    88     }
    89 
    90     /* webseed destruct */
    91     event_free (w->timer);
    92     tr_bandwidthDestruct (&w->bandwidth);
    93     tr_free (w->base_url);
    94 
    95     /* parent class destruct */
    96     tr_peerDestruct (tor, &w->parent);
    97 
    98     tr_free (w);
    99 }
    10076
    10177/***
     
    11187
    11288static void
    113 fire_client_got_rejs (tr_torrent * tor, tr_webseed * w,
    114                       tr_block_index_t block, tr_block_index_t count)
    115 {
    116     tr_block_index_t i;
    117     tr_peer_event e = TR_PEER_EVENT_INIT;
    118     e.eventType = TR_PEER_CLIENT_GOT_REJ;
    119     tr_torrentGetBlockLocation (tor, block, &e.pieceIndex, &e.offset, &e.length);
    120     for (i = 1; i <= count; i++) {
    121         if (i == count)
    122             e.length = tr_torBlockCountBytes (tor, block + count - 1);
    123         publish (w, &e);
    124         e.offset += e.length;
    125     }
    126 }
    127 
    128 static void
    129 fire_client_got_blocks (tr_torrent * tor, tr_webseed * w,
    130                         tr_block_index_t block, tr_block_index_t count)
    131 {
    132     tr_block_index_t i;
    133     tr_peer_event e = TR_PEER_EVENT_INIT;
    134     e.eventType = TR_PEER_CLIENT_GOT_BLOCK;
    135     tr_torrentGetBlockLocation (tor, block, &e.pieceIndex, &e.offset, &e.length);
    136     for (i = 1; i <= count; i++) {
    137         if (i == count)
    138             e.length = tr_torBlockCountBytes (tor, block + count - 1);
    139         publish (w, &e);
    140         e.offset += e.length;
     89fire_client_got_rejs (tr_torrent        * tor,
     90                      tr_webseed        * w,
     91                      tr_block_index_t    block,
     92                      tr_block_index_t    count)
     93{
     94  tr_block_index_t i;
     95  tr_peer_event e = TR_PEER_EVENT_INIT;
     96  e.eventType = TR_PEER_CLIENT_GOT_REJ;
     97  tr_torrentGetBlockLocation (tor, block, &e.pieceIndex, &e.offset, &e.length);
     98  for (i = 1; i <= count; i++)
     99    {
     100      if (i == count)
     101        e.length = tr_torBlockCountBytes (tor, block + count - 1);
     102      publish (w, &e);
     103      e.offset += e.length;
     104    }
     105}
     106
     107static void
     108fire_client_got_blocks (tr_torrent        * tor,
     109                        tr_webseed        * w,
     110                        tr_block_index_t    block,
     111                        tr_block_index_t    count)
     112{
     113  tr_block_index_t i;
     114  tr_peer_event e = TR_PEER_EVENT_INIT;
     115  e.eventType = TR_PEER_CLIENT_GOT_BLOCK;
     116  tr_torrentGetBlockLocation (tor, block, &e.pieceIndex, &e.offset, &e.length);
     117  for (i = 1; i <= count; i++)
     118    {
     119      if (i == count)
     120        e.length = tr_torBlockCountBytes (tor, block + count - 1);
     121      publish (w, &e);
     122      e.offset += e.length;
    141123    }
    142124}
     
    145127fire_client_got_piece_data (tr_webseed * w, uint32_t length)
    146128{
    147     tr_peer_event e = TR_PEER_EVENT_INIT;
    148     e.eventType = TR_PEER_CLIENT_GOT_PIECE_DATA;
    149     e.length = length;
    150     publish (w, &e);
     129  tr_peer_event e = TR_PEER_EVENT_INIT;
     130  e.eventType = TR_PEER_CLIENT_GOT_PIECE_DATA;
     131  e.length = length;
     132  publish (w, &e);
    151133}
    152134
     
    157139struct write_block_data
    158140{
    159     struct tr_webseed  * webseed;
    160     struct evbuffer    * content;
    161     tr_piece_index_t     piece_index;
    162     tr_block_index_t     block_index;
    163     tr_block_index_t     count;
    164     uint32_t             block_offset;
     141  tr_session         * session;
     142  int                  torrent_id;
     143  struct tr_webseed  * webseed;
     144  struct evbuffer    * content;
     145  tr_piece_index_t     piece_index;
     146  tr_block_index_t     block_index;
     147  tr_block_index_t     count;
     148  uint32_t             block_offset;
    165149};
    166150
     
    168152write_block_func (void * vdata)
    169153{
    170     struct write_block_data * data = vdata;
    171     struct tr_webseed * w = data->webseed;
    172     struct evbuffer * buf = data->content;
    173     struct tr_torrent * tor;
    174 
    175     tor = tr_torrentFindFromId (w->session, w->torrent_id);
    176     if (tor)
    177     {
    178         const uint32_t block_size = tor->blockSize;
    179         uint32_t len = evbuffer_get_length (buf);
    180         const uint32_t offset_end = data->block_offset + len;
    181         tr_cache * cache = w->session->cache;
    182         const tr_piece_index_t piece = data->piece_index;
    183 
    184         while (len > 0)
     154  struct write_block_data * data = vdata;
     155  struct tr_webseed * w = data->webseed;
     156  struct evbuffer * buf = data->content;
     157  struct tr_torrent * tor;
     158
     159  tor = tr_torrentFindFromId (data->session, data->torrent_id);
     160  if (tor != NULL)
     161    {
     162      const uint32_t block_size = tor->blockSize;
     163      uint32_t len = evbuffer_get_length (buf);
     164      const uint32_t offset_end = data->block_offset + len;
     165      tr_cache * cache = data->session->cache;
     166      const tr_piece_index_t piece = data->piece_index;
     167
     168      while (len > 0)
    185169        {
    186             const uint32_t bytes_this_pass = MIN (len, block_size);
    187             tr_cacheWriteBlock (cache, tor, piece, offset_end - len, bytes_this_pass, buf);
    188             len -= bytes_this_pass;
     170          const uint32_t bytes_this_pass = MIN (len, block_size);
     171          tr_cacheWriteBlock (cache, tor, piece, offset_end - len, bytes_this_pass, buf);
     172          len -= bytes_this_pass;
    189173        }
    190174
    191         fire_client_got_blocks (tor, w, data->block_index, data->count);
    192     }
    193 
    194     evbuffer_free (buf);
    195     tr_free (data);
     175      fire_client_got_blocks (tor, w, data->block_index, data->count);
     176    }
     177
     178  evbuffer_free (buf);
     179  tr_free (data);
    196180}
    197181
     
    202186struct connection_succeeded_data
    203187{
    204     struct tr_webseed  * webseed;
    205     char               * real_url;
    206     tr_piece_index_t     piece_index;
    207     uint32_t             piece_offset;
     188  struct tr_webseed  * webseed;
     189  char               * real_url;
     190  tr_piece_index_t     piece_index;
     191  uint32_t             piece_offset;
    208192};
    209193
     
    211195connection_succeeded (void * vdata)
    212196{
    213     tr_torrent * tor;
    214     struct connection_succeeded_data * data = vdata;
    215     struct tr_webseed * w = data->webseed;
    216 
    217     if (++w->active_transfers >= w->retry_challenge && w->retry_challenge)
    218         /* the server seems to be accepting more connections now */
    219         w->consecutive_failures = w->retry_tickcount = w->retry_challenge = 0;
    220 
    221     if (data->real_url &&
    222       (tor = tr_torrentFindFromId (w->session, w->torrent_id)))
    223     {
    224         uint64_t file_offset;
    225         tr_file_index_t file_index;
    226 
    227         tr_ioFindFileLocation (tor, data->piece_index, data->piece_offset,
    228                                &file_index, &file_offset);
    229         tr_free (w->file_urls[file_index]);
    230         w->file_urls[file_index] = data->real_url;
    231     }
     197  tr_torrent * tor;
     198  struct connection_succeeded_data * data = vdata;
     199  struct tr_webseed * w = data->webseed;
     200
     201  if (++w->active_transfers >= w->retry_challenge && w->retry_challenge)
     202    /* the server seems to be accepting more connections now */
     203    w->consecutive_failures = w->retry_tickcount = w->retry_challenge = 0;
     204
     205  if (data->real_url && (tor = tr_torrentFindFromId (w->session, w->torrent_id)))
     206    {
     207      uint64_t file_offset;
     208      tr_file_index_t file_index;
     209
     210      tr_ioFindFileLocation (tor, data->piece_index, data->piece_offset,
     211                             &file_index, &file_offset);
     212      tr_free (w->file_urls[file_index]);
     213      w->file_urls[file_index] = data->real_url;
     214      data->real_url = NULL;
     215    }
     216
     217  tr_free (data->real_url);
     218  tr_free (data);
    232219}
    233220
     
    241228                    void                           * vtask)
    242229{
    243     uint32_t len;
    244     const size_t n_added = info->n_added;
    245     struct tr_webseed_task * task = vtask;
    246     struct tr_webseed * w = task->webseed;
    247 
    248     if (n_added <= 0)
    249         return;
    250 
    251     if (!w->is_stopping)
    252     {
    253         tr_bandwidthUsed (&w->bandwidth, TR_DOWN, n_added, true, tr_time_msec ());
    254         fire_client_got_piece_data (w, n_added);
    255     }
    256 
    257     len = evbuffer_get_length (buf);
    258 
    259     if (!task->response_code)
    260     {
    261         tr_webGetTaskInfo (task->web_task, TR_WEB_GET_CODE, &task->response_code);
    262 
    263         if (task->response_code == 206)
     230  const size_t n_added = info->n_added;
     231  struct tr_webseed_task * task = vtask;
     232  tr_session * session = task->session;
     233
     234  tr_sessionLock (session);
     235
     236  if (!task->dead && (n_added>0))
     237    {
     238      uint32_t len;
     239      struct tr_webseed * w = task->webseed;
     240
     241      tr_bandwidthUsed (&w->bandwidth, TR_DOWN, n_added, true, tr_time_msec ());
     242      fire_client_got_piece_data (w, n_added);
     243      len = evbuffer_get_length (buf);
     244
     245      if (!task->response_code)
    264246        {
    265             const char * url;
    266             struct connection_succeeded_data * data;
    267 
    268             url = NULL;
    269             tr_webGetTaskInfo (task->web_task, TR_WEB_GET_REAL_URL, &url);
    270 
    271             data = tr_new (struct connection_succeeded_data, 1);
    272             data->webseed = w;
    273             data->real_url = tr_strdup (url);
    274             data->piece_index = task->piece_index;
    275             data->piece_offset = task->piece_offset
    276                                + (task->blocks_done * task->block_size)
    277                                + (len - 1);
    278 
    279             /* processing this uses a tr_torrent pointer,
    280                so push the work to the libevent thread... */
    281             tr_runInEventThread (w->session, connection_succeeded, data);
     247          tr_webGetTaskInfo (task->web_task, TR_WEB_GET_CODE, &task->response_code);
     248
     249          if (task->response_code == 206)
     250            {
     251              const char * url;
     252              struct connection_succeeded_data * data;
     253
     254              url = NULL;
     255              tr_webGetTaskInfo (task->web_task, TR_WEB_GET_REAL_URL, &url);
     256
     257              data = tr_new (struct connection_succeeded_data, 1);
     258              data->webseed = w;
     259              data->real_url = tr_strdup (url);
     260              data->piece_index = task->piece_index;
     261              data->piece_offset = task->piece_offset + (task->blocks_done * task->block_size) + (len - 1);
     262
     263              /* processing this uses a tr_torrent pointer,
     264                 so push the work to the libevent thread... */
     265              tr_runInEventThread (w->session, connection_succeeded, data);
     266            }
    282267        }
    283     }
    284 
    285     if ((task->response_code == 206) && (len >= task->block_size))
    286     {
    287         /* once we've got at least one full block, save it */
    288 
    289         struct write_block_data * data;
    290         const uint32_t block_size = task->block_size;
    291         const tr_block_index_t completed = len / block_size;
    292 
    293         data = tr_new (struct write_block_data, 1);
    294         data->webseed = task->webseed;
    295         data->piece_index = task->piece_index;
    296         data->block_index = task->block + task->blocks_done;
    297         data->count = completed;
    298         data->block_offset = task->piece_offset + task->blocks_done * block_size;
    299         data->content = evbuffer_new ();
    300 
    301         /* we don't use locking on this evbuffer so we must copy out the data
    302         that will be needed when writing the block in a different thread */
    303         evbuffer_remove_buffer (task->content, data->content,
    304                                 block_size * completed);
    305 
    306         tr_runInEventThread (w->session, write_block_func, data);
    307         task->blocks_done += completed;
    308     }
     268
     269      if ((task->response_code == 206) && (len >= task->block_size))
     270        {
     271          /* once we've got at least one full block, save it */
     272
     273          struct write_block_data * data;
     274          const uint32_t block_size = task->block_size;
     275          const tr_block_index_t completed = len / block_size;
     276
     277          data = tr_new (struct write_block_data, 1);
     278          data->webseed = task->webseed;
     279          data->piece_index = task->piece_index;
     280          data->block_index = task->block + task->blocks_done;
     281          data->count = completed;
     282          data->block_offset = task->piece_offset + task->blocks_done * block_size;
     283          data->content = evbuffer_new ();
     284          data->torrent_id = w->torrent_id;
     285          data->session = w->session;
     286
     287          /* we don't use locking on this evbuffer so we must copy out the data
     288             that will be needed when writing the block in a different thread */
     289          evbuffer_remove_buffer (task->content, data->content,
     290                                  block_size * completed);
     291 
     292          tr_runInEventThread (w->session, write_block_func, data);
     293          task->blocks_done += completed;
     294        }
     295    }
     296
     297  tr_sessionUnlock (session);
    309298}
    310299
    311300static void task_request_next_chunk (struct tr_webseed_task * task);
    312301
    313 static bool
    314 webseed_has_tasks (const tr_webseed * w)
    315 {
    316     return w->tasks != NULL;
    317 }
    318 
    319 
    320302static void
    321303on_idle (tr_webseed * w)
    322304{
    323     tr_torrent * tor = tr_torrentFindFromId (w->session, w->torrent_id);
    324     int want, running_tasks = tr_list_size (w->tasks);
    325 
    326     if (w->consecutive_failures >= MAX_CONSECUTIVE_FAILURES) {
    327         want = w->idle_connections;
    328 
    329         if (w->retry_tickcount >= FAILURE_RETRY_INTERVAL) {
    330             /* some time has passed since our connection attempts failed. try again */
    331             ++want;
    332             /* if this challenge is fulfilled we will reset consecutive_failures */
    333             w->retry_challenge = running_tasks + want;
     305  int want;
     306  int running_tasks = tr_list_size (w->tasks);
     307  tr_torrent * tor = tr_torrentFindFromId (w->session, w->torrent_id);
     308
     309  if (w->consecutive_failures >= MAX_CONSECUTIVE_FAILURES)
     310    {
     311      want = w->idle_connections;
     312
     313      if (w->retry_tickcount >= FAILURE_RETRY_INTERVAL)
     314        {
     315          /* some time has passed since our connection attempts failed. try again */
     316          ++want;
     317          /* if this challenge is fulfilled we will reset consecutive_failures */
     318          w->retry_challenge = running_tasks + want;
    334319        }
    335320    }
    336     else {
    337         want = MAX_WEBSEED_CONNECTIONS - running_tasks;
    338         w->retry_challenge = running_tasks + w->idle_connections + 1;
    339     }
    340 
    341     if (w->is_stopping && !webseed_has_tasks (w))
    342     {
    343         webseed_free (w);
    344     }
    345     else if (!w->is_stopping && tor
    346                              && tor->isRunning
    347                              && !tr_torrentIsSeed (tor)
    348                              && want)
    349     {
    350         int i;
    351         int got = 0;
    352         tr_block_index_t * blocks = NULL;
    353 
    354         blocks = tr_new (tr_block_index_t, want*2);
    355         tr_peerMgrGetNextRequests (tor, &w->parent, want, blocks, &got, true);
    356 
    357         w->idle_connections -= MIN (w->idle_connections, got);
    358         if (w->retry_tickcount >= FAILURE_RETRY_INTERVAL && got == want)
    359             w->retry_tickcount = 0;
    360 
    361         for (i=0; i<got; ++i)
     321  else
     322    {
     323      want = MAX_WEBSEED_CONNECTIONS - running_tasks;
     324      w->retry_challenge = running_tasks + w->idle_connections + 1;
     325    }
     326
     327  if (tor && tor->isRunning && !tr_torrentIsSeed (tor) && want)
     328    {
     329      int i;
     330      int got = 0;
     331      tr_block_index_t * blocks = NULL;
     332
     333      blocks = tr_new (tr_block_index_t, want*2);
     334      tr_peerMgrGetNextRequests (tor, &w->parent, want, blocks, &got, true);
     335
     336      w->idle_connections -= MIN (w->idle_connections, got);
     337      if (w->retry_tickcount >= FAILURE_RETRY_INTERVAL && got == want)
     338        w->retry_tickcount = 0;
     339
     340      for (i=0; i<got; ++i)
    362341        {
    363             const tr_block_index_t b = blocks[i*2];
    364             const tr_block_index_t be = blocks[i*2+1];
    365             struct tr_webseed_task * task = tr_new (struct tr_webseed_task, 1);
    366             task->webseed = w;
    367             task->block = b;
    368             task->piece_index = tr_torBlockPiece (tor, b);
    369             task->piece_offset = (tor->blockSize * b)
    370                                 - (tor->info.pieceSize * task->piece_index);
    371             task->length = (be - b) * tor->blockSize + tr_torBlockCountBytes (tor, be);
    372             task->blocks_done = 0;
    373             task->response_code = 0;
    374             task->block_size = tor->blockSize;
    375             task->content = evbuffer_new ();
    376             evbuffer_add_cb (task->content, on_content_changed, task);
    377             tr_list_append (&w->tasks, task);
    378             task_request_next_chunk (task);
     342          const tr_block_index_t b = blocks[i*2];
     343          const tr_block_index_t be = blocks[i*2+1];
     344          struct tr_webseed_task * task;
     345
     346          task = tr_new0 (struct tr_webseed_task, 1);
     347          task->session = tor->session;
     348          task->webseed = w;
     349          task->block = b;
     350          task->piece_index = tr_torBlockPiece (tor, b);
     351          task->piece_offset = (tor->blockSize * b) - (tor->info.pieceSize * task->piece_index);
     352          task->length = (be - b) * tor->blockSize + tr_torBlockCountBytes (tor, be);
     353          task->blocks_done = 0;
     354          task->response_code = 0;
     355          task->block_size = tor->blockSize;
     356          task->content = evbuffer_new ();
     357          evbuffer_add_cb (task->content, on_content_changed, task);
     358          tr_list_append (&w->tasks, task);
     359          task_request_next_chunk (task);
    379360        }
    380361
    381         tr_free (blocks);
     362      tr_free (blocks);
    382363    }
    383364}
     
    393374                   void          * vtask)
    394375{
    395     struct tr_webseed_task * t = vtask;
    396     tr_webseed * w = t->webseed;
    397     tr_torrent * tor = tr_torrentFindFromId (session, w->torrent_id);
    398     const int success = (response_code == 206);
    399 
    400     if (tor)
    401     {
    402         /* active_transfers was only increased if the connection was successful */
    403         if (t->response_code == 206)
    404             --w->active_transfers;
    405 
    406         if (!success)
     376  tr_webseed * w;
     377  tr_torrent * tor;
     378  struct tr_webseed_task * t = vtask;
     379  const int success = (response_code == 206);
     380
     381  if (t->dead)
     382    {
     383      evbuffer_free (t->content);
     384      tr_free (t);
     385      return;
     386    }
     387
     388  w = t->webseed;
     389  tor = tr_torrentFindFromId (session, w->torrent_id);
     390  if (tor != NULL)
     391    {
     392      /* active_transfers was only increased if the connection was successful */
     393      if (t->response_code == 206)
     394        --w->active_transfers;
     395
     396      if (!success)
    407397        {
    408             const tr_block_index_t blocks_remain = (t->length + tor->blockSize - 1)
     398          const tr_block_index_t blocks_remain = (t->length + tor->blockSize - 1)
    409399                                                   / tor->blockSize - t->blocks_done;
    410400
    411             if (blocks_remain)
    412                 fire_client_got_rejs (tor, w, t->block + t->blocks_done, blocks_remain);
    413 
    414             if (t->blocks_done)
    415                 ++w->idle_connections;
    416             else if (++w->consecutive_failures >= MAX_CONSECUTIVE_FAILURES && !w->retry_tickcount)
    417                 /* now wait a while until retrying to establish a connection */
    418                 ++w->retry_tickcount;
    419 
    420             tr_list_remove_data (&w->tasks, t);
    421             evbuffer_free (t->content);
    422             tr_free (t);
     401          if (blocks_remain)
     402            fire_client_got_rejs (tor, w, t->block + t->blocks_done, blocks_remain);
     403
     404          if (t->blocks_done)
     405            ++w->idle_connections;
     406          else if (++w->consecutive_failures >= MAX_CONSECUTIVE_FAILURES && !w->retry_tickcount)
     407            /* now wait a while until retrying to establish a connection */
     408            ++w->retry_tickcount;
     409
     410          tr_list_remove_data (&w->tasks, t);
     411          evbuffer_free (t->content);
     412          tr_free (t);
    423413        }
    424414        else
    425415        {
    426             const uint32_t bytes_done = t->blocks_done * tor->blockSize;
    427             const uint32_t buf_len = evbuffer_get_length (t->content);
    428 
    429             if (bytes_done + buf_len < t->length)
     416          const uint32_t bytes_done = t->blocks_done * tor->blockSize;
     417          const uint32_t buf_len = evbuffer_get_length (t->content);
     418
     419          if (bytes_done + buf_len < t->length)
    430420            {
    431                 /* request finished successfully but there's still data missing. that
    432                 means we've reached the end of a file and need to request the next one */
    433                 t->response_code = 0;
    434                 task_request_next_chunk (t);
     421              /* request finished successfully but there's still data missing. that
     422                 means we've reached the end of a file and need to request the next one */
     423              t->response_code = 0;
     424              task_request_next_chunk (t);
    435425            }
    436426            else
    437427            {
    438                 if (buf_len) {
    439                     /* on_content_changed () will not write a block if it is smaller than
    440                     the torrent's block size, i.e. the torrent's very last block */
    441                     tr_cacheWriteBlock (session->cache, tor,
    442                                         t->piece_index, t->piece_offset + bytes_done,
    443                                         buf_len, t->content);
    444 
    445                     fire_client_got_blocks (tor, t->webseed,
    446                                             t->block + t->blocks_done, 1);
     428              if (buf_len)
     429                {
     430                  /* on_content_changed () will not write a block if it is smaller than
     431                     the torrent's block size, i.e. the torrent's very last block */
     432                  tr_cacheWriteBlock (session->cache, tor,
     433                                      t->piece_index, t->piece_offset + bytes_done,
     434                                      buf_len, t->content);
     435
     436                  fire_client_got_blocks (tor, t->webseed,
     437                                          t->block + t->blocks_done, 1);
    447438                }
    448439
    449                 ++w->idle_connections;
    450 
    451                 tr_list_remove_data (&w->tasks, t);
    452                 evbuffer_free (t->content);
    453                 tr_free (t);
    454 
    455                 on_idle (w);
     440              ++w->idle_connections;
     441
     442              tr_list_remove_data (&w->tasks, t);
     443              evbuffer_free (t->content);
     444              tr_free (t);
     445
     446              on_idle (w);
    456447            }
    457448        }
     
    462453make_url (tr_webseed * w, const tr_file * file)
    463454{
    464     struct evbuffer * buf = evbuffer_new ();
    465 
    466     evbuffer_add (buf, w->base_url, w->base_url_len);
    467 
    468     /* if url ends with a '/', add the torrent name */
    469     if (w->base_url[w->base_url_len - 1] == '/' && file->name)
    470         tr_http_escape (buf, file->name, strlen (file->name), false);
    471 
    472     return buf;
     455  struct evbuffer * buf = evbuffer_new ();
     456
     457  evbuffer_add (buf, w->base_url, w->base_url_len);
     458
     459  /* if url ends with a '/', add the torrent name */
     460  if (w->base_url[w->base_url_len - 1] == '/' && file->name)
     461    tr_http_escape (buf, file->name, strlen (file->name), false);
     462
     463  return buf;
    473464}
    474465
     
    476467task_request_next_chunk (struct tr_webseed_task * t)
    477468{
    478     tr_webseed * w = t->webseed;
    479     tr_torrent * tor = tr_torrentFindFromId (w->session, w->torrent_id);
    480     if (tor != NULL)
    481     {
    482         char range[64];
    483         char ** urls = t->webseed->file_urls;
    484 
    485         const tr_info * inf = tr_torrentInfo (tor);
    486         const uint64_t remain = t->length - t->blocks_done * tor->blockSize
    487                                 - evbuffer_get_length (t->content);
    488 
    489         const uint64_t total_offset = tr_pieceOffset (tor, t->piece_index,
    490                                                            t->piece_offset,
    491                                                            t->length - remain);
    492         const tr_piece_index_t step_piece = total_offset / inf->pieceSize;
    493         const uint64_t step_piece_offset
    494                                = total_offset - (inf->pieceSize * step_piece);
    495 
    496         tr_file_index_t file_index;
    497         const tr_file * file;
    498         uint64_t file_offset;
    499         uint64_t this_pass;
    500 
    501         tr_ioFindFileLocation (tor, step_piece, step_piece_offset,
    502                                     &file_index, &file_offset);
    503         file = &inf->files[file_index];
    504         this_pass = MIN (remain, file->length - file_offset);
    505 
    506         if (!urls[file_index])
    507             urls[file_index] = evbuffer_free_to_str (make_url (t->webseed, file));
    508 
    509         tr_snprintf (range, sizeof range, "%"PRIu64"-%"PRIu64,
    510                      file_offset, file_offset + this_pass - 1);
    511         t->web_task = tr_webRunWithBuffer (w->session, urls[file_index],
    512                                            range, NULL, web_response_func, t, t->content);
    513     }
    514 }
    515 
    516 bool
    517 tr_webseedGetSpeed_Bps (const tr_webseed * w,
    518                         uint64_t           now,
    519                         unsigned int     * setme_Bps)
    520 {
    521     const bool is_active = webseed_has_tasks (w);
    522     *setme_Bps = is_active ? tr_bandwidthGetPieceSpeed_Bps (&w->bandwidth, now, TR_DOWN) : 0;
    523     return is_active;
    524 }
    525 
    526 bool
    527 tr_webseedIsActive (const tr_webseed * w)
    528 {
    529     unsigned int Bps = 0;
    530     return tr_webseedGetSpeed_Bps (w, tr_time_msec (), &Bps) && (Bps > 0);
     469  tr_webseed * w = t->webseed;
     470  tr_torrent * tor = tr_torrentFindFromId (w->session, w->torrent_id);
     471  if (tor != NULL)
     472    {
     473      char range[64];
     474      char ** urls = t->webseed->file_urls;
     475
     476      const tr_info * inf = tr_torrentInfo (tor);
     477      const uint64_t remain = t->length - t->blocks_done * tor->blockSize
     478                            - evbuffer_get_length (t->content);
     479
     480      const uint64_t total_offset = tr_pieceOffset (tor, t->piece_index,
     481                                                         t->piece_offset,
     482                                                         t->length - remain);
     483      const tr_piece_index_t step_piece = total_offset / inf->pieceSize;
     484      const uint64_t step_piece_offset = total_offset - (inf->pieceSize * step_piece);
     485
     486      tr_file_index_t file_index;
     487      const tr_file * file;
     488      uint64_t file_offset;
     489      uint64_t this_pass;
     490
     491      tr_ioFindFileLocation (tor, step_piece, step_piece_offset,
     492                             &file_index, &file_offset);
     493      file = &inf->files[file_index];
     494      this_pass = MIN (remain, file->length - file_offset);
     495
     496      if (!urls[file_index])
     497        urls[file_index] = evbuffer_free_to_str (make_url (t->webseed, file));
     498
     499      tr_snprintf (range, sizeof range, "%"PRIu64"-%"PRIu64,
     500                   file_offset, file_offset + this_pass - 1);
     501      t->web_task = tr_webRunWithBuffer (w->session, urls[file_index],
     502                                         range, NULL, web_response_func, t, t->content);
     503    }
    531504}
    532505
     
    538511webseed_timer_func (evutil_socket_t foo UNUSED, short bar UNUSED, void * vw)
    539512{
    540     tr_webseed * w = vw;
    541     if (w->retry_tickcount)
    542         ++w->retry_tickcount;
    543     on_idle (w);
    544     tr_timerAddMsec (w->timer, TR_IDLE_TIMER_MSEC);
    545 }
     513  tr_webseed * w = vw;
     514
     515  if (w->retry_tickcount)
     516    ++w->retry_tickcount;
     517
     518  on_idle (w);
     519
     520  tr_timerAddMsec (w->timer, TR_IDLE_TIMER_MSEC);
     521}
     522
     523/***
     524****  tr_peer virtual functions
     525***/
     526
     527static bool
     528webseed_is_transferring_pieces (const tr_peer * peer,
     529                                uint64_t        now,
     530                                tr_direction    direction,
     531                                unsigned int  * setme_Bps)
     532{
     533  unsigned int Bps = 0;
     534  bool is_active = false;
     535
     536  if (direction == TR_DOWN)
     537    {
     538      const tr_webseed * w = (const tr_webseed *) peer;
     539      is_active = w->tasks != NULL;
     540      Bps = tr_bandwidthGetPieceSpeed_Bps (&w->bandwidth, now, direction);
     541    }
     542
     543  if (setme_Bps != NULL)
     544    *setme_Bps = Bps;
     545
     546  return is_active;
     547}
     548
     549static void
     550webseed_destruct (tr_peer * peer)
     551{
     552  tr_list * l;
     553  tr_webseed * w = (tr_webseed *) peer;
     554
     555  /* flag all the pending tasks as dead */
     556  for (l=w->tasks; l!=NULL; l=l->next)
     557    {
     558      struct tr_webseed_task * task = l->data;
     559      task->dead = true;
     560    }
     561  tr_list_free (&w->tasks, NULL);
     562
     563  /* if we have an array of file URLs, free it */
     564  if (w->file_urls != NULL)
     565    {
     566      tr_file_index_t i;
     567      tr_torrent * tor = tr_torrentFindFromId (w->session, w->torrent_id);
     568      const tr_info * inf = tr_torrentInfo (tor);
     569
     570      for (i=0; i<inf->fileCount; ++i)
     571        tr_free (w->file_urls[i]);
     572      tr_free (w->file_urls);
     573    }
     574
     575  /* webseed destruct */
     576  event_free (w->timer);
     577  tr_bandwidthDestruct (&w->bandwidth);
     578  tr_free (w->base_url);
     579
     580  /* parent class destruct */
     581  tr_peerDestruct (&w->parent);
     582}
     583
     584static const struct tr_peer_virtual_funcs my_funcs =
     585{
     586  .destruct = webseed_destruct,
     587  .is_transferring_pieces = webseed_is_transferring_pieces
     588};
     589
     590/***
     591****
     592***/
    546593
    547594tr_webseed*
     
    551598               void               * callback_data)
    552599{
    553     tr_webseed * w = tr_new0 (tr_webseed, 1);
    554     tr_peer * peer = &w->parent;
    555     const tr_info * inf = tr_torrentInfo (tor);
    556 
    557     /* construct parent class */
    558     tr_peerConstruct (peer);
    559     peer->peerIsChoked = true;
    560     peer->clientIsInterested = !tr_torrentIsSeed (tor);
    561     peer->client = TR_KEY_webseeds;
    562     tr_bitfieldSetHasAll (&peer->have);
    563     tr_peerUpdateProgress (tor, peer);
    564 
    565     w->torrent_id = tr_torrentId (tor);
    566     w->session = tor->session;
    567     w->base_url_len = strlen (url);
    568     w->base_url = tr_strndup (url, w->base_url_len);
    569     w->callback = callback;
    570     w->callback_data = callback_data;
    571     w->file_urls = tr_new0 (char *, inf->fileCount);
    572     //tr_rcConstruct (&w->download_rate);
    573     tr_bandwidthConstruct (&w->bandwidth, tor->session, &tor->bandwidth);
    574     w->timer = evtimer_new (w->session->event_base, webseed_timer_func, w);
    575     tr_timerAddMsec (w->timer, TR_IDLE_TIMER_MSEC);
    576     return w;
    577 }
    578 
    579 void
    580 tr_webseedFree (tr_webseed * w)
    581 {
    582     if (w)
    583     {
    584         if (webseed_has_tasks (w))
    585             w->is_stopping = true;
    586         else
    587             webseed_free (w);
    588     }
    589 }
     600  tr_webseed * w = tr_new0 (tr_webseed, 1);
     601  tr_peer * peer = &w->parent;
     602  const tr_info * inf = tr_torrentInfo (tor);
     603
     604  /* construct parent class */
     605  tr_peerConstruct (peer, tor);
     606  peer->client = TR_KEY_webseeds;
     607  peer->funcs = &my_funcs;
     608  tr_bitfieldSetHasAll (&peer->have);
     609  tr_peerUpdateProgress (tor, peer);
     610
     611  w->torrent_id = tr_torrentId (tor);
     612  w->session = tor->session;
     613  w->base_url_len = strlen (url);
     614  w->base_url = tr_strndup (url, w->base_url_len);
     615  w->callback = callback;
     616  w->callback_data = callback_data;
     617  w->file_urls = tr_new0 (char *, inf->fileCount);
     618  //tr_rcConstruct (&w->download_rate);
     619  tr_bandwidthConstruct (&w->bandwidth, tor->session, &tor->bandwidth);
     620  w->timer = evtimer_new (w->session->event_base, webseed_timer_func, w);
     621  tr_timerAddMsec (w->timer, TR_IDLE_TIMER_MSEC);
     622  return w;
     623}
  • trunk/libtransmission/webseed.h

    r13625 r13954  
    2727                           void              * callback_data);
    2828
    29 void        tr_webseedFree (tr_webseed *);
    30 
    31 /** @return true if a request is being processed, or false if idle */
    32 bool        tr_webseedGetSpeed_Bps (const tr_webseed * w,
    33                                     uint64_t           now,
    34                                     unsigned int     * setme_Bps);
    35 
    36 /** @return true if a request is being processed, or false if idle */
    37 bool        tr_webseedIsActive (const tr_webseed * w);
    38 
    39 
    4029#endif
Note: See TracChangeset for help on using the changeset viewer.