]> granicus.if.org Git - transmission/commitdiff
(libT) make the class hierarchy between tr_peer, tr_peerMsgs, and tr_webseed a little...
authorJordan Lee <jordan@transmissionbt.com>
Mon, 4 Feb 2013 16:23:33 +0000 (16:23 +0000)
committerJordan Lee <jordan@transmissionbt.com>
Mon, 4 Feb 2013 16:23:33 +0000 (16:23 +0000)
libtransmission/clients.c
libtransmission/clients.h
libtransmission/peer-common.h
libtransmission/peer-io.h
libtransmission/peer-mgr.c
libtransmission/peer-mgr.h
libtransmission/peer-msgs.c
libtransmission/peer-msgs.h
libtransmission/webseed.c
libtransmission/webseed.h

index 7c2df0a1e7535f1be928b106e6e000aadd02a9fa..659086d5e54af84f56255d7c79b0d4e2fd48d224 100644 (file)
@@ -143,7 +143,7 @@ decodeBitCometClient (char * buf, size_t buflen, const uint8_t * id)
     return true;
 }
 
-void
+char *
 tr_clientForId (char * buf, size_t buflen, const void * id_in)
 {
     const uint8_t * id = id_in;
@@ -151,7 +151,7 @@ tr_clientForId (char * buf, size_t buflen, const void * id_in)
     *buf = '\0';
 
     if (!id)
-        return;
+        return buf;
 
     /* Azureus-style */
     if (id[0] == '-' && id[7] == '-')
@@ -308,7 +308,7 @@ tr_clientForId (char * buf, size_t buflen, const void * id_in)
         }
 
         if (*buf)
-            return;
+            return buf;
     }
 
     /* uTorrent will replace the trailing dash with an extra digit for longer version numbers */
@@ -331,7 +331,7 @@ tr_clientForId (char * buf, size_t buflen, const void * id_in)
         }
 
         if (*buf)
-            return;
+            return buf;
     }
 
     /* Mainline */
@@ -339,11 +339,11 @@ tr_clientForId (char * buf, size_t buflen, const void * id_in)
     {
         if (*id=='M') mainline_style (buf, buflen, "BitTorrent", id);
         if (*id=='Q') mainline_style (buf, buflen, "Queen Bee", id);
-        if (*buf) return;
+        if (*buf) return buf;
     }
 
     if (decodeBitCometClient (buf, buflen, id))
-        return;
+        return buf;
 
     /* Clients with no version */
          if (!memcmp (id, "AZ2500BT", 8))  no_version (buf, buflen, "BitTyrant (Azureus Mod)");
@@ -440,7 +440,7 @@ tr_clientForId (char * buf, size_t buflen, const void * id_in)
             if (name)
             {
                 tr_snprintf (buf, buflen, "%s %d.%d.%d", name, a, b, c);
-                return;
+                return buf;
             }
         }
     }
@@ -461,4 +461,6 @@ tr_clientForId (char * buf, size_t buflen, const void * id_in)
         *walk = '\0';
         tr_strlcpy (buf, out, buflen);
     }
+
+  return buf;
 }
index dc18d5cab31da168eb49f5f2d1e3a3b4f8a8012b..c260ef1c262acd48a82c5bdcef5c47bb03301270 100644 (file)
@@ -21,6 +21,6 @@
  * @brief parse a peer-id into a human-readable client name and version number
  * @ingroup utils
  */
-void tr_clientForId (char * buf, size_t buflen, const void * peer_id);
+char* tr_clientForId (char * buf, size_t buflen, const void * peer_id);
 
 #endif
index f9a7adef077fb55d23460138890b17c929ddf1ca..0598fae521bb0a25cd249a3617eb391cf7ac7610 100644 (file)
@@ -27,6 +27,9 @@
  * @{
  */
 
+struct tr_peer;
+struct tr_swarm;
+
 enum
 {
   /* this is the maximum size of a block request.
@@ -72,11 +75,30 @@ tr_peer_event;
 
 extern const tr_peer_event TR_PEER_EVENT_INIT;
 
+typedef void tr_peer_callback (struct tr_peer       * peer,
+                               const tr_peer_event  * event,
+                               void                 * client_data);
+
+/***
+****
+***/
+
+typedef void (*tr_peer_destruct_func)(struct tr_peer * peer);
+typedef bool (*tr_peer_is_transferring_pieces_func)(const struct tr_peer * peer,
+                                                    uint64_t now,
+                                                    tr_direction direction,
+                                                    unsigned int * Bps);
+struct tr_peer_virtual_funcs
+{
+  tr_peer_destruct_func destruct;
+  tr_peer_is_transferring_pieces_func is_transferring_pieces;
+};
+
 /**
  * State information about a connected peer.
  *
  * @see struct peer_atom
- * @see tr_peermsgs
+ * @see tr_peerMsgs
  */
 typedef struct tr_peer
 {
@@ -84,22 +106,6 @@ typedef struct tr_peer
      NOTE: private to peer-mgr.c */
   bool doPurge;
 
-  /* Whether or not we've choked this peer.
-     Only applies to BitTorrent peers */
-  bool peerIsChoked;
-
-  /* whether or not the peer has indicated it will download from us.
-     Only applies to BitTorrent peers */
-  bool peerIsInterested;
-
-  /* whether or the peer is choking us.
-     Only applies to BitTorrent peers */
-  bool clientIsChoked;
-
-  /* whether or not we've indicated to the peer that we would download from them if unchoked.
-     Only applies to BitTorrent peers */
-  bool clientIsInterested;
-
   /* number of bad pieces they've contributed to */
   uint8_t strikes;
 
@@ -109,11 +115,11 @@ typedef struct tr_peer
   /* how many requests we've made and are currently awaiting a response for */
   int pendingReqsToPeer;
 
-  struct tr_peerIo * io;
-
   /* Hook to private peer-mgr information */
   struct peer_atom * atom;
 
+  struct tr_swarm * swarm;
+
   /** how complete the peer's copy of the torrent is. [0.0...1.0] */
   float progress;
 
@@ -124,21 +130,21 @@ typedef struct tr_peer
      For BitTorrent peers, this is the app name derived from the `v' string in LTEP's handshake dictionary */
   tr_quark client;
 
-  time_t chokeChangedAt;
-
   tr_recentHistory blocksSentToClient;
   tr_recentHistory blocksSentToPeer;
 
   tr_recentHistory cancelsSentToClient;
   tr_recentHistory cancelsSentToPeer;
 
-  struct tr_peermsgs * msgs;
+  const struct tr_peer_virtual_funcs * funcs;
 }
 tr_peer;
 
-typedef void tr_peer_callback (struct tr_peer       * peer,
-                               const tr_peer_event  * event,
-                               void                 * client_data);
+
+void tr_peerConstruct (struct tr_peer * peer, const tr_torrent * tor);
+
+void tr_peerDestruct  (struct tr_peer * peer);
+
 
 /** Update the tr_peer.progress field based on the 'have' bitset. */
 void tr_peerUpdateProgress (tr_torrent * tor, struct tr_peer *);
index 82b30ca3e872b3359fb99f3b70875f9c70b1716f..a592ed1f4ef0c7d105c6d3c586f68978f50b6ff9 100644 (file)
@@ -90,7 +90,7 @@ typedef struct tr_peerIo
 
     tr_port               port;
     int                   socket;
-    struct UTPSocket      *utp_socket;
+    struct UTPSocket    utp_socket;
 
     int                   refCount;
 
@@ -138,13 +138,13 @@ tr_peerIo*  tr_peerIoNewIncoming (tr_session              * session,
                                   int                       socket,
                                   struct UTPSocket *        utp_socket);
 
-void tr_peerIoRefImpl         (const char              * file,
+void tr_peerIoRefImpl            (const char              * file,
                                   int                       line,
                                   tr_peerIo               * io);
 
 #define tr_peerIoRef(io) tr_peerIoRefImpl (__FILE__, __LINE__, (io));
 
-void tr_peerIoUnrefImpl       (const char              * file,
+void tr_peerIoUnrefImpl          (const char              * file,
                                   int                       line,
                                   tr_peerIo               * io);
 
index 3da034b4f325d899012d14646c59119bfb341056..82bdad3be23b9219cfc535dc0871175c6e67a95f 100644 (file)
@@ -114,7 +114,7 @@ const tr_peer_event TR_PEER_EVENT_INIT = { 0, 0, NULL, 0, 0, 0, 0 };
  * for banned peers.
  *
  * @see tr_peer
- * @see tr_peermsgs
+ * @see tr_peerMsgs
  */
 struct peer_atom
 {
@@ -186,13 +186,13 @@ typedef struct tr_swarm
 {
   tr_ptrArray                outgoingHandshakes; /* tr_handshake */
   tr_ptrArray                pool; /* struct peer_atom */
-  tr_ptrArray                peers; /* tr_peer */
+  tr_ptrArray                peers; /* tr_peerMsgs */
   tr_ptrArray                webseeds; /* tr_webseed */
 
   tr_torrent               * tor;
   struct tr_peerMgr        * manager;
 
-  tr_peer                  * optimistic; /* the optimistic peer, or NULL if none */
+  tr_peerMsgs              * optimistic; /* the optimistic peer, or NULL if none */
   int                        optimisticUnchokeTimeScaler;
 
   bool                       isRunning;
@@ -251,6 +251,74 @@ struct tr_peerMgr
     } \
   while (0)
 
+/**
+*** tr_peer virtual functions
+**/
+
+static bool
+tr_peerIsTransferringPieces (const tr_peer * peer,
+                             uint64_t        now,
+                             tr_direction    direction,
+                             unsigned int  * Bps)
+{
+  assert (peer != NULL);
+  assert (peer->funcs != NULL);
+
+  return (*peer->funcs->is_transferring_pieces)(peer, now, direction, Bps);
+}
+
+unsigned int
+tr_peerGetPieceSpeed_Bps (const tr_peer    * peer,
+                          uint64_t           now,
+                          tr_direction       direction)
+{
+  unsigned int Bps = 0;
+  tr_peerIsTransferringPieces (peer, now, direction, &Bps);
+  return Bps;
+}
+
+static void
+tr_peerFree (tr_peer * peer)
+{
+  assert (peer != NULL);
+  assert (peer->funcs != NULL);
+
+  (*peer->funcs->destruct)(peer);
+
+  tr_free (peer);
+}
+
+void
+tr_peerConstruct (tr_peer * peer, const tr_torrent * tor)
+{
+  assert (peer != NULL);
+  assert (tr_isTorrent (tor));
+
+  memset (peer, 0, sizeof (tr_peer));
+
+  peer->client = TR_KEY_NONE;
+  peer->swarm = tor->swarm;
+  tr_bitfieldConstruct (&peer->have, tor->info.pieceCount);
+  tr_bitfieldConstruct (&peer->blame, tor->blockCount);
+}
+
+static void peerDeclinedAllRequests (tr_swarm *, const tr_peer *);
+
+void
+tr_peerDestruct (tr_peer * peer)
+{
+  assert (peer != NULL);
+
+  if (peer->swarm != NULL)
+    peerDeclinedAllRequests (peer->swarm, peer);
+
+  tr_bitfieldDestruct (&peer->have);
+  tr_bitfieldDestruct (&peer->blame);
+
+  if (peer->atom)
+    peer->atom->peer = NULL;
+}
+
 /**
 ***
 **/
@@ -375,78 +443,6 @@ peerIsInUse (const tr_swarm * cs, const struct peer_atom * atom)
       || getExistingHandshake (&s->manager->incomingHandshakes, &atom->addr);
 }
 
-void
-tr_peerConstruct (tr_peer * peer)
-{
-  memset (peer, 0, sizeof (tr_peer));
-
-  peer->have = TR_BITFIELD_INIT;
-}
-
-static tr_peer*
-peerNew (struct peer_atom * atom)
-{
-  tr_peer * peer = tr_new (tr_peer, 1);
-  tr_peerConstruct (peer);
-
-  peer->atom = atom;
-  atom->peer = peer;
-
-  return peer;
-}
-
-static tr_peer*
-getPeer (tr_swarm * s, struct peer_atom * atom)
-{
-  tr_peer * peer;
-
-  assert (swarmIsLocked (s));
-
-  peer = atom->peer;
-
-  if (peer == NULL)
-    {
-      peer = peerNew (atom);
-      tr_bitfieldConstruct (&peer->have, s->tor->info.pieceCount);
-      tr_bitfieldConstruct (&peer->blame, s->tor->blockCount);
-      tr_ptrArrayInsertSorted (&s->peers, peer, peerCompare);
-    }
-
-  return peer;
-}
-
-static void peerDeclinedAllRequests (tr_swarm *, const tr_peer *);
-
-void
-tr_peerDestruct (tr_torrent * tor, tr_peer * peer)
-{
-  assert (peer != NULL);
-
-  peerDeclinedAllRequests (tor->swarm, peer);
-
-  if (peer->msgs != NULL)
-    tr_peerMsgsFree (peer->msgs);
-
-  if (peer->io)
-    {
-      tr_peerIoClear (peer->io);
-      tr_peerIoUnref (peer->io); /* balanced by the ref in handshakeDoneCB () */
-    }
-
-  tr_bitfieldDestruct (&peer->have);
-  tr_bitfieldDestruct (&peer->blame);
-
-  if (peer->atom)
-    peer->atom->peer = NULL;
-}
-
-static void
-peerDelete (tr_swarm * s, tr_peer * peer)
-{
-  tr_peerDestruct (s->tor, peer);
-  tr_free (peer);
-}
-
 static inline bool
 replicationExists (const tr_swarm * s)
 {
@@ -466,8 +462,7 @@ replicationNew (tr_swarm * s)
 {
   tr_piece_index_t piece_i;
   const tr_piece_index_t piece_count = s->tor->info.pieceCount;
-  tr_peer ** peers = (tr_peer**) tr_ptrArrayBase (&s->peers);
-  const int peer_count = tr_ptrArraySize (&s->peers);
+  const int n = tr_ptrArraySize (&s->peers);
 
   assert (!replicationExists (s));
 
@@ -479,9 +474,12 @@ replicationNew (tr_swarm * s)
       int peer_i;
       uint16_t r = 0;
 
-      for (peer_i=0; peer_i<peer_count; ++peer_i)
-        if (tr_bitfieldHas (&peers[peer_i]->have, piece_i))
-          ++r;
+      for (peer_i=0; peer_i<n; ++peer_i)
+        {
+          tr_peer * peer = tr_ptrArrayNth (&s->peers, peer_i);
+          if (tr_bitfieldHas (&peer->have, piece_i))
+            ++r;
+        }
 
       s->pieceReplication[piece_i] = r;
     }
@@ -498,7 +496,7 @@ swarmFree (void * vs)
   assert (tr_ptrArrayEmpty (&s->outgoingHandshakes));
   assert (tr_ptrArrayEmpty (&s->peers));
 
-  tr_ptrArrayDestruct (&s->webseeds, (PtrArrayForeachFunc)tr_webseedFree);
+  tr_ptrArrayDestruct (&s->webseeds, (PtrArrayForeachFunc)tr_peerFree);
   tr_ptrArrayDestruct (&s->pool, (PtrArrayForeachFunc)tr_free);
   tr_ptrArrayDestruct (&s->outgoingHandshakes, NULL);
   tr_ptrArrayDestruct (&s->peers, NULL);
@@ -519,11 +517,11 @@ rebuildWebseedArray (tr_swarm * s, tr_torrent * tor)
   const tr_info * inf = &tor->info;
 
   /* clear the array */
-  tr_ptrArrayDestruct (&s->webseeds, (PtrArrayForeachFunc)tr_webseedFree);
+  tr_ptrArrayDestruct (&s->webseeds, (PtrArrayForeachFunc)tr_peerFree);
   s->webseeds = TR_PTR_ARRAY_INIT;
 
   /* repopulate it */
-  for (i = 0; i < inf->webseedCount; ++i)
+  for (i=0; i<inf->webseedCount; ++i)
     {
       tr_webseed * w = tr_webseedNew (tor, inf->webseeds[i], peerCallbackFunc, s);
       tr_ptrArrayAppend (&s->webseeds, w);
@@ -598,18 +596,18 @@ tr_peerMgrFree (tr_peerMgr * manager)
 }
 
 static int
-clientIsDownloadingFrom (const tr_torrent * tor, const tr_peer * peer)
+clientIsDownloadingFrom (const tr_torrent * tor, const tr_peerMsgs * p)
 {
   if (!tr_torrentHasMetadata (tor))
     return true;
 
-  return peer->clientIsInterested && !peer->clientIsChoked;
+  return tr_peerMsgsIsClientInterested (p) && !tr_peerMsgsIsClientChoked (p);
 }
 
 static int
-clientIsUploadingTo (const tr_peer * peer)
+clientIsUploadingTo (const tr_peerMsgs * p)
 {
-  return peer->peerIsInterested && !peer->peerIsChoked;
+  return tr_peerMsgsIsPeerInterested (p) && !tr_peerMsgsIsPeerChoked (p);
 }
 
 /***
@@ -868,14 +866,15 @@ requestListRemove (tr_swarm * s, tr_block_index_t block, const tr_peer * peer)
 }
 
 static int
-countActiveWebseeds (const tr_swarm * s)
+countActiveWebseeds (tr_swarm * s)
 {
+  int i;
   int activeCount = 0;
-  const tr_webseed ** w = (const tr_webseed **) tr_ptrArrayBase (&s->webseeds);
-  const tr_webseed ** const wend = w + tr_ptrArraySize (&s->webseeds);
+  const int n = tr_ptrArraySize (&s->webseeds);
+  const uint64_t now = tr_time_msec ();
 
-  for (; w!=wend; ++w)
-    if (tr_webseedIsActive (*w))
+  for (i=0; i<n; ++i)
+    if (tr_peerIsTransferringPieces (tr_ptrArrayNth(&s->webseeds,i), now, TR_DOWN, NULL))
       ++activeCount;
 
   return activeCount;
@@ -902,14 +901,17 @@ updateEndgame (tr_swarm * s)
     }
   else if (!s->endgame) /* only recalculate when endgame first begins */
     {
+      int i;
       int numDownloading = 0;
-      const tr_peer ** p = (const tr_peer **) tr_ptrArrayBase (&s->peers);
-      const tr_peer ** const pend = p + tr_ptrArraySize (&s->peers);
+      const int n = tr_ptrArraySize (&s->peers);
 
       /* add the active bittorrent peers... */
-      for (; p!=pend; ++p)
-        if ((*p)->pendingReqsToPeer > 0)
-          ++numDownloading;
+      for (i=0; i<n; ++i)
+        {
+          const tr_peer * p = tr_ptrArrayNth (&s->peers, i);
+          if (p->pendingReqsToPeer > 0)
+            ++numDownloading;
+        }
 
       /* add the active webseeds... */
       numDownloading += countActiveWebseeds (s);
@@ -1340,8 +1342,6 @@ tr_peerMgrGetNextRequests (tr_torrent           * tor,
 
   /* sanity clause */
   assert (tr_isTorrent (tor));
-  assert (peer->clientIsInterested);
-  assert (!peer->clientIsChoked);
   assert (numwant > 0);
 
   /* walk through the pieces and find blocks that should be requested */
@@ -1515,7 +1515,9 @@ refillUpkeep (int foo UNUSED, short bar UNUSED, void * vmgr)
 
             for (it=s->requests, end=it+n; it!=end; ++it)
             {
-                if ((it->sentAt <= too_old) && it->peer->msgs && !tr_peerMsgsIsReadingBlock (it->peer->msgs, it->block))
+                tr_peerMsgs * msgs = PEER_MSGS(it->peer);
+
+                if ((msgs !=NULL) && (it->sentAt <= too_old) && !tr_peerMsgsIsReadingBlock (msgs, it->block))
                     cancel[cancelCount++] = *it;
                 else
                 {
@@ -1529,11 +1531,15 @@ refillUpkeep (int foo UNUSED, short bar UNUSED, void * vmgr)
             s->requestCount = keepCount;
 
             /* send cancel messages for all the "cancel" ones */
-            for (it=cancel, end=it+cancelCount; it!=end; ++it) {
-                if ((it->peer != NULL) && (it->peer->msgs != NULL)) {
-                    tr_historyAdd (&it->peer->cancelsSentToPeer, now, 1);
-                    tr_peerMsgsCancel (it->peer->msgs, it->block);
-                    decrementPendingReqCount (it);
+            for (it=cancel, end=it+cancelCount; it!=end; ++it)
+            {
+              tr_peerMsgs * msgs = PEER_MSGS(it->peer);
+
+              if (msgs != NULL)
+                {
+                  tr_historyAdd (&it->peer->cancelsSentToPeer, now, 1);
+                  tr_peerMsgsCancel (msgs, it->block);
+                  decrementPendingReqCount (it);
                 }
             }
 
@@ -1655,10 +1661,10 @@ cancelAllRequestsForBlock (tr_swarm          * s,
     {
       tr_peer * p = peers[i];
 
-      if ((p != no_notify) && (p->msgs != NULL))
+      if ((p != no_notify) && (p != NULL))
         {
           tr_historyAdd (&p->cancelsSentToPeer, tr_time (), 1);
-          tr_peerMsgsCancel (p->msgs, block);
+          tr_peerMsgsCancel (PEER_MSGS(p), block);
         }
 
       removeRequestFromTables (s, block, p);
@@ -1670,19 +1676,21 @@ cancelAllRequestsForBlock (tr_swarm          * s,
 void
 tr_peerMgrPieceCompleted (tr_torrent * tor, tr_piece_index_t p)
 {
+  int i;
   bool pieceCameFromPeers = false;
   tr_swarm * const s = tor->swarm;
-  const tr_peer ** peer = (const tr_peer **) tr_ptrArrayBase (&s->peers);
-  const tr_peer ** const pend = peer + tr_ptrArraySize (&s->peers);
+  const int n = tr_ptrArraySize (&s->peers);
 
   /* walk through our peers */
-  for ( ; peer!=pend; ++peer)
+  for (i=0; i<n; ++i)
     {
+      tr_peer * peer = tr_ptrArrayNth (&s->peers, i);
+
       /* notify the peer that we now have this piece */
-      tr_peerMsgsHave ((*peer)->msgs, p);
+      tr_peerMsgsHave (PEER_MSGS(peer), p);
 
       if (!pieceCameFromPeers)
-        pieceCameFromPeers = tr_bitfieldHas (&(*peer)->blame, p);
+        pieceCameFromPeers = tr_bitfieldHas (&peer->blame, p);
     }
 
   if (pieceCameFromPeers) /* webseed downloads don't belong in announce totals */
@@ -1901,6 +1909,31 @@ getPeerCount (const tr_swarm * s)
   return tr_ptrArraySize (&s->peers);/* + tr_ptrArraySize (&t->outgoingHandshakes); */
 }
 
+
+static void
+createBitTorrentPeer (tr_torrent       * tor,
+                      struct tr_peerIo * io,
+                      struct peer_atom * atom,
+                      tr_quark           client)
+{
+  tr_peer * peer;
+  tr_swarm * swarm;
+
+  assert (atom != NULL);
+  assert (tr_isTorrent (tor));
+  assert (tor->swarm != NULL);
+
+  swarm = tor->swarm;
+
+  peer = (tr_peer*) tr_peerMsgsNew (tor, io, peerCallbackFunc, swarm);
+  peer->atom = atom;
+  peer->client = client;
+  atom->peer = peer;
+
+  tr_ptrArrayInsertSorted (&swarm->peers, peer, peerCompare);
+}
+
+
 /* FIXME: this is kind of a mess. */
 static bool
 myHandshakeDoneCB (tr_handshake  * handshake,
@@ -1997,21 +2030,19 @@ myHandshakeDoneCB (tr_handshake  * handshake,
             }
           else
             {
-              peer = getPeer (s, atom);
+              tr_quark client;
+              tr_peerIo * io;
+              char buf[128];
 
-              if (!peer_id)
-                peer->client = TR_KEY_NONE;
+              if (peer_id != NULL)
+                client = tr_quark_new (tr_clientForId (buf, sizeof (buf), peer_id), -1);
               else
-                {
-                  char client[128];
-                  tr_clientForId (client, sizeof (client), peer_id);
-                  peer->client = tr_quark_new (client, -1);
-                }
+                client = TR_KEY_NONE;
 
-              peer->io = tr_handshakeStealIO (handshake); /* this steals its refcount too, which is
-                                                                balanced by our unref in peerDelete ()  */
-              tr_peerIoSetParent (peer->io, &s->tor->bandwidth);
-              tr_peerMsgsNew (s->tor, peer, peerCallbackFunc, s);
+              io = tr_handshakeStealIO (handshake); /* this steals its refcount too, which is
+                                                       balanced by our unref in peerDelete ()  */
+              tr_peerIoSetParent (io, &s->tor->bandwidth);
+              createBitTorrentPeer (s->tor, io, atom, client);
 
               success = true;
             }
@@ -2400,7 +2431,7 @@ stopSwarm (tr_swarm * swarm)
 
   /* disconnect the peers. */
   while ((peer = tr_ptrArrayPop (&swarm->peers)))
-    peerDelete (swarm, peer);
+    tr_peerFree (peer);
 
   /* disconnect the handshakes. handshakeAbort calls handshakeDoneCB (),
    * which removes the handshake from t->outgoingHandshakes... */
@@ -2533,13 +2564,13 @@ tr_peerMgrTorrentAvailability (const tr_torrent  * tor,
 static bool
 peerIsSeed (const tr_peer * peer)
 {
-    if (peer->progress >= 1.0)
-        return true;
+  if (peer->progress >= 1.0)
+    return true;
 
-    if (peer->atom && atomIsSeed (peer->atom))
-        return true;
+  if (peer->atom && atomIsSeed (peer->atom))
+    return true;
 
-    return false;
+  return false;
 }
 
 /* count how many bytes we want that connected peers have */
@@ -2595,9 +2626,8 @@ tr_peerMgrTorrentStats (tr_torrent  * tor,
                         int         * setmePeersFrom)
 {
   int i;
-  int size;
+  int n;
   tr_swarm * s;
-  const tr_peer ** peers;
 
   assert (tr_isTorrent (tor));
 
@@ -2607,28 +2637,27 @@ tr_peerMgrTorrentStats (tr_torrent  * tor,
   *setmeWebseedsSendingToUs  = 0;
 
   s = tor->swarm;
-  size = tr_ptrArraySize (&s->peers);
-  peers = (const tr_peer **) tr_ptrArrayBase (&s->peers);
+  n = tr_ptrArraySize (&s->peers);
 
   for (i=0; i<TR_PEER_FROM__MAX; ++i)
     setmePeersFrom[i] = 0;
 
-  for (i=0; i<size; ++i)
+  for (i=0; i<n; ++i)
     {
-      const tr_peer * peer = peers[i];
+      tr_peer * peer = tr_ptrArrayNth (&s->peers, i);
+      tr_peerMsgs * msgs = PEER_MSGS (peer);
       const struct peer_atom * atom = peer->atom;
 
-      if (peer->io == NULL) /* not connected */
-        continue;
+      assert (msgs != NULL);
 
       ++*setmePeersConnected;
 
       ++setmePeersFrom[atom->fromFirst];
 
-      if (clientIsDownloadingFrom (tor, peer))
+      if (clientIsDownloadingFrom (tor, msgs))
         ++*setmePeersSendingToUs;
 
-      if (clientIsUploadingTo (peer))
+      if (clientIsUploadingTo (msgs))
         ++*setmePeersGettingFromUs;
     }
 
@@ -2639,26 +2668,24 @@ double*
 tr_peerMgrWebSpeeds_KBps (const tr_torrent * tor)
 {
   unsigned int i;
-  unsigned int webseedCount;
-  const tr_swarm * s;
-  const tr_webseed ** webseeds;
+  tr_swarm * s;
+  unsigned int n;
   double * ret = NULL;
   const uint64_t now = tr_time_msec ();
 
   assert (tr_isTorrent (tor));
 
   s = tor->swarm;
-  webseedCount = tr_ptrArraySize (&s->webseeds);
-  webseeds = (const tr_webseed**) tr_ptrArrayBase (&s->webseeds);
-  ret = tr_new0 (double, webseedCount);
+  n = tr_ptrArraySize (&s->webseeds);
+  ret = tr_new0 (double, n);
 
   assert (s->manager != NULL);
-  assert (webseedCount == tor->info.webseedCount);
+  assert (n == tor->info.webseedCount);
 
-  for (i=0; i<webseedCount; ++i)
+  for (i=0; i<n; ++i)
     {
-      unsigned int Bps;
-      if (tr_webseedGetSpeed_Bps (webseeds[i], now, &Bps))
+      unsigned int Bps = 0;
+      if (tr_peerIsTransferringPieces (tr_ptrArrayNth(&s->webseeds,i), now, TR_DOWN, &Bps))
         ret[i] = Bps / (double)tr_speed_K;
       else
         ret[i] = -1.0;
@@ -2667,12 +2694,6 @@ tr_peerMgrWebSpeeds_KBps (const tr_torrent * tor)
   return ret;
 }
 
-unsigned int
-tr_peerGetPieceSpeed_Bps (const tr_peer * peer, uint64_t now, tr_direction direction)
-{
-  return peer->io ? tr_peerIoGetPieceSpeed_Bps (peer->io, now, direction) : 0.0;
-}
-
 struct tr_peer_stat *
 tr_peerMgrPeerStats (const tr_torrent * tor, int * setmeCount)
 {
@@ -2680,7 +2701,7 @@ tr_peerMgrPeerStats (const tr_torrent * tor, int * setmeCount)
   int size = 0;
   tr_peer_stat * ret;
   const tr_swarm * s;
-  const tr_peer ** peers;
+  tr_peer ** peers;
   const time_t now = tr_time ();
   const uint64_t now_msec = tr_time_msec ();
 
@@ -2688,14 +2709,15 @@ tr_peerMgrPeerStats (const tr_torrent * tor, int * setmeCount)
   assert (tor->swarm->manager != NULL);
 
   s = tor->swarm;
-  peers = (const tr_peer**) tr_ptrArrayBase (&s->peers);
+  peers = (tr_peer**) tr_ptrArrayBase (&s->peers);
   size = tr_ptrArraySize (&s->peers);
   ret = tr_new0 (tr_peer_stat, size);
 
   for (i=0; i<size; ++i)
     {
       char *                   pch;
-      const tr_peer *          peer = peers[i];
+      tr_peer *                peer = peers[i];
+      tr_peerMsgs *            msgs = PEER_MSGS (peer);
       const struct peer_atom * atom = peer->atom;
       tr_peer_stat *           stat = ret + i;
 
@@ -2704,17 +2726,17 @@ tr_peerMgrPeerStats (const tr_torrent * tor, int * setmeCount)
       stat->port                = ntohs (peer->atom->port);
       stat->from                = atom->fromFirst;
       stat->progress            = peer->progress;
-      stat->isUTP               = peer->io->utp_socket != NULL;
-      stat->isEncrypted         = tr_peerIoIsEncrypted (peer->io) ? 1 : 0;
+      stat->isUTP               = tr_peerMsgsIsUtpConnection (msgs);
+      stat->isEncrypted         = tr_peerMsgsIsEncrypted (msgs);
       stat->rateToPeer_KBps     = toSpeedKBps (tr_peerGetPieceSpeed_Bps (peer, now_msec, TR_CLIENT_TO_PEER));
       stat->rateToClient_KBps   = toSpeedKBps (tr_peerGetPieceSpeed_Bps (peer, now_msec, TR_PEER_TO_CLIENT));
-      stat->peerIsChoked        = peer->peerIsChoked;
-      stat->peerIsInterested    = peer->peerIsInterested;
-      stat->clientIsChoked      = peer->clientIsChoked;
-      stat->clientIsInterested  = peer->clientIsInterested;
-      stat->isIncoming          = tr_peerIoIsIncoming (peer->io);
-      stat->isDownloadingFrom   = clientIsDownloadingFrom (tor, peer);
-      stat->isUploadingTo       = clientIsUploadingTo (peer);
+      stat->peerIsChoked        = tr_peerMsgsIsPeerChoked (msgs);
+      stat->peerIsInterested    = tr_peerMsgsIsPeerInterested (msgs);
+      stat->clientIsChoked      = tr_peerMsgsIsClientChoked (msgs);
+      stat->clientIsInterested  = tr_peerMsgsIsClientInterested (msgs);
+      stat->isIncoming          = tr_peerMsgsIsIncomingConnection (msgs);
+      stat->isDownloadingFrom   = clientIsDownloadingFrom (tor, msgs);
+      stat->isUploadingTo       = clientIsUploadingTo (msgs);
       stat->isSeed              = peerIsSeed (peer);
 
       stat->blocksToPeer        = tr_historyGet (&peer->blocksSentToPeer,    now, CANCEL_HISTORY_SEC);
@@ -2727,7 +2749,7 @@ tr_peerMgrPeerStats (const tr_torrent * tor, int * setmeCount)
 
       pch = stat->flagStr;
       if (stat->isUTP) *pch++ = 'T';
-      if (s->optimistic == peer) *pch++ = 'O';
+      if (s->optimistic == msgs) *pch++ = 'O';
       if (stat->isDownloadingFrom) *pch++ = 'D';
       else if (stat->clientIsInterested) *pch++ = 'd';
       if (stat->isUploadingTo) *pch++ = 'U';
@@ -2761,10 +2783,7 @@ tr_peerMgrClearInterest (tr_torrent * tor)
   assert (tr_torrentIsLocked (tor));
 
   for (i=0; i<peerCount; ++i)
-    {
-      const tr_peer * peer = tr_ptrArrayNth (&s->peers, i);
-      tr_peerMsgsSetInterested (peer->msgs, false);
-    }
+    tr_peerMsgsSetInterested (tr_ptrArrayNth (&s->peers, i), false);
 }
 
 /* does this peer have any pieces that we want? */
@@ -2920,7 +2939,7 @@ rechokeDownloads (tr_swarm * s)
 
           if (!isPeerInteresting (s->tor, piece_is_interesting, peer))
             {
-              tr_peerMsgsSetInterested (peer->msgs, false);
+              tr_peerMsgsSetInterested (PEER_MSGS(peer), false);
             }
           else
             {
@@ -2957,7 +2976,7 @@ rechokeDownloads (tr_swarm * s)
   qsort (rechoke, rechoke_count, sizeof (struct tr_rechoke_info), compare_rechoke_info);
   s->interestedCount = MIN (maxPeers, rechoke_count);
   for (i=0; i<rechoke_count; ++i)
-    tr_peerMsgsSetInterested (rechoke[i].peer->msgs, i<s->interestedCount);
+    tr_peerMsgsSetInterested (PEER_MSGS(rechoke[i].peer), i<s->interestedCount);
 
   /* cleanup */
   tr_free (rechoke);
@@ -2969,12 +2988,12 @@ rechokeDownloads (tr_swarm * s)
 
 struct ChokeData
 {
-  bool      isInterested;
-  bool      wasChoked;
-  bool      isChoked;
-  int       rate;
-  int       salt;
-  tr_peer * peer;
+  bool          isInterested;
+  bool          wasChoked;
+  bool          isChoked;
+  int           rate;
+  int           salt;
+  tr_peerMsgs * msgs;
 };
 
 static int
@@ -2996,10 +3015,10 @@ compareChoke (const void * va, const void * vb)
 }
 
 /* is this a new connection? */
-static int
-isNew (const tr_peer * peer)
+static bool
+isNew (const tr_peerMsgs * msgs)
 {
-  return peer && peer->io && tr_peerIoGetAge (peer->io) < 45;
+  return (msgs != NULL) && (tr_peerMsgsGetConnectionAge (msgs) < 45);
 }
 
 /* get a rate for deciding which peers to choke and unchoke. */
@@ -3065,22 +3084,24 @@ rechokeUploads (tr_swarm * s, const uint64_t now)
   for (i=0, size=0; i<peerCount; ++i)
     {
       tr_peer * peer = peers[i];
+      tr_peerMsgs * msgs = PEER_MSGS (peer);
+
       struct peer_atom * atom = peer->atom;
 
       if (peerIsSeed (peer)) /* choke seeds and partial seeds */
         {
-          tr_peerMsgsSetChoke (peer->msgs, true);
+          tr_peerMsgsSetChoke (PEER_MSGS(peer), true);
         }
       else if (chokeAll) /* choke everyone if we're not uploading */
         {
-          tr_peerMsgsSetChoke (peer->msgs, true);
+          tr_peerMsgsSetChoke (PEER_MSGS(peer), true);
         }
-      else if (peer != s->optimistic)
+      else if (msgs != s->optimistic)
         {
           struct ChokeData * n = &choke[size++];
-          n->peer         = peer;
-          n->isInterested = peer->peerIsInterested;
-          n->wasChoked    = peer->peerIsChoked;
+          n->msgs         = msgs;
+          n->isInterested = tr_peerMsgsIsPeerInterested (msgs);
+          n->wasChoked    = tr_peerMsgsIsPeerChoked (msgs);
           n->rate         = getRate (s->tor, atom, now);
           n->salt         = tr_cryptoWeakRandInt (INT_MAX);
           n->isChoked     = true;
@@ -3123,9 +3144,9 @@ rechokeUploads (tr_swarm * s, const uint64_t now)
         {
           if (choke[i].isInterested)
             {
-              const tr_peer * peer = choke[i].peer;
+              const tr_peerMsgs * msgs = choke[i].msgs;
               int x = 1, y;
-              if (isNew (peer)) x *= 3;
+              if (isNew (msgs)) x *= 3;
               for (y=0; y<x; ++y)
                 tr_ptrArrayAppend (&randPool, &choke[i]);
             }
@@ -3135,7 +3156,7 @@ rechokeUploads (tr_swarm * s, const uint64_t now)
         {
           c = tr_ptrArrayNth (&randPool, tr_cryptoWeakRandInt (n));
           c->isChoked = false;
-          s->optimistic = c->peer;
+          s->optimistic = c->msgs;
           s->optimisticUnchokeTimeScaler = OPTIMISTIC_UNCHOKE_MULTIPLIER;
         }
 
@@ -3143,7 +3164,7 @@ rechokeUploads (tr_swarm * s, const uint64_t now)
     }
 
   for (i=0; i<size; ++i)
-    tr_peerMsgsSetChoke (choke[i].peer->msgs, choke[i].isChoked);
+    tr_peerMsgsSetChoke (choke[i].msgs, choke[i].isChoked);
 
   /* cleanup */
   tr_free (choke);
@@ -3305,7 +3326,7 @@ removePeer (tr_swarm * s, tr_peer * peer)
     tr_decrReplicationFromBitfield (s, &peer->have);
 
   assert (removed == peer);
-  peerDelete (s, removed);
+  tr_peerFree (removed);
 }
 
 static void
@@ -3332,7 +3353,7 @@ closePeer (tr_swarm * s, tr_peer * peer)
       tordbg (s, "incremented atom %s numFails to %d", tr_atomAddrStr (atom), (int)atom->numFails);
     }
 
-  tordbg (s, "removing bad peer %s", tr_peerIoGetAddrStr (peer->io));
+  tordbg (s, "removing bad peer %s", tr_atomAddrStr (peer->atom));
   removePeer (s, peer);
 }
 
@@ -3554,10 +3575,7 @@ pumpAllPeers (tr_peerMgr * mgr)
       tr_swarm * s = tor->swarm;
 
       for (j=0; j<tr_ptrArraySize (&s->peers); ++j)
-        {
-          tr_peer * peer = tr_ptrArrayNth (&s->peers, j);
-          tr_peerMsgsPulse (peer->msgs);
-        }
+        tr_peerMsgsPulse (tr_ptrArrayNth (&s->peers, j));
     }
 }
 
index 85aa67ab7b8b551bdb00238d29aafd010375b157..ca65948e1f12f5ed68cb255298cd8ee3b02d7ed3 100644 (file)
@@ -65,140 +65,134 @@ typedef struct tr_pex
 }
 tr_pex;
 
-
-struct tr_peerIo;
-struct tr_peermsgs;
-
-/* opaque forward declaration */
 struct peer_atom;
-
-void tr_peerConstruct (struct tr_peer * peer);
-
-void tr_peerDestruct (tr_torrent * tor, struct tr_peer * peer);
-
+struct tr_peerIo;
+struct tr_peerMsgs;
+struct tr_swarm;
 
 static inline bool
 tr_isPex (const tr_pex * pex)
 {
-    return pex && tr_address_is_valid (&pex->addr);
+  return pex && tr_address_is_valid (&pex->addr);
 }
 
 const tr_address * tr_peerAddress (const tr_peer *);
 
 int tr_pexCompare (const void * a, const void * b);
 
-tr_peerMgr* tr_peerMgrNew (tr_session *);
+tr_peerMgr * tr_peerMgrNew                  (tr_session          * session);
 
-void tr_peerMgrFree (tr_peerMgr * manager);
+void         tr_peerMgrFree                 (tr_peerMgr          * manager);
 
-bool tr_peerMgrPeerIsSeed (const tr_torrent * tor,
-                           const tr_address * addr);
+bool         tr_peerMgrPeerIsSeed           (const tr_torrent    * tor,
+                                             const tr_address    * addr);
 
-void tr_peerMgrSetUtpSupported (tr_torrent       * tor,
-                                const tr_address * addr);
+void         tr_peerMgrSetUtpSupported      (tr_torrent          * tor,
+                                             const tr_address    * addr);
 
-void tr_peerMgrSetUtpFailed (tr_torrent *tor,
-                             const tr_address *addr,
-                             bool failed);
+void         tr_peerMgrSetUtpFailed         (tr_torrent          * tor,
+                                             const tr_address    * addr,
+                                             bool                  failed);
 
-void tr_peerMgrGetNextRequests (tr_torrent          * torrent,
-                                tr_peer             * peer,
-                                int                   numwant,
-                                tr_block_index_t    * setme,
-                                int                 * numgot,
-                                bool                  get_intervals);
+void         tr_peerMgrGetNextRequests      (tr_torrent          * torrent,
+                                             tr_peer             * peer,
+                                             int                   numwant,
+                                             tr_block_index_t    * setme,
+                                             int                 * numgot,
+                                             bool                  get_intervals);
 
-bool tr_peerMgrDidPeerRequest (const tr_torrent  * torrent,
-                               const tr_peer     * peer,
-                               tr_block_index_t    block);
+bool         tr_peerMgrDidPeerRequest       (const tr_torrent    * torrent,
+                                             const tr_peer       * peer,
+                                             tr_block_index_t      block);
 
-void tr_peerMgrRebuildRequests (tr_torrent * torrent);
+void         tr_peerMgrRebuildRequests      (tr_torrent          * torrent);
 
-void tr_peerMgrAddIncoming (tr_peerMgr  * manager,
-                            tr_address  * addr,
-                            tr_port       port,
-                            int           socket,
-                            struct UTPSocket *utp_socket);
+void         tr_peerMgrAddIncoming          (tr_peerMgr          * manager,
+                                             tr_address          * addr,
+                                             tr_port               port,
+                                             int                   socket,
+                                             struct UTPSocket    * utp_socket);
 
-tr_pex * tr_peerMgrCompactToPex (const void    * compact,
-                                 size_t          compactLen,
-                                 const uint8_t * added_f,
-                                 size_t          added_f_len,
-                                 size_t        * setme_pex_count);
+tr_pex *     tr_peerMgrCompactToPex         (const void          * compact,
+                                             size_t                compactLen,
+                                             const uint8_t       * added_f,
+                                             size_t                added_f_len,
+                                             size_t              * setme_pex_count);
 
-tr_pex * tr_peerMgrCompact6ToPex (const void    * compact,
-                                  size_t          compactLen,
-                                  const uint8_t * added_f,
-                                  size_t          added_f_len,
-                                  size_t        * pexCount);
+tr_pex *     tr_peerMgrCompact6ToPex        (const void          * compact,
+                                             size_t                compactLen,
+                                             const uint8_t       * added_f,
+                                             size_t                added_f_len,
+                                             size_t              * pexCount);
 
-tr_pex * tr_peerMgrArrayToPex (const void * array,
-                               size_t       arrayLen,
-                               size_t      * setme_pex_count);
+tr_pex *     tr_peerMgrArrayToPex           (const void          * array,
+                                             size_t                arrayLen,
+                                             size_t              * setme_pex_count);
 
 /**
  * @param seedProbability [0..100] for likelihood that the peer is a seed; -1 for unknown
  */
-void tr_peerMgrAddPex (tr_torrent     * tor,
-                       uint8_t          from,
-                       const tr_pex   * pex,
-                       int8_t           seedProbability);
+void         tr_peerMgrAddPex               (tr_torrent          * tor,
+                                             uint8_t               from,
+                                             const tr_pex        * pex,
+                                             int8_t                seedProbability);
 
-void tr_peerMgrMarkAllAsSeeds (tr_torrent * tor);
+void         tr_peerMgrMarkAllAsSeeds       (tr_torrent          * tor);
 
 enum
 {
-    TR_PEERS_CONNECTED,
-    TR_PEERS_INTERESTING
+  TR_PEERS_CONNECTED,
+  TR_PEERS_INTERESTING
 };
 
-int  tr_peerMgrGetPeers (tr_torrent      * tor,
-                         tr_pex         ** setme_pex,
-                         uint8_t           address_type,
-                         uint8_t           peer_list_mode,
-                         int               max_peer_count);
-
-void tr_peerMgrStartTorrent (tr_torrent * tor);
+int          tr_peerMgrGetPeers             (tr_torrent          * tor,
+                                             tr_pex             ** setme_pex,
+                                             uint8_t               address_type,
+                                             uint8_t               peer_list_mode,
+                                             int                   max_peer_count);
 
-void tr_peerMgrStopTorrent (tr_torrent * tor);
+void         tr_peerMgrStartTorrent         (tr_torrent          * tor);
 
-void tr_peerMgrAddTorrent (tr_peerMgr         * manager,
-                           struct tr_torrent  * tor);
+void         tr_peerMgrStopTorrent          (tr_torrent          * tor);
 
-void tr_peerMgrRemoveTorrent (tr_torrent * tor);
+void         tr_peerMgrAddTorrent           (tr_peerMgr          * manager,
+                                             struct tr_torrent   * tor);
 
-void tr_peerMgrTorrentAvailability (const tr_torrent   * tor,
-                                    int8_t             * tab,
-                                    unsigned int         tabCount);
+void         tr_peerMgrRemoveTorrent        (tr_torrent          * tor);
 
-uint64_t tr_peerMgrGetDesiredAvailable (const tr_torrent * tor);
+void         tr_peerMgrTorrentAvailability  (const tr_torrent    * tor,
+                                             int8_t              * tab,
+                                             unsigned int          tabCount);
 
-void tr_peerMgrOnTorrentGotMetainfo (tr_torrent * tor);
+uint64_t     tr_peerMgrGetDesiredAvailable  (const tr_torrent    * tor);
 
-void tr_peerMgrOnBlocklistChanged (tr_peerMgr * manager);
+void         tr_peerMgrOnTorrentGotMetainfo (tr_torrent         * tor);
 
-void tr_peerMgrTorrentStats (tr_torrent * tor,
-                             int * setmePeersConnected,
-                             int * setmeWebseedsSendingToUs,
-                             int * setmePeersSendingToUs,
-                             int * setmePeersGettingFromUs,
-                             int * setmePeersFrom); /* TR_PEER_FROM__MAX */
+void         tr_peerMgrOnBlocklistChanged   (tr_peerMgr         * manager);
 
-struct tr_peer_stat* tr_peerMgrPeerStats (const tr_torrent * tor,
-                                          int              * setmeCount);
+void         tr_peerMgrTorrentStats         (tr_torrent         * tor,
+                                             int                * setmePeersConnected,
+                                             int                * setmeWebseedsSendingToUs,
+                                             int                * setmePeersSendingToUs,
+                                             int                * setmePeersGettingFromUs,
+                                             int                * setmePeersFrom); /* TR_PEER_FROM__MAX */
 
-double* tr_peerMgrWebSpeeds_KBps (const tr_torrent * tor);
+struct tr_peer_stat * tr_peerMgrPeerStats   (const tr_torrent   * tor,
+                                             int                * setmeCount);
 
+double *     tr_peerMgrWebSpeeds_KBps       (const tr_torrent   * tor);
 
-unsigned int tr_peerGetPieceSpeed_Bps (const tr_peer    * peer,
-                                       uint64_t           now,
-                                       tr_direction       direction);
+unsigned int tr_peerGetPieceSpeed_Bps       (const tr_peer      * peer,
+                                             uint64_t             now,
+                                             tr_direction         direction);
 
-void tr_peerMgrClearInterest (tr_torrent * tor);
+void         tr_peerMgrClearInterest        (tr_torrent         * tor);
 
-void tr_peerMgrGotBadPiece (tr_torrent * tor, tr_piece_index_t pieceIndex);
+void         tr_peerMgrGotBadPiece          (tr_torrent         * tor,
+                                             tr_piece_index_t     pieceIndex);
 
-void tr_peerMgrPieceCompleted (tr_torrent * tor, tr_piece_index_t pieceIndex);
+void         tr_peerMgrPieceCompleted       (tr_torrent         * tor,
+                                             tr_piece_index_t     pieceIndex);
  
 
 
index fcef213e69f6f1028cd8216d77d0596ab6eab4f7..8b150b32c0ddd01f8d8ce70e299130df55d05357 100644 (file)
 
 enum
 {
-    BT_CHOKE                = 0,
-    BT_UNCHOKE              = 1,
-    BT_INTERESTED           = 2,
-    BT_NOT_INTERESTED       = 3,
-    BT_HAVE                 = 4,
-    BT_BITFIELD             = 5,
-    BT_REQUEST              = 6,
-    BT_PIECE                = 7,
-    BT_CANCEL               = 8,
-    BT_PORT                 = 9,
+  BT_CHOKE                = 0,
+  BT_UNCHOKE              = 1,
+  BT_INTERESTED           = 2,
+  BT_NOT_INTERESTED       = 3,
+  BT_HAVE                 = 4,
+  BT_BITFIELD             = 5,
+  BT_REQUEST              = 6,
+  BT_PIECE                = 7,
+  BT_CANCEL               = 8,
+  BT_PORT                 = 9,
 
-    BT_FEXT_SUGGEST         = 13,
-    BT_FEXT_HAVE_ALL        = 14,
-    BT_FEXT_HAVE_NONE       = 15,
-    BT_FEXT_REJECT          = 16,
-    BT_FEXT_ALLOWED_FAST    = 17,
+  BT_FEXT_SUGGEST         = 13,
+  BT_FEXT_HAVE_ALL        = 14,
+  BT_FEXT_HAVE_NONE       = 15,
+  BT_FEXT_REJECT          = 16,
+  BT_FEXT_ALLOWED_FAST    = 17,
 
-    BT_LTEP                 = 20,
+  BT_LTEP                 = 20,
 
-    LTEP_HANDSHAKE          = 0,
+  LTEP_HANDSHAKE          = 0,
 
-    UT_PEX_ID               = 1,
-    UT_METADATA_ID          = 3,
+  UT_PEX_ID               = 1,
+  UT_METADATA_ID          = 3,
 
-    MAX_PEX_PEER_COUNT      = 50,
+  MAX_PEX_PEER_COUNT      = 50,
 
-    MIN_CHOKE_PERIOD_SEC    = 10,
+  MIN_CHOKE_PERIOD_SEC    = 10,
 
-    /* idle seconds before we send a keepalive */
-    KEEPALIVE_INTERVAL_SECS = 100,
+  /* idle seconds before we send a keepalive */
+  KEEPALIVE_INTERVAL_SECS = 100,
 
-    PEX_INTERVAL_SECS       = 90, /* sec between sendPex () calls */
+  PEX_INTERVAL_SECS       = 90, /* sec between sendPex () calls */
 
-    REQQ                    = 512,
+  REQQ                    = 512,
 
-    METADATA_REQQ           = 64,
+  METADATA_REQQ           = 64,
 
-    /* used in lowering the outMessages queue period */
-    IMMEDIATE_PRIORITY_INTERVAL_SECS = 0,
-    HIGH_PRIORITY_INTERVAL_SECS = 2,
-    LOW_PRIORITY_INTERVAL_SECS = 10,
+  MAGIC_NUMBER            = 21549,
 
-    /* number of pieces we'll allow in our fast set */
-    MAX_FAST_SET_SIZE = 3,
+  /* used in lowering the outMessages queue period */
+  IMMEDIATE_PRIORITY_INTERVAL_SECS = 0,
+  HIGH_PRIORITY_INTERVAL_SECS = 2,
+  LOW_PRIORITY_INTERVAL_SECS = 10,
 
-    /* how many blocks to keep prefetched per peer */
-    PREFETCH_SIZE = 18,
+  /* number of pieces we'll allow in our fast set */
+  MAX_FAST_SET_SIZE = 3,
 
-    /* when we're making requests from another peer,
-       batch them together to send enough requests to
-       meet our bandwidth goals for the next N seconds */
-    REQUEST_BUF_SECS = 10,
+  /* how many blocks to keep prefetched per peer */
+  PREFETCH_SIZE = 18,
 
-    /* defined in BEP #9 */
-    METADATA_MSG_TYPE_REQUEST = 0,
-    METADATA_MSG_TYPE_DATA = 1,
-    METADATA_MSG_TYPE_REJECT = 2
+  /* when we're making requests from another peer,
+     batch them together to send enough requests to
+     meet our bandwidth goals for the next N seconds */
+  REQUEST_BUF_SECS = 10,
+
+  /* defined in BEP #9 */
+  METADATA_MSG_TYPE_REQUEST = 0,
+  METADATA_MSG_TYPE_DATA = 1,
+  METADATA_MSG_TYPE_REJECT = 2
 };
 
 enum
 {
-    AWAITING_BT_LENGTH,
-    AWAITING_BT_ID,
-    AWAITING_BT_MESSAGE,
-    AWAITING_BT_PIECE
+  AWAITING_BT_LENGTH,
+  AWAITING_BT_ID,
+  AWAITING_BT_MESSAGE,
+  AWAITING_BT_PIECE
 };
 
 typedef enum
@@ -117,17 +119,15 @@ typedef enum
 }
 encryption_preference_t;
 
-
-
 /**
 ***
 **/
 
 struct peer_request
 {
-    uint32_t    index;
-    uint32_t    offset;
-    uint32_t    length;
+  uint32_t index;
+  uint32_t offset;
+  uint32_t length;
 };
 
 static void
@@ -135,9 +135,9 @@ blockToReq (const tr_torrent     * tor,
             tr_block_index_t       block,
             struct peer_request  * setme)
 {
-    tr_torrentGetBlockLocation (tor, block, &setme->index,
-                                            &setme->offset,
-                                            &setme->length);
+  tr_torrentGetBlockLocation (tor, block, &setme->index,
+                                          &setme->offset,
+                                          &setme->length);
 }
 
 /**
@@ -148,10 +148,10 @@ blockToReq (const tr_torrent     * tor,
  * the current message that it's sending us. */
 struct tr_incoming
 {
-    uint8_t                id;
-    uint32_t               length; /* includes the +1 for id length */
-    struct peer_request    blockReq; /* metadata for incoming blocks */
-    struct evbuffer *      block; /* piece data for incoming blocks */
+  uint8_t                id;
+  uint32_t               length; /* includes the +1 for id length */
+  struct peer_request    blockReq; /* metadata for incoming blocks */
+  struct evbuffer      * block; /* piece data for incoming blocks */
 };
 
 /**
@@ -168,71 +168,90 @@ struct tr_incoming
  * @see struct peer_atom
  * @see tr_peer
  */
-struct tr_peermsgs
+struct tr_peerMsgs
 {
-    bool            peerSupportsPex;
-    bool            peerSupportsMetadataXfer;
-    bool            clientSentLtepHandshake;
-    bool            peerSentLtepHandshake;
+  struct tr_peer peer; /* parent */
+
+  uint16_t magic_number;
+
+  /* Whether or not we've choked this peer. */
+  bool peer_is_choked;
+
+  /* whether or not the peer has indicated it will download from us. */
+  bool peer_is_interested;
+
+  /* whether or the peer is choking us. */
+  bool client_is_choked;
+
+  /* whether or not we've indicated to the peer that we would download from them if unchoked. */
+  bool client_is_interested;
 
-    /*bool          haveFastSet;*/
 
-    int             desiredRequestCount;
+  bool peerSupportsPex;
+  bool peerSupportsMetadataXfer;
+  bool clientSentLtepHandshake;
+  bool peerSentLtepHandshake;
 
-    int             prefetchCount;
+  /*bool haveFastSet;*/
 
-    /* how long the outMessages batch should be allowed to grow before
-     * it's flushed -- some messages (like requests >:) should be sent
-     * very quickly; others aren't as urgent. */
-    int8_t          outMessagesBatchPeriod;
+  int desiredRequestCount;
 
-    uint8_t         state;
-    uint8_t         ut_pex_id;
-    uint8_t         ut_metadata_id;
-    uint16_t        pexCount;
-    uint16_t        pexCount6;
+  int prefetchCount;
 
-    tr_port         dht_port;
+  /* how long the outMessages batch should be allowed to grow before
+   * it's flushed -- some messages (like requests >:) should be sent
+   * very quickly; others aren't as urgent. */
+  int8_t          outMessagesBatchPeriod;
 
-    encryption_preference_t  encryption_preference;
+  uint8_t         state;
+  uint8_t         ut_pex_id;
+  uint8_t         ut_metadata_id;
+  uint16_t        pexCount;
+  uint16_t        pexCount6;
 
-    size_t                   metadata_size_hint;
+  tr_port         dht_port;
+
+  encryption_preference_t  encryption_preference;
+
+  size_t                   metadata_size_hint;
 #if 0
-    size_t                 fastsetSize;
-    tr_piece_index_t       fastset[MAX_FAST_SET_SIZE];
+  size_t                 fastsetSize;
+  tr_piece_index_t       fastset[MAX_FAST_SET_SIZE];
 #endif
 
-    tr_peer *              peer;
+  tr_torrent *           torrent;
 
-    tr_torrent *           torrent;
+  tr_peer_callback      * callback;
+  void                  * callbackData;
 
-    tr_peer_callback      * callback;
-    void                  * callbackData;
+  struct evbuffer *      outMessages; /* all the non-piece messages */
 
-    struct evbuffer *      outMessages; /* all the non-piece messages */
+  struct peer_request    peerAskedFor[REQQ];
 
-    struct peer_request    peerAskedFor[REQQ];
+  int peerAskedForMetadata[METADATA_REQQ];
+  int peerAskedForMetadataCount;
 
-    int                    peerAskedForMetadata[METADATA_REQQ];
-    int                    peerAskedForMetadataCount;
+  tr_pex * pex;
+  tr_pex * pex6;
 
-    tr_pex               * pex;
-    tr_pex               * pex6;
+  /*time_t clientSentPexAt;*/
+  time_t clientSentAnythingAt;
 
-    /*time_t                 clientSentPexAt;*/
-    time_t                 clientSentAnythingAt;
+  time_t chokeChangedAt;
 
-    /* when we started batching the outMessages */
-    time_t                outMessagesBatchedAt;
+  /* when we started batching the outMessages */
+  time_t outMessagesBatchedAt;
 
-    struct tr_incoming    incoming;
+  struct tr_incoming    incoming;
 
-    /* if the peer supports the Extension Protocol in BEP 10 and
-       supplied a reqq argument, it's stored here. Otherwise, the
-       value is zero and should be ignored. */
-    int64_t               reqq;
+  /* if the peer supports the Extension Protocol in BEP 10 and
+     supplied a reqq argument, it's stored here. Otherwise, the
+     value is zero and should be ignored. */
+  int64_t reqq;
 
-    struct event        * pexTimer;
+  struct event * pexTimer;
+
+  struct tr_peerIo * io;
 };
 
 /**
@@ -240,9 +259,9 @@ struct tr_peermsgs
 **/
 
 static inline tr_session*
-getSession (struct tr_peermsgs * msgs)
+getSession (struct tr_peerMsgs * msgs)
 {
-    return msgs->torrent->session;
+  return msgs->torrent->session;
 }
 
 /**
@@ -251,34 +270,34 @@ getSession (struct tr_peermsgs * msgs)
 
 static void
 myDebug (const char * file, int line,
-         const struct tr_peermsgs * msgs,
+         const struct tr_peerMsgs * msgs,
          const char * fmt, ...)
 {
-    FILE * fp = tr_logGetFile ();
+  FILE * fp = tr_logGetFile ();
 
-    if (fp)
+  if (fp)
     {
-        va_list           args;
-        char              timestr[64];
-        struct evbuffer * buf = evbuffer_new ();
-        char *            base = tr_basename (file);
-        char *            message;
-
-        evbuffer_add_printf (buf, "[%s] %s - %s [%s]: ",
-                             tr_logGetTimeStr (timestr, sizeof (timestr)),
-                             tr_torrentName (msgs->torrent),
-                             tr_peerIoGetAddrStr (msgs->peer->io),
-                             tr_quark_get_string (msgs->peer->client, NULL));
-        va_start (args, fmt);
-        evbuffer_add_vprintf (buf, fmt, args);
-        va_end (args);
-        evbuffer_add_printf (buf, " (%s:%d)\n", base, line);
-
-        message = evbuffer_free_to_str (buf);
-        fputs (message, fp);
-
-        tr_free (base);
-        tr_free (message);
+      va_list           args;
+      char              timestr[64];
+      struct evbuffer * buf = evbuffer_new ();
+      char *            base = tr_basename (file);
+      char *            message;
+
+      evbuffer_add_printf (buf, "[%s] %s - %s [%s]: ",
+                           tr_logGetTimeStr (timestr, sizeof (timestr)),
+                           tr_torrentName (msgs->torrent),
+                           tr_peerIoGetAddrStr (msgs->io),
+                           tr_quark_get_string (msgs->peer.client, NULL));
+      va_start (args, fmt);
+      evbuffer_add_vprintf (buf, fmt, args);
+      va_end (args);
+      evbuffer_add_printf (buf, " (%s:%d)\n", base, line);
+
+      message = evbuffer_free_to_str (buf);
+      fputs (message, fp);
+
+      tr_free (base);
+      tr_free (message);
     }
 }
 
@@ -295,154 +314,154 @@ myDebug (const char * file, int line,
 **/
 
 static void
-pokeBatchPeriod (tr_peermsgs * msgs, int interval)
+pokeBatchPeriod (tr_peerMsgs * msgs, int interval)
 {
-    if (msgs->outMessagesBatchPeriod > interval)
+  if (msgs->outMessagesBatchPeriod > interval)
     {
-        msgs->outMessagesBatchPeriod = interval;
-        dbgmsg (msgs, "lowering batch interval to %d seconds", interval);
+      msgs->outMessagesBatchPeriod = interval;
+      dbgmsg (msgs, "lowering batch interval to %d seconds", interval);
     }
 }
 
 static void
-dbgOutMessageLen (tr_peermsgs * msgs)
+dbgOutMessageLen (tr_peerMsgs * msgs)
 {
-    dbgmsg (msgs, "outMessage size is now %zu", evbuffer_get_length (msgs->outMessages));
+  dbgmsg (msgs, "outMessage size is now %zu", evbuffer_get_length (msgs->outMessages));
 }
 
 static void
-protocolSendReject (tr_peermsgs * msgs, const struct peer_request * req)
+protocolSendReject (tr_peerMsgs * msgs, const struct peer_request * req)
 {
-    struct evbuffer * out = msgs->outMessages;
+  struct evbuffer * out = msgs->outMessages;
 
-    assert (tr_peerIoSupportsFEXT (msgs->peer->io));
+  assert (tr_peerIoSupportsFEXT (msgs->io));
 
-    evbuffer_add_uint32 (out, sizeof (uint8_t) + 3 * sizeof (uint32_t));
-    evbuffer_add_uint8 (out, BT_FEXT_REJECT);
-    evbuffer_add_uint32 (out, req->index);
-    evbuffer_add_uint32 (out, req->offset);
-    evbuffer_add_uint32 (out, req->length);
+  evbuffer_add_uint32 (out, sizeof (uint8_t) + 3 * sizeof (uint32_t));
+  evbuffer_add_uint8 (out, BT_FEXT_REJECT);
+  evbuffer_add_uint32 (out, req->index);
+  evbuffer_add_uint32 (out, req->offset);
+  evbuffer_add_uint32 (out, req->length);
 
-    dbgmsg (msgs, "rejecting %u:%u->%u...", req->index, req->offset, req->length);
-    dbgOutMessageLen (msgs);
+  dbgmsg (msgs, "rejecting %u:%u->%u...", req->index, req->offset, req->length);
+  dbgOutMessageLen (msgs);
 }
 
 static void
-protocolSendRequest (tr_peermsgs * msgs, const struct peer_request * req)
+protocolSendRequest (tr_peerMsgs * msgs, const struct peer_request * req)
 {
-    struct evbuffer * out = msgs->outMessages;
+  struct evbuffer * out = msgs->outMessages;
 
-    evbuffer_add_uint32 (out, sizeof (uint8_t) + 3 * sizeof (uint32_t));
-    evbuffer_add_uint8 (out, BT_REQUEST);
-    evbuffer_add_uint32 (out, req->index);
-    evbuffer_add_uint32 (out, req->offset);
-    evbuffer_add_uint32 (out, req->length);
+  evbuffer_add_uint32 (out, sizeof (uint8_t) + 3 * sizeof (uint32_t));
+  evbuffer_add_uint8 (out, BT_REQUEST);
+  evbuffer_add_uint32 (out, req->index);
+  evbuffer_add_uint32 (out, req->offset);
+  evbuffer_add_uint32 (out, req->length);
 
-    dbgmsg (msgs, "requesting %u:%u->%u...", req->index, req->offset, req->length);
-    dbgOutMessageLen (msgs);
-    pokeBatchPeriod (msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS);
+  dbgmsg (msgs, "requesting %u:%u->%u...", req->index, req->offset, req->length);
+  dbgOutMessageLen (msgs);
+  pokeBatchPeriod (msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS);
 }
 
 static void
-protocolSendCancel (tr_peermsgs * msgs, const struct peer_request * req)
+protocolSendCancel (tr_peerMsgs * msgs, const struct peer_request * req)
 {
-    struct evbuffer * out = msgs->outMessages;
+  struct evbuffer * out = msgs->outMessages;
 
-    evbuffer_add_uint32 (out, sizeof (uint8_t) + 3 * sizeof (uint32_t));
-    evbuffer_add_uint8 (out, BT_CANCEL);
-    evbuffer_add_uint32 (out, req->index);
-    evbuffer_add_uint32 (out, req->offset);
-    evbuffer_add_uint32 (out, req->length);
+  evbuffer_add_uint32 (out, sizeof (uint8_t) + 3 * sizeof (uint32_t));
+  evbuffer_add_uint8 (out, BT_CANCEL);
+  evbuffer_add_uint32 (out, req->index);
+  evbuffer_add_uint32 (out, req->offset);
+  evbuffer_add_uint32 (out, req->length);
 
-    dbgmsg (msgs, "cancelling %u:%u->%u...", req->index, req->offset, req->length);
-    dbgOutMessageLen (msgs);
-    pokeBatchPeriod (msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS);
+  dbgmsg (msgs, "cancelling %u:%u->%u...", req->index, req->offset, req->length);
+  dbgOutMessageLen (msgs);
+  pokeBatchPeriod (msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS);
 }
 
 static void
-protocolSendPort (tr_peermsgs *msgs, uint16_t port)
+protocolSendPort (tr_peerMsgs *msgs, uint16_t port)
 {
-    struct evbuffer * out = msgs->outMessages;
+  struct evbuffer * out = msgs->outMessages;
 
-    dbgmsg (msgs, "sending Port %u", port);
-    evbuffer_add_uint32 (out, 3);
-    evbuffer_add_uint8 (out, BT_PORT);
-    evbuffer_add_uint16 (out, port);
+  dbgmsg (msgs, "sending Port %u", port);
+  evbuffer_add_uint32 (out, 3);
+  evbuffer_add_uint8 (out, BT_PORT);
+  evbuffer_add_uint16 (out, port);
 }
 
 static void
-protocolSendHave (tr_peermsgs * msgs, uint32_t index)
+protocolSendHave (tr_peerMsgs * msgs, uint32_t index)
 {
-    struct evbuffer * out = msgs->outMessages;
+  struct evbuffer * out = msgs->outMessages;
 
-    evbuffer_add_uint32 (out, sizeof (uint8_t) + sizeof (uint32_t));
-    evbuffer_add_uint8 (out, BT_HAVE);
-    evbuffer_add_uint32 (out, index);
+  evbuffer_add_uint32 (out, sizeof (uint8_t) + sizeof (uint32_t));
+  evbuffer_add_uint8 (out, BT_HAVE);
+  evbuffer_add_uint32 (out, index);
 
-    dbgmsg (msgs, "sending Have %u", index);
-    dbgOutMessageLen (msgs);
-    pokeBatchPeriod (msgs, LOW_PRIORITY_INTERVAL_SECS);
+  dbgmsg (msgs, "sending Have %u", index);
+  dbgOutMessageLen (msgs);
+  pokeBatchPeriod (msgs, LOW_PRIORITY_INTERVAL_SECS);
 }
 
 #if 0
 static void
-protocolSendAllowedFast (tr_peermsgs * msgs, uint32_t pieceIndex)
+protocolSendAllowedFast (tr_peerMsgs * msgs, uint32_t pieceIndex)
 {
-    tr_peerIo       * io  = msgs->peer->io;
-    struct evbuffer * out = msgs->outMessages;
+  tr_peerIo       * io  = msgs->io;
+  struct evbuffer * out = msgs->outMessages;
 
-    assert (tr_peerIoSupportsFEXT (msgs->peer->io));
+  assert (tr_peerIoSupportsFEXT (msgs->io));
 
-    evbuffer_add_uint32 (io, out, sizeof (uint8_t) + sizeof (uint32_t));
-    evbuffer_add_uint8 (io, out, BT_FEXT_ALLOWED_FAST);
-    evbuffer_add_uint32 (io, out, pieceIndex);
+  evbuffer_add_uint32 (io, out, sizeof (uint8_t) + sizeof (uint32_t));
+  evbuffer_add_uint8 (io, out, BT_FEXT_ALLOWED_FAST);
+  evbuffer_add_uint32 (io, out, pieceIndex);
 
-    dbgmsg (msgs, "sending Allowed Fast %u...", pieceIndex);
-    dbgOutMessageLen (msgs);
+  dbgmsg (msgs, "sending Allowed Fast %u...", pieceIndex);
+  dbgOutMessageLen (msgs);
 }
 #endif
 
 static void
-protocolSendChoke (tr_peermsgs * msgs, int choke)
+protocolSendChoke (tr_peerMsgs * msgs, int choke)
 {
-    struct evbuffer * out = msgs->outMessages;
+  struct evbuffer * out = msgs->outMessages;
 
-    evbuffer_add_uint32 (out, sizeof (uint8_t));
-    evbuffer_add_uint8 (out, choke ? BT_CHOKE : BT_UNCHOKE);
+  evbuffer_add_uint32 (out, sizeof (uint8_t));
+  evbuffer_add_uint8 (out, choke ? BT_CHOKE : BT_UNCHOKE);
 
-    dbgmsg (msgs, "sending %s...", choke ? "Choke" : "Unchoke");
-    dbgOutMessageLen (msgs);
-    pokeBatchPeriod (msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS);
+  dbgmsg (msgs, "sending %s...", choke ? "Choke" : "Unchoke");
+  dbgOutMessageLen (msgs);
+  pokeBatchPeriod (msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS);
 }
 
 static void
-protocolSendHaveAll (tr_peermsgs * msgs)
+protocolSendHaveAll (tr_peerMsgs * msgs)
 {
-    struct evbuffer * out = msgs->outMessages;
+  struct evbuffer * out = msgs->outMessages;
 
-    assert (tr_peerIoSupportsFEXT (msgs->peer->io));
+  assert (tr_peerIoSupportsFEXT (msgs->io));
 
-    evbuffer_add_uint32 (out, sizeof (uint8_t));
-    evbuffer_add_uint8 (out, BT_FEXT_HAVE_ALL);
+  evbuffer_add_uint32 (out, sizeof (uint8_t));
+  evbuffer_add_uint8 (out, BT_FEXT_HAVE_ALL);
 
-    dbgmsg (msgs, "sending HAVE_ALL...");
-    dbgOutMessageLen (msgs);
-    pokeBatchPeriod (msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS);
+  dbgmsg (msgs, "sending HAVE_ALL...");
+  dbgOutMessageLen (msgs);
+  pokeBatchPeriod (msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS);
 }
 
 static void
-protocolSendHaveNone (tr_peermsgs * msgs)
+protocolSendHaveNone (tr_peerMsgs * msgs)
 {
-    struct evbuffer * out = msgs->outMessages;
+  struct evbuffer * out = msgs->outMessages;
 
-    assert (tr_peerIoSupportsFEXT (msgs->peer->io));
+  assert (tr_peerIoSupportsFEXT (msgs->io));
 
-    evbuffer_add_uint32 (out, sizeof (uint8_t));
-    evbuffer_add_uint8 (out, BT_FEXT_HAVE_NONE);
+  evbuffer_add_uint32 (out, sizeof (uint8_t));
+  evbuffer_add_uint8 (out, BT_FEXT_HAVE_NONE);
 
-    dbgmsg (msgs, "sending HAVE_NONE...");
-    dbgOutMessageLen (msgs);
-    pokeBatchPeriod (msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS);
+  dbgmsg (msgs, "sending HAVE_NONE...");
+  dbgOutMessageLen (msgs);
+  pokeBatchPeriod (msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS);
 }
 
 /**
@@ -450,131 +469,128 @@ protocolSendHaveNone (tr_peermsgs * msgs)
 **/
 
 static void
-publish (tr_peermsgs * msgs, tr_peer_event * e)
+publish (tr_peerMsgs * msgs, tr_peer_event * e)
 {
-    assert (msgs->peer);
-    assert (msgs->peer->msgs == msgs);
-
-    if (msgs->callback != NULL)
-        msgs->callback (msgs->peer, e, msgs->callbackData);
+  if (msgs->callback != NULL)
+    msgs->callback (&msgs->peer, e, msgs->callbackData);
 }
 
 static void
-fireError (tr_peermsgs * msgs, int err)
+fireError (tr_peerMsgs * msgs, int err)
 {
-    tr_peer_event e = TR_PEER_EVENT_INIT;
-    e.eventType = TR_PEER_ERROR;
-    e.err = err;
-    publish (msgs, &e);
+  tr_peer_event e = TR_PEER_EVENT_INIT;
+  e.eventType = TR_PEER_ERROR;
+  e.err = err;
+  publish (msgs, &e);
 }
 
 static void
-fireGotBlock (tr_peermsgs * msgs, const struct peer_request * req)
+fireGotBlock (tr_peerMsgs * msgs, const struct peer_request * req)
 {
-    tr_peer_event e = TR_PEER_EVENT_INIT;
-    e.eventType = TR_PEER_CLIENT_GOT_BLOCK;
-    e.pieceIndex = req->index;
-    e.offset = req->offset;
-    e.length = req->length;
-    publish (msgs, &e);
+  tr_peer_event e = TR_PEER_EVENT_INIT;
+  e.eventType = TR_PEER_CLIENT_GOT_BLOCK;
+  e.pieceIndex = req->index;
+  e.offset = req->offset;
+  e.length = req->length;
+  publish (msgs, &e);
 }
 
 static void
-fireGotRej (tr_peermsgs * msgs, const struct peer_request * req)
+fireGotRej (tr_peerMsgs * msgs, const struct peer_request * req)
 {
-    tr_peer_event e = TR_PEER_EVENT_INIT;
-    e.eventType = TR_PEER_CLIENT_GOT_REJ;
-    e.pieceIndex = req->index;
-    e.offset = req->offset;
-    e.length = req->length;
-    publish (msgs, &e);
+  tr_peer_event e = TR_PEER_EVENT_INIT;
+  e.eventType = TR_PEER_CLIENT_GOT_REJ;
+  e.pieceIndex = req->index;
+  e.offset = req->offset;
+  e.length = req->length;
+  publish (msgs, &e);
 }
 
 static void
-fireGotChoke (tr_peermsgs * msgs)
+fireGotChoke (tr_peerMsgs * msgs)
 {
-    tr_peer_event e = TR_PEER_EVENT_INIT;
-    e.eventType = TR_PEER_CLIENT_GOT_CHOKE;
-    publish (msgs, &e);
+  tr_peer_event e = TR_PEER_EVENT_INIT;
+  e.eventType = TR_PEER_CLIENT_GOT_CHOKE;
+  publish (msgs, &e);
 }
 
 static void
-fireClientGotHaveAll (tr_peermsgs * msgs)
+fireClientGotHaveAll (tr_peerMsgs * msgs)
 {
-    tr_peer_event e = TR_PEER_EVENT_INIT;
-    e.eventType = TR_PEER_CLIENT_GOT_HAVE_ALL;
-    publish (msgs, &e);
+  tr_peer_event e = TR_PEER_EVENT_INIT;
+  e.eventType = TR_PEER_CLIENT_GOT_HAVE_ALL;
+  publish (msgs, &e);
 }
 
 static void
-fireClientGotHaveNone (tr_peermsgs * msgs)
+fireClientGotHaveNone (tr_peerMsgs * msgs)
 {
-    tr_peer_event e = TR_PEER_EVENT_INIT;
-    e.eventType = TR_PEER_CLIENT_GOT_HAVE_NONE;
-    publish (msgs, &e);
+  tr_peer_event e = TR_PEER_EVENT_INIT;
+  e.eventType = TR_PEER_CLIENT_GOT_HAVE_NONE;
+  publish (msgs, &e);
 }
 
 static void
-fireClientGotPieceData (tr_peermsgs * msgs, uint32_t length)
+fireClientGotPieceData (tr_peerMsgs * msgs, uint32_t length)
 {
-    tr_peer_event e = TR_PEER_EVENT_INIT;
-    e.length = length;
-    e.eventType = TR_PEER_CLIENT_GOT_PIECE_DATA;
-    publish (msgs, &e);
+  tr_peer_event e = TR_PEER_EVENT_INIT;
+  e.length = length;
+  e.eventType = TR_PEER_CLIENT_GOT_PIECE_DATA;
+  publish (msgs, &e);
 }
 
 static void
-firePeerGotPieceData (tr_peermsgs * msgs, uint32_t length)
+firePeerGotPieceData (tr_peerMsgs * msgs, uint32_t length)
 {
-    tr_peer_event e = TR_PEER_EVENT_INIT;
-    e.length = length;
-    e.eventType = TR_PEER_PEER_GOT_PIECE_DATA;
-    publish (msgs, &e);
+  tr_peer_event e = TR_PEER_EVENT_INIT;
+  e.length = length;
+  e.eventType = TR_PEER_PEER_GOT_PIECE_DATA;
+  publish (msgs, &e);
 }
 
 static void
-fireClientGotSuggest (tr_peermsgs * msgs, uint32_t pieceIndex)
+fireClientGotSuggest (tr_peerMsgs * msgs, uint32_t pieceIndex)
 {
-    tr_peer_event e = TR_PEER_EVENT_INIT;
-    e.eventType = TR_PEER_CLIENT_GOT_SUGGEST;
-    e.pieceIndex = pieceIndex;
-    publish (msgs, &e);
+  tr_peer_event e = TR_PEER_EVENT_INIT;
+  e.eventType = TR_PEER_CLIENT_GOT_SUGGEST;
+  e.pieceIndex = pieceIndex;
+  publish (msgs, &e);
 }
 
 static void
-fireClientGotPort (tr_peermsgs * msgs, tr_port port)
+fireClientGotPort (tr_peerMsgs * msgs, tr_port port)
 {
-    tr_peer_event e = TR_PEER_EVENT_INIT;
-    e.eventType = TR_PEER_CLIENT_GOT_PORT;
-    e.port = port;
-    publish (msgs, &e);
+  tr_peer_event e = TR_PEER_EVENT_INIT;
+  e.eventType = TR_PEER_CLIENT_GOT_PORT;
+  e.port = port;
+  publish (msgs, &e);
 }
 
 static void
-fireClientGotAllowedFast (tr_peermsgs * msgs, uint32_t pieceIndex)
+fireClientGotAllowedFast (tr_peerMsgs * msgs, uint32_t pieceIndex)
 {
-    tr_peer_event e = TR_PEER_EVENT_INIT;
-    e.eventType = TR_PEER_CLIENT_GOT_ALLOWED_FAST;
-    e.pieceIndex = pieceIndex;
-    publish (msgs, &e);
+  tr_peer_event e = TR_PEER_EVENT_INIT;
+  e.eventType = TR_PEER_CLIENT_GOT_ALLOWED_FAST;
+  e.pieceIndex = pieceIndex;
+  publish (msgs, &e);
 }
 
 static void
-fireClientGotBitfield (tr_peermsgs * msgs, tr_bitfield * bitfield)
+fireClientGotBitfield (tr_peerMsgs * msgs, tr_bitfield * bitfield)
 {
-    tr_peer_event e = TR_PEER_EVENT_INIT;
-    e.eventType = TR_PEER_CLIENT_GOT_BITFIELD;
-    e.bitfield = bitfield;
-    publish (msgs, &e);
+  tr_peer_event e = TR_PEER_EVENT_INIT;
+  e.eventType = TR_PEER_CLIENT_GOT_BITFIELD;
+  e.bitfield = bitfield;
+  publish (msgs, &e);
 }
 
 static void
-fireClientGotHave (tr_peermsgs * msgs, tr_piece_index_t index)
+fireClientGotHave (tr_peerMsgs * msgs, tr_piece_index_t index)
 {
-    tr_peer_event e = TR_PEER_EVENT_INIT;
-    e.eventType = TR_PEER_CLIENT_GOT_HAVE;
-    e.pieceIndex = index;
-    publish (msgs, &e);
+  tr_peer_event e = TR_PEER_EVENT_INIT;
+  e.eventType = TR_PEER_CLIENT_GOT_HAVE;
+  e.pieceIndex = index;
+  publish (msgs, &e);
 }
 
 
@@ -639,15 +655,15 @@ tr_generateAllowedSet (tr_piece_index_t * setmePieces,
 }
 
 static void
-updateFastSet (tr_peermsgs * msgs UNUSED)
+updateFastSet (tr_peerMsgs * msgs UNUSED)
 {
-    const bool fext = tr_peerIoSupportsFEXT (msgs->peer->io);
+    const bool fext = tr_peerIoSupportsFEXT (msgs->io);
     const int peerIsNeedy = msgs->peer->progress < 0.10;
 
     if (fext && peerIsNeedy && !msgs->haveFastSet)
     {
         size_t i;
-        const struct tr_address * addr = tr_peerIoGetAddress (msgs->peer->io, NULL);
+        const struct tr_address * addr = tr_peerIoGetAddress (msgs->io, NULL);
         const tr_info * inf = &msgs->torrent->info;
         const size_t numwant = MIN (MAX_FAST_SET_SIZE, inf->pieceCount);
 
@@ -667,97 +683,98 @@ updateFastSet (tr_peermsgs * msgs UNUSED)
 **/
 
 static void
-sendInterest (tr_peermsgs * msgs, bool clientIsInterested)
+sendInterest (tr_peerMsgs * msgs, bool b)
 {
-    struct evbuffer * out = msgs->outMessages;
+  struct evbuffer * out = msgs->outMessages;
 
-    assert (msgs);
-    assert (tr_isBool (clientIsInterested));
+  assert (msgs);
+  assert (tr_isBool (b));
 
-    msgs->peer->clientIsInterested = clientIsInterested;
-    dbgmsg (msgs, "Sending %s", clientIsInterested ? "Interested" : "Not Interested");
-    evbuffer_add_uint32 (out, sizeof (uint8_t));
-    evbuffer_add_uint8 (out, clientIsInterested ? BT_INTERESTED : BT_NOT_INTERESTED);
+  msgs->client_is_interested = b;
+  dbgmsg (msgs, "Sending %s", b ? "Interested" : "Not Interested");
+  evbuffer_add_uint32 (out, sizeof (uint8_t));
+  evbuffer_add_uint8 (out, b ? BT_INTERESTED : BT_NOT_INTERESTED);
 
-    pokeBatchPeriod (msgs, HIGH_PRIORITY_INTERVAL_SECS);
-    dbgOutMessageLen (msgs);
+  pokeBatchPeriod (msgs, HIGH_PRIORITY_INTERVAL_SECS);
+  dbgOutMessageLen (msgs);
 }
 
 static void
-updateInterest (tr_peermsgs * msgs UNUSED)
+updateInterest (tr_peerMsgs * msgs UNUSED)
 {
     /* FIXME -- might need to poke the mgr on startup */
 }
 
 void
-tr_peerMsgsSetInterested (tr_peermsgs * msgs, bool clientIsInterested)
+tr_peerMsgsSetInterested (tr_peerMsgs * msgs, bool b)
 {
-    assert (tr_isBool (clientIsInterested));
+  assert (tr_isBool (b));
 
-    if (clientIsInterested != msgs->peer->clientIsInterested)
-        sendInterest (msgs, clientIsInterested);
+  if (msgs->client_is_interested != b)
+    sendInterest (msgs, b);
 }
 
 static bool
-popNextMetadataRequest (tr_peermsgs * msgs, int * piece)
+popNextMetadataRequest (tr_peerMsgs * msgs, int * piece)
 {
-    if (msgs->peerAskedForMetadataCount == 0)
-        return false;
+  if (msgs->peerAskedForMetadataCount == 0)
+    return false;
 
-    *piece = msgs->peerAskedForMetadata[0];
+  *piece = msgs->peerAskedForMetadata[0];
 
-    tr_removeElementFromArray (msgs->peerAskedForMetadata, 0, sizeof (int),
-                               msgs->peerAskedForMetadataCount--);
+  tr_removeElementFromArray (msgs->peerAskedForMetadata, 0, sizeof (int),
+                             msgs->peerAskedForMetadataCount--);
 
-    return true;
+  return true;
 }
 
 static bool
-popNextRequest (tr_peermsgs * msgs, struct peer_request * setme)
+popNextRequest (tr_peerMsgs * msgs, struct peer_request * setme)
 {
-    if (msgs->peer->pendingReqsToClient == 0)
-        return false;
+  if (msgs->peer.pendingReqsToClient == 0)
+    return false;
 
-    *setme = msgs->peerAskedFor[0];
+  *setme = msgs->peerAskedFor[0];
 
-    tr_removeElementFromArray (msgs->peerAskedFor, 0, sizeof (struct peer_request),
-                               msgs->peer->pendingReqsToClient--);
+  tr_removeElementFromArray (msgs->peerAskedFor,
+                             0,
+                             sizeof (struct peer_request),
+                             msgs->peer.pendingReqsToClient--);
 
-    return true;
+  return true;
 }
 
 static void
-cancelAllRequestsToClient (tr_peermsgs * msgs)
+cancelAllRequestsToClient (tr_peerMsgs * msgs)
 {
-    struct peer_request req;
-    const int mustSendCancel = tr_peerIoSupportsFEXT (msgs->peer->io);
+  struct peer_request req;
+  const int mustSendCancel = tr_peerIoSupportsFEXT (msgs->io);
 
-    while (popNextRequest (msgs, &req))
-        if (mustSendCancel)
-            protocolSendReject (msgs, &req);
+  while (popNextRequest (msgs, &req))
+    if (mustSendCancel)
+      protocolSendReject (msgs, &req);
 }
 
 void
-tr_peerMsgsSetChoke (tr_peermsgs * msgs, bool peerIsChoked)
+tr_peerMsgsSetChoke (tr_peerMsgs * msgs, bool peer_is_choked)
 {
-    const time_t now = tr_time ();
-    const time_t fibrillationTime = now - MIN_CHOKE_PERIOD_SEC;
+  const time_t now = tr_time ();
+  const time_t fibrillationTime = now - MIN_CHOKE_PERIOD_SEC;
 
-    assert (msgs);
-    assert (msgs->peer);
-    assert (tr_isBool (peerIsChoked));
+  assert (msgs != NULL);
+  assert (tr_isBool (peer_is_choked));
 
-    if (msgs->peer->chokeChangedAt > fibrillationTime)
+  if (msgs->chokeChangedAt > fibrillationTime)
     {
-        dbgmsg (msgs, "Not changing choke to %d to avoid fibrillation", peerIsChoked);
+      dbgmsg (msgs, "Not changing choke to %d to avoid fibrillation", peer_is_choked);
     }
-    else if (msgs->peer->peerIsChoked != peerIsChoked)
+  else if (msgs->peer_is_choked != peer_is_choked)
     {
-        msgs->peer->peerIsChoked = peerIsChoked;
-        if (peerIsChoked)
-            cancelAllRequestsToClient (msgs);
-        protocolSendChoke (msgs, peerIsChoked);
-        msgs->peer->chokeChangedAt = now;
+      msgs->peer_is_choked = peer_is_choked;
+      if (peer_is_choked)
+        cancelAllRequestsToClient (msgs);
+      protocolSendChoke (msgs, peer_is_choked);
+      msgs->chokeChangedAt = now;
     }
 }
 
@@ -766,12 +783,12 @@ tr_peerMsgsSetChoke (tr_peermsgs * msgs, bool peerIsChoked)
 **/
 
 void
-tr_peerMsgsHave (tr_peermsgs * msgs, uint32_t index)
+tr_peerMsgsHave (tr_peerMsgs * msgs, uint32_t index)
 {
-    protocolSendHave (msgs, index);
+  protocolSendHave (msgs, index);
 
-    /* since we have more pieces now, we might not be interested in this peer */
-    updateInterest (msgs);
+  /* since we have more pieces now, we might not be interested in this peer */
+  updateInterest (msgs);
 }
 
 /**
@@ -779,7 +796,7 @@ tr_peerMsgsHave (tr_peermsgs * msgs, uint32_t index)
 **/
 
 static bool
-reqIsValid (const tr_peermsgs * peer,
+reqIsValid (const tr_peerMsgs * peer,
             uint32_t            index,
             uint32_t            offset,
             uint32_t            length)
@@ -788,13 +805,13 @@ reqIsValid (const tr_peermsgs * peer,
 }
 
 static bool
-requestIsValid (const tr_peermsgs * msgs, const struct peer_request * req)
+requestIsValid (const tr_peerMsgs * msgs, const struct peer_request * req)
 {
     return reqIsValid (msgs, req->index, req->offset, req->length);
 }
 
 void
-tr_peerMsgsCancel (tr_peermsgs * msgs, tr_block_index_t block)
+tr_peerMsgsCancel (tr_peerMsgs * msgs, tr_block_index_t block)
 {
     struct peer_request req;
 /*fprintf (stderr, "SENDING CANCEL MESSAGE FOR BLOCK %zu\n\t\tFROM PEER %p ------------------------------------\n", (size_t)block, msgs->peer);*/
@@ -807,7 +824,7 @@ tr_peerMsgsCancel (tr_peermsgs * msgs, tr_block_index_t block)
 **/
 
 static void
-sendLtepHandshake (tr_peermsgs * msgs)
+sendLtepHandshake (tr_peerMsgs * msgs)
 {
     tr_variant val;
     bool allow_pex;
@@ -874,7 +891,7 @@ sendLtepHandshake (tr_peermsgs * msgs)
 }
 
 static void
-parseLtepHandshake (tr_peermsgs * msgs, int len, struct evbuffer * inbuf)
+parseLtepHandshake (tr_peerMsgs * msgs, int len, struct evbuffer * inbuf)
 {
     int64_t   i;
     tr_variant   val, * sub;
@@ -886,7 +903,7 @@ parseLtepHandshake (tr_peermsgs * msgs, int len, struct evbuffer * inbuf)
 
     memset (&pex, 0, sizeof (tr_pex));
 
-    tr_peerIoReadBytes (msgs->peer->io, inbuf, tmp, len);
+    tr_peerIoReadBytes (msgs->io, inbuf, tmp, len);
     msgs->peerSentLtepHandshake = 1;
 
     if (tr_variantFromBenc (&val, tmp, len) || !tr_variantIsDict (&val))
@@ -925,7 +942,7 @@ parseLtepHandshake (tr_peermsgs * msgs, int len, struct evbuffer * inbuf)
             /* Mysterious ÂµTorrent extension that we don't grok.  However,
                it implies support for ÂµTP, so use it to indicate that. */
             tr_peerMgrSetUtpFailed (msgs->torrent,
-                                    tr_peerIoGetAddress (msgs->peer->io, NULL),
+                                    tr_peerIoGetAddress (msgs->io, NULL),
                                     false);
         }
     }
@@ -947,7 +964,7 @@ parseLtepHandshake (tr_peermsgs * msgs, int len, struct evbuffer * inbuf)
         dbgmsg (msgs, "peer's port is now %d", (int)i);
     }
 
-    if (tr_peerIoIsIncoming (msgs->peer->io)
+    if (tr_peerIoIsIncoming (msgs->io)
         && tr_variantDictFindRaw (&val, TR_KEY_ipv4, &addr, &addr_len)
         && (addr_len == 4))
     {
@@ -956,7 +973,7 @@ parseLtepHandshake (tr_peermsgs * msgs, int len, struct evbuffer * inbuf)
         tr_peerMgrAddPex (msgs->torrent, TR_PEER_FROM_LTEP, &pex, seedProbability);
     }
 
-    if (tr_peerIoIsIncoming (msgs->peer->io)
+    if (tr_peerIoIsIncoming (msgs->io)
         && tr_variantDictFindRaw (&val, TR_KEY_ipv6, &addr, &addr_len)
         && (addr_len == 16))
     {
@@ -974,7 +991,7 @@ parseLtepHandshake (tr_peermsgs * msgs, int len, struct evbuffer * inbuf)
 }
 
 static void
-parseUtMetadata (tr_peermsgs * msgs, int msglen, struct evbuffer * inbuf)
+parseUtMetadata (tr_peerMsgs * msgs, int msglen, struct evbuffer * inbuf)
 {
     tr_variant dict;
     char * msg_end;
@@ -984,7 +1001,7 @@ parseUtMetadata (tr_peermsgs * msgs, int msglen, struct evbuffer * inbuf)
     int64_t total_size = 0;
     uint8_t * tmp = tr_new (uint8_t, msglen);
 
-    tr_peerIoReadBytes (msgs->peer->io, inbuf, tmp, msglen);
+    tr_peerIoReadBytes (msgs->io, inbuf, tmp, msglen);
     msg_end = (char*)tmp + msglen;
 
     if (!tr_variantFromBencFull (&dict, tmp, msglen, NULL, &benc_end))
@@ -1051,7 +1068,7 @@ parseUtMetadata (tr_peermsgs * msgs, int msglen, struct evbuffer * inbuf)
 }
 
 static void
-parseUtPex (tr_peermsgs * msgs, int msglen, struct evbuffer * inbuf)
+parseUtPex (tr_peerMsgs * msgs, int msglen, struct evbuffer * inbuf)
 {
     int loaded = 0;
     uint8_t * tmp = tr_new (uint8_t, msglen);
@@ -1060,7 +1077,7 @@ parseUtPex (tr_peermsgs * msgs, int msglen, struct evbuffer * inbuf)
     const uint8_t * added;
     size_t added_len;
 
-    tr_peerIoReadBytes (msgs->peer->io, inbuf, tmp, msglen);
+    tr_peerIoReadBytes (msgs->io, inbuf, tmp, msglen);
 
     if (tr_torrentAllowsPex (tor)
       && ((loaded = !tr_variantFromBenc (&val, tmp, msglen))))
@@ -1113,21 +1130,21 @@ parseUtPex (tr_peermsgs * msgs, int msglen, struct evbuffer * inbuf)
     tr_free (tmp);
 }
 
-static void sendPex (tr_peermsgs * msgs);
+static void sendPex (tr_peerMsgs * msgs);
 
 static void
-parseLtep (tr_peermsgs * msgs, int msglen, struct evbuffer  * inbuf)
+parseLtep (tr_peerMsgs * msgs, int msglen, struct evbuffer  * inbuf)
 {
     uint8_t ltep_msgid;
 
-    tr_peerIoReadUint8 (msgs->peer->io, inbuf, &ltep_msgid);
+    tr_peerIoReadUint8 (msgs->io, inbuf, &ltep_msgid);
     msglen--;
 
     if (ltep_msgid == LTEP_HANDSHAKE)
     {
         dbgmsg (msgs, "got ltep handshake");
         parseLtepHandshake (msgs, msglen, inbuf);
-        if (tr_peerIoSupportsLTEP (msgs->peer->io))
+        if (tr_peerIoSupportsLTEP (msgs->io))
         {
             sendLtepHandshake (msgs);
             sendPex (msgs);
@@ -1153,14 +1170,14 @@ parseLtep (tr_peermsgs * msgs, int msglen, struct evbuffer  * inbuf)
 }
 
 static int
-readBtLength (tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen)
+readBtLength (tr_peerMsgs * msgs, struct evbuffer * inbuf, size_t inlen)
 {
     uint32_t len;
 
     if (inlen < sizeof (len))
         return READ_LATER;
 
-    tr_peerIoReadUint32 (msgs->peer->io, inbuf, &len);
+    tr_peerIoReadUint32 (msgs->io, inbuf, &len);
 
     if (len == 0) /* peer sent us a keepalive message */
         dbgmsg (msgs, "got KeepAlive");
@@ -1173,17 +1190,17 @@ readBtLength (tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen)
     return READ_NOW;
 }
 
-static int readBtMessage (tr_peermsgs *, struct evbuffer *, size_t);
+static int readBtMessage (tr_peerMsgs *, struct evbuffer *, size_t);
 
 static int
-readBtId (tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen)
+readBtId (tr_peerMsgs * msgs, struct evbuffer * inbuf, size_t inlen)
 {
     uint8_t id;
 
     if (inlen < sizeof (uint8_t))
         return READ_LATER;
 
-    tr_peerIoReadUint8 (msgs->peer->io, inbuf, &id);
+    tr_peerIoReadUint8 (msgs->io, inbuf, &id);
     msgs->incoming.id = id;
     dbgmsg (msgs, "msgs->incoming.id is now %d; msgs->incoming.length is %zu", id, (size_t)msgs->incoming.length);
 
@@ -1201,40 +1218,40 @@ readBtId (tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen)
 }
 
 static void
-updatePeerProgress (tr_peermsgs * msgs)
+updatePeerProgress (tr_peerMsgs * msgs)
 {
-    tr_peerUpdateProgress (msgs->torrent, msgs->peer);
+  tr_peerUpdateProgress (msgs->torrent, &msgs->peer);
 
-    /*updateFastSet (msgs);*/
-    updateInterest (msgs);
+  /*updateFastSet (msgs);*/
+  updateInterest (msgs);
 }
 
 static void
-prefetchPieces (tr_peermsgs *msgs)
+prefetchPieces (tr_peerMsgs *msgs)
 {
-    int i;
+  int i;
 
-    if (!getSession (msgs)->isPrefetchEnabled)
-        return;
+  if (!getSession (msgs)->isPrefetchEnabled)
+    return;
 
-    for (i=msgs->prefetchCount; i<msgs->peer->pendingReqsToClient && i<PREFETCH_SIZE; ++i)
+  for (i=msgs->prefetchCount; i<msgs->peer.pendingReqsToClient && i<PREFETCH_SIZE; ++i)
     {
-        const struct peer_request * req = msgs->peerAskedFor + i;
-        if (requestIsValid (msgs, req))
+      const struct peer_request * req = msgs->peerAskedFor + i;
+      if (requestIsValid (msgs, req))
         {
-            tr_cachePrefetchBlock (getSession (msgs)->cache, msgs->torrent, req->index, req->offset, req->length);
-            ++msgs->prefetchCount;
+          tr_cachePrefetchBlock (getSession (msgs)->cache, msgs->torrent, req->index, req->offset, req->length);
+          ++msgs->prefetchCount;
         }
     }
 }
 
 static void
-peerMadeRequest (tr_peermsgs * msgs, const struct peer_request * req)
+peerMadeRequest (tr_peerMsgs * msgs, const struct peer_request * req)
 {
-    const bool fext = tr_peerIoSupportsFEXT (msgs->peer->io);
+    const bool fext = tr_peerIoSupportsFEXT (msgs->io);
     const int reqIsValid = requestIsValid (msgs, req);
     const int clientHasPiece = reqIsValid && tr_cpPieceIsComplete (&msgs->torrent->completion, req->index);
-    const int peerIsChoked = msgs->peer->peerIsChoked;
+    const int peerIsChoked = msgs->peer_is_choked;
 
     int allow = false;
 
@@ -1244,13 +1261,13 @@ peerMadeRequest (tr_peermsgs * msgs, const struct peer_request * req)
         dbgmsg (msgs, "rejecting request for a piece we don't have.");
     else if (peerIsChoked)
         dbgmsg (msgs, "rejecting request from choked peer");
-    else if (msgs->peer->pendingReqsToClient + 1 >= REQQ)
+    else if (msgs->peer.pendingReqsToClient + 1 >= REQQ)
         dbgmsg (msgs, "rejecting request ... reqq is full");
     else
         allow = true;
 
     if (allow) {
-        msgs->peerAskedFor[msgs->peer->pendingReqsToClient++] = *req;
+        msgs->peerAskedFor[msgs->peer.pendingReqsToClient++] = *req;
         prefetchPieces (msgs);
     } else if (fext) {
         protocolSendReject (msgs, req);
@@ -1258,7 +1275,7 @@ peerMadeRequest (tr_peermsgs * msgs, const struct peer_request * req)
 }
 
 static bool
-messageLengthIsCorrect (const tr_peermsgs * msg, uint8_t id, uint32_t len)
+messageLengthIsCorrect (const tr_peerMsgs * msg, uint8_t id, uint32_t len)
 {
     switch (id)
     {
@@ -1303,12 +1320,12 @@ messageLengthIsCorrect (const tr_peermsgs * msg, uint8_t id, uint32_t len)
     }
 }
 
-static int clientGotBlock (tr_peermsgs *               msgs,
+static int clientGotBlock (tr_peerMsgs *               msgs,
                            struct evbuffer *           block,
                            const struct peer_request * req);
 
 static int
-readBtPiece (tr_peermsgs      * msgs,
+readBtPiece (tr_peerMsgs      * msgs,
              struct evbuffer  * inbuf,
              size_t             inlen,
              size_t           * setme_piece_bytes_read)
@@ -1323,8 +1340,8 @@ readBtPiece (tr_peermsgs      * msgs,
         if (inlen < 8)
             return READ_LATER;
 
-        tr_peerIoReadUint32 (msgs->peer->io, inbuf, &req->index);
-        tr_peerIoReadUint32 (msgs->peer->io, inbuf, &req->offset);
+        tr_peerIoReadUint32 (msgs->io, inbuf, &req->index);
+        tr_peerIoReadUint32 (msgs->io, inbuf, &req->offset);
         req->length = msgs->incoming.length - 9;
         dbgmsg (msgs, "got incoming block header %u:%u->%u", req->index, req->offset, req->length);
         return READ_NOW;
@@ -1344,7 +1361,7 @@ readBtPiece (tr_peermsgs      * msgs,
         nLeft = req->length - evbuffer_get_length (block_buffer);
         n = MIN (nLeft, inlen);
 
-        tr_peerIoReadBytesToBuf (msgs->peer->io, inbuf, block_buffer, n);
+        tr_peerIoReadBytesToBuf (msgs->io, inbuf, block_buffer, n);
 
         fireClientGotPieceData (msgs, n);
         *setme_piece_bytes_read += n;
@@ -1365,10 +1382,10 @@ readBtPiece (tr_peermsgs      * msgs,
     }
 }
 
-static void updateDesiredRequestCount (tr_peermsgs * msgs);
+static void updateDesiredRequestCount (tr_peerMsgs * msgs);
 
 static int
-readBtMessage (tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen)
+readBtMessage (tr_peerMsgs * msgs, struct evbuffer * inbuf, size_t inlen)
 {
     uint32_t      ui32;
     uint32_t      msglen = msgs->incoming.length;
@@ -1376,7 +1393,7 @@ readBtMessage (tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen)
 #ifndef NDEBUG
     const size_t  startBufLen = evbuffer_get_length (inbuf);
 #endif
-    const bool fext = tr_peerIoSupportsFEXT (msgs->peer->io);
+    const bool fext = tr_peerIoSupportsFEXT (msgs->io);
 
     --msglen; /* id length */
 
@@ -1396,29 +1413,29 @@ readBtMessage (tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen)
     {
         case BT_CHOKE:
             dbgmsg (msgs, "got Choke");
-            msgs->peer->clientIsChoked = 1;
+            msgs->client_is_choked = true;
             if (!fext)
                 fireGotChoke (msgs);
             break;
 
         case BT_UNCHOKE:
             dbgmsg (msgs, "got Unchoke");
-            msgs->peer->clientIsChoked = 0;
+            msgs->client_is_choked = false;
             updateDesiredRequestCount (msgs);
             break;
 
         case BT_INTERESTED:
             dbgmsg (msgs, "got Interested");
-            msgs->peer->peerIsInterested = 1;
+            msgs->peer_is_interested = true;
             break;
 
         case BT_NOT_INTERESTED:
             dbgmsg (msgs, "got Not Interested");
-            msgs->peer->peerIsInterested = 0;
+            msgs->peer_is_interested = false;
             break;
 
         case BT_HAVE:
-            tr_peerIoReadUint32 (msgs->peer->io, inbuf, &ui32);
+            tr_peerIoReadUint32 (msgs->io, inbuf, &ui32);
             dbgmsg (msgs, "got Have: %u", ui32);
             if (tr_torrentHasMetadata (msgs->torrent)
                     && (ui32 >= msgs->torrent->info.pieceCount))
@@ -1428,8 +1445,8 @@ readBtMessage (tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen)
             }
 
             /* a peer can send the same HAVE message twice... */
-            if (!tr_bitfieldHas (&msgs->peer->have, ui32)) {
-                tr_bitfieldAdd (&msgs->peer->have, ui32);
+            if (!tr_bitfieldHas (&msgs->peer.have, ui32)) {
+                tr_bitfieldAdd (&msgs->peer.have, ui32);
                 fireClientGotHave (msgs, ui32);
             }
             updatePeerProgress (msgs);
@@ -1438,9 +1455,9 @@ readBtMessage (tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen)
         case BT_BITFIELD: {
             uint8_t * tmp = tr_new (uint8_t, msglen);
             dbgmsg (msgs, "got a bitfield");
-            tr_peerIoReadBytes (msgs->peer->io, inbuf, tmp, msglen);
-            tr_bitfieldSetRaw (&msgs->peer->have, tmp, msglen, tr_torrentHasMetadata (msgs->torrent));
-            fireClientGotBitfield (msgs, &msgs->peer->have);
+            tr_peerIoReadBytes (msgs->io, inbuf, tmp, msglen);
+            tr_bitfieldSetRaw (&msgs->peer.have, tmp, msglen, tr_torrentHasMetadata (msgs->torrent));
+            fireClientGotBitfield (msgs, &msgs->peer.have);
             updatePeerProgress (msgs);
             tr_free (tmp);
             break;
@@ -1449,9 +1466,9 @@ readBtMessage (tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen)
         case BT_REQUEST:
         {
             struct peer_request r;
-            tr_peerIoReadUint32 (msgs->peer->io, inbuf, &r.index);
-            tr_peerIoReadUint32 (msgs->peer->io, inbuf, &r.offset);
-            tr_peerIoReadUint32 (msgs->peer->io, inbuf, &r.length);
+            tr_peerIoReadUint32 (msgs->io, inbuf, &r.index);
+            tr_peerIoReadUint32 (msgs->io, inbuf, &r.offset);
+            tr_peerIoReadUint32 (msgs->io, inbuf, &r.length);
             dbgmsg (msgs, "got Request: %u:%u->%u", r.index, r.offset, r.length);
             peerMadeRequest (msgs, &r);
             break;
@@ -1461,21 +1478,21 @@ readBtMessage (tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen)
         {
             int i;
             struct peer_request r;
-            tr_peerIoReadUint32 (msgs->peer->io, inbuf, &r.index);
-            tr_peerIoReadUint32 (msgs->peer->io, inbuf, &r.offset);
-            tr_peerIoReadUint32 (msgs->peer->io, inbuf, &r.length);
-            tr_historyAdd (&msgs->peer->cancelsSentToClient, tr_time (), 1);
+            tr_peerIoReadUint32 (msgs->io, inbuf, &r.index);
+            tr_peerIoReadUint32 (msgs->io, inbuf, &r.offset);
+            tr_peerIoReadUint32 (msgs->io, inbuf, &r.length);
+            tr_historyAdd (&msgs->peer.cancelsSentToClient, tr_time (), 1);
             dbgmsg (msgs, "got a Cancel %u:%u->%u", r.index, r.offset, r.length);
 
-            for (i=0; i<msgs->peer->pendingReqsToClient; ++i) {
+            for (i=0; i<msgs->peer.pendingReqsToClient; ++i) {
                 const struct peer_request * req = msgs->peerAskedFor + i;
                 if ((req->index == r.index) && (req->offset == r.offset) && (req->length == r.length))
                     break;
             }
 
-            if (i < msgs->peer->pendingReqsToClient)
+            if (i < msgs->peer.pendingReqsToClient)
                 tr_removeElementFromArray (msgs->peerAskedFor, i, sizeof (struct peer_request),
-                                           msgs->peer->pendingReqsToClient--);
+                                           msgs->peer.pendingReqsToClient--);
             break;
         }
 
@@ -1485,16 +1502,16 @@ readBtMessage (tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen)
 
         case BT_PORT:
             dbgmsg (msgs, "Got a BT_PORT");
-            tr_peerIoReadUint16 (msgs->peer->io, inbuf, &msgs->dht_port);
+            tr_peerIoReadUint16 (msgs->io, inbuf, &msgs->dht_port);
             if (msgs->dht_port > 0)
                 tr_dhtAddNode (getSession (msgs),
-                               tr_peerAddress (msgs->peer),
+                               tr_peerAddress (&msgs->peer),
                                msgs->dht_port, 0);
             break;
 
         case BT_FEXT_SUGGEST:
             dbgmsg (msgs, "Got a BT_FEXT_SUGGEST");
-            tr_peerIoReadUint32 (msgs->peer->io, inbuf, &ui32);
+            tr_peerIoReadUint32 (msgs->io, inbuf, &ui32);
             if (fext)
                 fireClientGotSuggest (msgs, ui32);
             else {
@@ -1505,7 +1522,7 @@ readBtMessage (tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen)
 
         case BT_FEXT_ALLOWED_FAST:
             dbgmsg (msgs, "Got a BT_FEXT_ALLOWED_FAST");
-            tr_peerIoReadUint32 (msgs->peer->io, inbuf, &ui32);
+            tr_peerIoReadUint32 (msgs->io, inbuf, &ui32);
             if (fext)
                 fireClientGotAllowedFast (msgs, ui32);
             else {
@@ -1517,8 +1534,8 @@ readBtMessage (tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen)
         case BT_FEXT_HAVE_ALL:
             dbgmsg (msgs, "Got a BT_FEXT_HAVE_ALL");
             if (fext) {
-                tr_bitfieldSetHasAll (&msgs->peer->have);
-assert (tr_bitfieldHasAll (&msgs->peer->have));
+                tr_bitfieldSetHasAll (&msgs->peer.have);
+assert (tr_bitfieldHasAll (&msgs->peer.have));
                 fireClientGotHaveAll (msgs);
                 updatePeerProgress (msgs);
             } else {
@@ -1530,7 +1547,7 @@ assert (tr_bitfieldHasAll (&msgs->peer->have));
         case BT_FEXT_HAVE_NONE:
             dbgmsg (msgs, "Got a BT_FEXT_HAVE_NONE");
             if (fext) {
-                tr_bitfieldSetHasNone (&msgs->peer->have);
+                tr_bitfieldSetHasNone (&msgs->peer.have);
                 fireClientGotHaveNone (msgs);
                 updatePeerProgress (msgs);
             } else {
@@ -1543,9 +1560,9 @@ assert (tr_bitfieldHasAll (&msgs->peer->have));
         {
             struct peer_request r;
             dbgmsg (msgs, "Got a BT_FEXT_REJECT");
-            tr_peerIoReadUint32 (msgs->peer->io, inbuf, &r.index);
-            tr_peerIoReadUint32 (msgs->peer->io, inbuf, &r.offset);
-            tr_peerIoReadUint32 (msgs->peer->io, inbuf, &r.length);
+            tr_peerIoReadUint32 (msgs->io, inbuf, &r.index);
+            tr_peerIoReadUint32 (msgs->io, inbuf, &r.offset);
+            tr_peerIoReadUint32 (msgs->io, inbuf, &r.length);
             if (fext)
                 fireGotRej (msgs, &r);
             else {
@@ -1562,7 +1579,7 @@ assert (tr_bitfieldHasAll (&msgs->peer->have));
 
         default:
             dbgmsg (msgs, "peer sent us an UNKNOWN: %d", (int)id);
-            tr_peerIoDrain (msgs->peer->io, inbuf, msglen);
+            tr_peerIoDrain (msgs->io, inbuf, msglen);
             break;
     }
 
@@ -1575,7 +1592,7 @@ assert (tr_bitfieldHasAll (&msgs->peer->have));
 
 /* returns 0 on success, or an errno on failure */
 static int
-clientGotBlock (tr_peermsgs                * msgs,
+clientGotBlock (tr_peerMsgs                * msgs,
                 struct evbuffer            * data,
                 const struct peer_request  * req)
 {
@@ -1594,7 +1611,7 @@ clientGotBlock (tr_peermsgs                * msgs,
 
     dbgmsg (msgs, "got block %u:%u->%u", req->index, req->offset, req->length);
 
-    if (!tr_peerMgrDidPeerRequest (msgs->torrent, msgs->peer, block)) {
+    if (!tr_peerMgrDidPeerRequest (msgs->torrent, &msgs->peer, block)) {
         dbgmsg (msgs, "we didn't ask for this message...");
         return 0;
     }
@@ -1610,7 +1627,7 @@ clientGotBlock (tr_peermsgs                * msgs,
     if ((err = tr_cacheWriteBlock (getSession (msgs)->cache, tor, req->index, req->offset, req->length, data)))
         return err;
 
-    tr_bitfieldAdd (&msgs->peer->blame, req->index);
+    tr_bitfieldAdd (&msgs->peer.blame, req->index);
     fireGotBlock (msgs, req);
     return 0;
 }
@@ -1620,7 +1637,7 @@ static int peerPulse (void * vmsgs);
 static void
 didWrite (tr_peerIo * io UNUSED, size_t bytesWritten, bool wasPieceData, void * vmsgs)
 {
-    tr_peermsgs * msgs = vmsgs;
+    tr_peerMsgs * msgs = vmsgs;
 
     if (wasPieceData)
       firePeerGotPieceData (msgs, bytesWritten);
@@ -1633,7 +1650,7 @@ static ReadState
 canRead (tr_peerIo * io, void * vmsgs, size_t * piece)
 {
     ReadState         ret;
-    tr_peermsgs *     msgs = vmsgs;
+    tr_peerMsgs *     msgs = vmsgs;
     struct evbuffer * in = tr_peerIoGetReadBuffer (io);
     const size_t      inlen = evbuffer_get_length (in);
 
@@ -1669,7 +1686,7 @@ canRead (tr_peerIo * io, void * vmsgs, size_t * piece)
 }
 
 int
-tr_peerMsgsIsReadingBlock (const tr_peermsgs * msgs, tr_block_index_t block)
+tr_peerMsgsIsReadingBlock (const tr_peerMsgs * msgs, tr_block_index_t block)
 {
     if (msgs->state != AWAITING_BT_PIECE)
         return false;
@@ -1684,14 +1701,14 @@ tr_peerMsgsIsReadingBlock (const tr_peermsgs * msgs, tr_block_index_t block)
 **/
 
 static void
-updateDesiredRequestCount (tr_peermsgs * msgs)
+updateDesiredRequestCount (tr_peerMsgs * msgs)
 {
     tr_torrent * const torrent = msgs->torrent;
 
     /* there are lots of reasons we might not want to request any blocks... */
     if (tr_torrentIsSeed (torrent) || !tr_torrentHasMetadata (torrent)
-                                    || msgs->peer->clientIsChoked
-                                    || !msgs->peer->clientIsInterested)
+                                    || msgs->client_is_choked
+                                    || !msgs->client_is_interested)
     {
         msgs->desiredRequestCount = 0;
     }
@@ -1706,7 +1723,7 @@ updateDesiredRequestCount (tr_peermsgs * msgs)
 
         /* Get the rate limit we should use.
          * FIXME: this needs to consider all the other peers as well... */
-        rate_Bps = tr_peerGetPieceSpeed_Bps (msgs->peer, now, TR_PEER_TO_CLIENT);
+        rate_Bps = tr_peerGetPieceSpeed_Bps (&msgs->peer, now, TR_PEER_TO_CLIENT);
         if (tr_torrentUsesSpeedLimit (torrent, TR_PEER_TO_CLIENT))
             rate_Bps = MIN (rate_Bps, tr_torrentGetSpeedLimit_Bps (torrent, TR_PEER_TO_CLIENT));
 
@@ -1728,7 +1745,7 @@ updateDesiredRequestCount (tr_peermsgs * msgs)
 }
 
 static void
-updateMetadataRequests (tr_peermsgs * msgs, time_t now)
+updateMetadataRequests (tr_peerMsgs * msgs, time_t now)
 {
     int piece;
 
@@ -1762,18 +1779,22 @@ updateMetadataRequests (tr_peermsgs * msgs, time_t now)
 }
 
 static void
-updateBlockRequests (tr_peermsgs * msgs)
+updateBlockRequests (tr_peerMsgs * msgs)
 {
     if (tr_torrentIsPieceTransferAllowed (msgs->torrent, TR_PEER_TO_CLIENT)
         && (msgs->desiredRequestCount > 0)
-        && (msgs->peer->pendingReqsToPeer <= (msgs->desiredRequestCount * 0.66)))
+        && (msgs->peer.pendingReqsToPeer <= (msgs->desiredRequestCount * 0.66)))
     {
         int i;
         int n;
-        const int numwant = msgs->desiredRequestCount - msgs->peer->pendingReqsToPeer;
-        tr_block_index_t * blocks = tr_new (tr_block_index_t, numwant);
+        tr_block_index_t * blocks;
+        const int numwant = msgs->desiredRequestCount - msgs->peer.pendingReqsToPeer;
 
-        tr_peerMgrGetNextRequests (msgs->torrent, msgs->peer, numwant, blocks, &n, false);
+        assert (tr_peerMsgsIsClientInterested (msgs));
+        assert (!tr_peerMsgsIsClientChoked (msgs));
+
+        blocks = tr_new (tr_block_index_t, numwant);
+        tr_peerMgrGetNextRequests (msgs->torrent, &msgs->peer, numwant, blocks, &n, false);
 
         for (i=0; i<n; ++i)
         {
@@ -1787,13 +1808,13 @@ updateBlockRequests (tr_peermsgs * msgs)
 }
 
 static size_t
-fillOutputBuffer (tr_peermsgs * msgs, time_t now)
+fillOutputBuffer (tr_peerMsgs * msgs, time_t now)
 {
     int piece;
     size_t bytesWritten = 0;
     struct peer_request req;
     const bool haveMessages = evbuffer_get_length (msgs->outMessages) != 0;
-    const bool fext = tr_peerIoSupportsFEXT (msgs->peer->io);
+    const bool fext = tr_peerIoSupportsFEXT (msgs->io);
 
     /**
     ***  Protocol messages
@@ -1808,8 +1829,8 @@ fillOutputBuffer (tr_peermsgs * msgs, time_t now)
     {
         const size_t len = evbuffer_get_length (msgs->outMessages);
         /* flush the protocol messages */
-        dbgmsg (msgs, "flushing outMessages... to %p (length is %zu)", msgs->peer->io, len);
-        tr_peerIoWriteBuf (msgs->peer->io, msgs->outMessages, false);
+        dbgmsg (msgs, "flushing outMessages... to %p (length is %zu)", msgs->io, len);
+        tr_peerIoWriteBuf (msgs->io, msgs->outMessages, false);
         msgs->clientSentAnythingAt = now;
         msgs->outMessagesBatchedAt = 0;
         msgs->outMessagesBatchPeriod = LOW_PRIORITY_INTERVAL_SECS;
@@ -1820,7 +1841,7 @@ fillOutputBuffer (tr_peermsgs * msgs, time_t now)
     ***  Metadata Pieces
     **/
 
-    if ((tr_peerIoGetWriteBufferSpace (msgs->peer->io, now) >= METADATA_PIECE_SIZE)
+    if ((tr_peerIoGetWriteBufferSpace (msgs->io, now) >= METADATA_PIECE_SIZE)
         && popNextMetadataRequest (msgs, &piece))
     {
         char * data;
@@ -1886,7 +1907,7 @@ fillOutputBuffer (tr_peermsgs * msgs, time_t now)
     ***  Data Blocks
     **/
 
-    if ((tr_peerIoGetWriteBufferSpace (msgs->peer->io, now) >= msgs->torrent->blockSize)
+    if ((tr_peerIoGetWriteBufferSpace (msgs->io, now) >= msgs->torrent->blockSize)
         && popNextRequest (msgs, &req))
     {
         --msgs->prefetchCount;
@@ -1927,10 +1948,10 @@ fillOutputBuffer (tr_peermsgs * msgs, time_t now)
                 const size_t n = evbuffer_get_length (out);
                 dbgmsg (msgs, "sending block %u:%u->%u", req.index, req.offset, req.length);
                 assert (n == msglen);
-                tr_peerIoWriteBuf (msgs->peer->io, out, true);
+                tr_peerIoWriteBuf (msgs->io, out, true);
                 bytesWritten += n;
                 msgs->clientSentAnythingAt = now;
-                tr_historyAdd (&msgs->peer->blocksSentToPeer, tr_time (), 1);
+                tr_historyAdd (&msgs->peer.blocksSentToPeer, tr_time (), 1);
             }
 
             evbuffer_free (out);
@@ -1969,10 +1990,10 @@ fillOutputBuffer (tr_peermsgs * msgs, time_t now)
 static int
 peerPulse (void * vmsgs)
 {
-    tr_peermsgs * msgs = vmsgs;
+    tr_peerMsgs * msgs = vmsgs;
     const time_t  now = tr_time ();
 
-    if (tr_isPeerIo (msgs->peer->io)) {
+    if (tr_isPeerIo (msgs->io)) {
         updateDesiredRequestCount (msgs);
         updateBlockRequests (msgs);
         updateMetadataRequests (msgs, now);
@@ -1986,7 +2007,7 @@ peerPulse (void * vmsgs)
 }
 
 void
-tr_peerMsgsPulse (tr_peermsgs * msgs)
+tr_peerMsgsPulse (tr_peerMsgs * msgs)
 {
     if (msgs != NULL)
         peerPulse (msgs);
@@ -2004,7 +2025,7 @@ gotError (tr_peerIo * io UNUSED, short what, void * vmsgs)
 }
 
 static void
-sendBitfield (tr_peermsgs * msgs)
+sendBitfield (tr_peerMsgs * msgs)
 {
     void * bytes;
     size_t byte_count = 0;
@@ -2023,9 +2044,9 @@ sendBitfield (tr_peermsgs * msgs)
 }
 
 static void
-tellPeerWhatWeHave (tr_peermsgs * msgs)
+tellPeerWhatWeHave (tr_peerMsgs * msgs)
 {
-    const bool fext = tr_peerIoSupportsFEXT (msgs->peer->io);
+    const bool fext = tr_peerIoSupportsFEXT (msgs->io);
 
     if (fext && tr_cpHasAll (&msgs->torrent->completion))
     {
@@ -2164,7 +2185,7 @@ tr_set_compare (const void * va, size_t aCount,
 
 
 static void
-sendPex (tr_peermsgs * msgs)
+sendPex (tr_peerMsgs * msgs)
 {
     if (msgs->peerSupportsPex && tr_torrentAllowsPex (msgs->torrent))
     {
@@ -2333,7 +2354,7 @@ sendPex (tr_peermsgs * msgs)
 static void
 pexPulse (int foo UNUSED, short bar UNUSED, void * vmsgs)
 {
-    struct tr_peermsgs * msgs = vmsgs;
+    struct tr_peerMsgs * msgs = vmsgs;
 
     sendPex (msgs);
 
@@ -2341,83 +2362,207 @@ pexPulse (int foo UNUSED, short bar UNUSED, void * vmsgs)
     tr_timerAdd (msgs->pexTimer, PEX_INTERVAL_SECS, 0);
 }
 
-/**
-***
-**/
+/***
+****  tr_peer virtual functions
+***/
 
-tr_peermsgs*
-tr_peerMsgsNew (struct tr_torrent    * torrent,
-                struct tr_peer       * peer,
-                tr_peer_callback     * callback,
-                void                 * callbackData)
+static bool
+peermsgs_is_transferring_pieces (const struct tr_peer * peer,
+                                 uint64_t               now,
+                                 tr_direction           direction, 
+                                 unsigned int         * setme_Bps)
 {
-    tr_peermsgs * m;
-
-    assert (peer);
-    assert (peer->io);
-
-    m = tr_new0 (tr_peermsgs, 1);
-    m->callback = callback;
-    m->callbackData = callbackData;
-    m->peer = peer;
-    m->torrent = torrent;
-    m->peer->clientIsChoked = 1;
-    m->peer->peerIsChoked = 1;
-    m->peer->clientIsInterested = 0;
-    m->peer->peerIsInterested = 0;
-    m->state = AWAITING_BT_LENGTH;
-    m->outMessages = evbuffer_new ();
-    m->outMessagesBatchedAt = 0;
-    m->outMessagesBatchPeriod = LOW_PRIORITY_INTERVAL_SECS;
-    peer->msgs = m;
-
-    if (tr_torrentAllowsPex (torrent)) {
-        m->pexTimer = evtimer_new (torrent->session->event_base, pexPulse, m);
-        tr_timerAdd (m->pexTimer, PEX_INTERVAL_SECS, 0);
-    }
+  unsigned int Bps = 0;
 
-    if (tr_peerIoSupportsUTP (peer->io)) {
-        const tr_address * addr = tr_peerIoGetAddress (peer->io, NULL);
-        tr_peerMgrSetUtpSupported (torrent, addr);
-        tr_peerMgrSetUtpFailed (torrent, addr, false);
+  if (tr_isPeerMsgs (peer))
+    {
+      const tr_peerMsgs * msgs = (const tr_peerMsgs *) peer;
+      Bps = tr_peerIoGetPieceSpeed_Bps (msgs->io, now, direction);
     }
 
-    if (tr_peerIoSupportsLTEP (peer->io))
-        sendLtepHandshake (m);
+  if (setme_Bps != NULL)
+    *setme_Bps = Bps;
 
-    tellPeerWhatWeHave (m);
+  return Bps > 0;
+}
 
-    if (tr_dhtEnabled (torrent->session) && tr_peerIoSupportsDHT (peer->io))
+static void
+peermsgs_destruct (tr_peer * peer)
+{
+  tr_peerMsgs * msgs = PEER_MSGS (peer);
+
+  assert (msgs != NULL);
+
+  if (msgs->pexTimer != NULL)
+    event_free (msgs->pexTimer);
+
+  if (msgs->incoming.block != NULL)
+    evbuffer_free (msgs->incoming.block);
+
+  if (msgs->io)
     {
-        /* Only send PORT over IPv6 when the IPv6 DHT is running (BEP-32). */
-        const struct tr_address *addr = tr_peerIoGetAddress (peer->io, NULL);
-        if (addr->type == TR_AF_INET || tr_globalIPv6 ()) {
-            protocolSendPort (m, tr_dhtPort (torrent->session));
-        }
+      tr_peerIoClear (msgs->io);
+      tr_peerIoUnref (msgs->io); /* balanced by the ref in handshakeDoneCB () */
     }
 
-    tr_peerIoSetIOFuncs (m->peer->io, canRead, didWrite, gotError, m);
-    updateDesiredRequestCount (m);
+  evbuffer_free (msgs->outMessages);
+  tr_free (msgs->pex6);
+  tr_free (msgs->pex);
 
-    return m;
+  tr_peerDestruct (&msgs->peer);
+
+  memset (msgs, ~0, sizeof (tr_peerMsgs));
 }
 
-void
-tr_peerMsgsFree (tr_peermsgs* msgs)
+static const struct tr_peer_virtual_funcs my_funcs =
+{
+  .destruct = peermsgs_destruct,
+  .is_transferring_pieces = peermsgs_is_transferring_pieces
+};
+
+/***
+****
+***/
+
+time_t
+tr_peerMsgsGetConnectionAge (const tr_peerMsgs * msgs)
+{
+  assert (tr_isPeerMsgs (msgs));
+
+  return tr_peerIoGetAge (msgs->io);
+}
+
+bool
+tr_peerMsgsIsPeerChoked (const tr_peerMsgs * msgs)
+{
+  assert (tr_isPeerMsgs (msgs));
+
+  return msgs->peer_is_choked;
+}
+
+bool
+tr_peerMsgsIsPeerInterested (const tr_peerMsgs * msgs)
+{
+  assert (tr_isPeerMsgs (msgs));
+
+  return msgs->peer_is_interested;
+}
+
+bool
+tr_peerMsgsIsClientChoked (const tr_peerMsgs * msgs)
+{
+  assert (tr_isPeerMsgs (msgs));
+
+  return msgs->client_is_choked;
+}
+
+bool
+tr_peerMsgsIsClientInterested (const tr_peerMsgs * msgs)
+{
+  assert (tr_isPeerMsgs (msgs));
+
+  return msgs->client_is_interested;
+}
+
+bool
+tr_peerMsgsIsUtpConnection (const tr_peerMsgs * msgs)
+{
+  assert (tr_isPeerMsgs (msgs));
+
+  return msgs->io->utp_socket != NULL;
+}
+
+bool
+tr_peerMsgsIsEncrypted (const tr_peerMsgs * msgs)
 {
-    if (msgs)
+  assert (tr_isPeerMsgs (msgs));
+
+  return tr_peerIoIsEncrypted (msgs->io);
+}
+
+bool
+tr_peerMsgsIsIncomingConnection (const tr_peerMsgs * msgs)
+{
+  assert (tr_isPeerMsgs (msgs));
+
+  return tr_peerIoIsIncoming (msgs->io);
+}
+
+/***
+****
+***/
+
+bool
+tr_isPeerMsgs (const void * msgs)
+{
+  /* FIXME: this is pretty crude */
+  return (msgs != NULL)
+      && (((struct tr_peerMsgs*)msgs)->magic_number == MAGIC_NUMBER);
+}
+
+tr_peerMsgs *
+tr_peerMsgsCast (void * vm)
+{
+  return tr_isPeerMsgs(vm) ? vm : NULL;
+}
+
+tr_peerMsgs *
+tr_peerMsgsNew (struct tr_torrent    * torrent,
+                struct tr_peerIo     * io,
+                tr_peer_callback     * callback,
+                void                 * callbackData)
+{
+  tr_peerMsgs * m;
+
+  assert (io != NULL);
+
+  m = tr_new0 (tr_peerMsgs, 1);
+
+  tr_peerConstruct (&m->peer, torrent);
+  m->peer.funcs = &my_funcs;
+
+  m->magic_number = MAGIC_NUMBER;
+  m->client_is_choked = true;
+  m->peer_is_choked = true;
+  m->client_is_interested = false;
+  m->peer_is_interested = false;
+  m->callback = callback;
+  m->callbackData = callbackData;
+  m->io = io;
+  m->torrent = torrent;
+  m->state = AWAITING_BT_LENGTH;
+  m->outMessages = evbuffer_new ();
+  m->outMessagesBatchedAt = 0;
+  m->outMessagesBatchPeriod = LOW_PRIORITY_INTERVAL_SECS;
+
+  if (tr_torrentAllowsPex (torrent))
     {
-        if (msgs->pexTimer != NULL)
-            event_free (msgs->pexTimer);
+      m->pexTimer = evtimer_new (torrent->session->event_base, pexPulse, m);
+      tr_timerAdd (m->pexTimer, PEX_INTERVAL_SECS, 0);
+    }
+
+  if (tr_peerIoSupportsUTP (m->io))
+    {
+      const tr_address * addr = tr_peerIoGetAddress (m->io, NULL);
+      tr_peerMgrSetUtpSupported (torrent, addr);
+      tr_peerMgrSetUtpFailed (torrent, addr, false);
+    }
 
-        if (msgs->incoming.block != NULL)
-            evbuffer_free (msgs->incoming.block);
+  if (tr_peerIoSupportsLTEP (m->io))
+    sendLtepHandshake (m);
 
-        evbuffer_free (msgs->outMessages);
-        tr_free (msgs->pex6);
-        tr_free (msgs->pex);
+  tellPeerWhatWeHave (m);
 
-        memset (msgs, ~0, sizeof (tr_peermsgs));
-        tr_free (msgs);
+  if (tr_dhtEnabled (torrent->session) && tr_peerIoSupportsDHT (m->io))
+    {
+      /* Only send PORT over IPv6 when the IPv6 DHT is running (BEP-32). */
+      const struct tr_address *addr = tr_peerIoGetAddress (m->io, NULL);
+      if (addr->type == TR_AF_INET || tr_globalIPv6 ())
+        protocolSendPort (m, tr_dhtPort (torrent->session));
     }
+
+  tr_peerIoSetIOFuncs (m->io, canRead, didWrite, gotError, m);
+  updateDesiredRequestCount (m);
+
+  return m;
 }
index 9955c4c2e4fd8a5653bb2f3841f34c9a286095f2..459166bba7658a922649f38e3227c1a6ed7f2cfb 100644 (file)
@@ -11,7 +11,7 @@
  */
 
 #ifndef __TRANSMISSION__
-#error only libtransmission should #include this header.
+ #error only libtransmission should #include this header.
 #endif
 
 #ifndef TR_PEER_MSGS_H
@@ -23,6 +23,7 @@
 struct tr_address;
 struct tr_bitfield;
 struct tr_peer;
+struct tr_peerIo;
 struct tr_torrent;
 
 /**
@@ -30,37 +31,57 @@ struct tr_torrent;
  * @{
  */
 
-typedef struct tr_peermsgs tr_peermsgs;
+typedef struct tr_peerMsgs tr_peerMsgs;
 
-tr_peermsgs* tr_peerMsgsNew              (struct tr_torrent        * torrent,
-                                          struct tr_peer           * peer,
-                                          tr_peer_callback         * callback,
-                                          void                     * callback_data);
+#define PEER_MSGS(o) (tr_peerMsgsCast(o))
 
-void         tr_peerMsgsSetChoke         (tr_peermsgs              * msgs,
-                                          bool                       peerIsChoked);
+bool         tr_isPeerMsgs                   (const void               * msgs);
 
-int          tr_peerMsgsIsReadingBlock   (const tr_peermsgs        * msgs,
-                                          tr_block_index_t           block);
+tr_peerMsgs* tr_peerMsgsCast                 (void                     * msgs);
 
-void         tr_peerMsgsSetInterested    (tr_peermsgs              * msgs,
-                                          bool                       clientIsInterested);
+tr_peerMsgs* tr_peerMsgsNew                  (struct tr_torrent        * torrent,
+                                              struct tr_peerIo         * io,
+                                              tr_peer_callback         * callback,
+                                              void                     * callback_data);
 
-void         tr_peerMsgsHave             (tr_peermsgs              * msgs,
-                                          uint32_t                   pieceIndex);
+bool         tr_peerMsgsIsPeerChoked         (const tr_peerMsgs        * msgs);
 
-void         tr_peerMsgsPulse            (tr_peermsgs              * msgs);
+bool         tr_peerMsgsIsPeerInterested     (const tr_peerMsgs        * msgs);
 
-void         tr_peerMsgsCancel           (tr_peermsgs              * msgs,
-                                          tr_block_index_t           block);
+bool         tr_peerMsgsIsClientChoked       (const tr_peerMsgs        * msgs);
 
-void         tr_peerMsgsFree             (tr_peermsgs              * msgs);
+bool         tr_peerMsgsIsClientInterested   (const tr_peerMsgs        * msgs);
 
-size_t       tr_generateAllowedSet       (tr_piece_index_t         * setmePieces,
-                                          size_t                     desiredSetSize,
-                                          size_t                     pieceCount,
-                                          const uint8_t            * infohash,
-                                          const struct tr_address  * addr);
+time_t       tr_peerMsgsGetConnectionAge     (const tr_peerMsgs        * msgs);
+
+bool         tr_peerMsgsIsUtpConnection      (const tr_peerMsgs        * msgs);
+
+bool         tr_peerMsgsIsEncrypted          (const tr_peerMsgs        * msgs);
+
+bool         tr_peerMsgsIsIncomingConnection (const tr_peerMsgs        * msgs);
+
+void         tr_peerMsgsSetChoke             (tr_peerMsgs              * msgs,
+                                              bool                       peerIsChoked);
+
+int          tr_peerMsgsIsReadingBlock       (const tr_peerMsgs        * msgs,
+                                              tr_block_index_t           block);
+
+void         tr_peerMsgsSetInterested        (tr_peerMsgs              * msgs,
+                                              bool                       clientIsInterested);
+
+void         tr_peerMsgsHave                 (tr_peerMsgs              * msgs,
+                                              uint32_t                   pieceIndex);
+
+void         tr_peerMsgsPulse                (tr_peerMsgs              * msgs);
+
+void         tr_peerMsgsCancel               (tr_peerMsgs              * msgs,
+                                              tr_block_index_t           block);
+
+size_t       tr_generateAllowedSet           (tr_piece_index_t         * setmePieces,
+                                              size_t                     desiredSetSize,
+                                              size_t                     pieceCount,
+                                              const uint8_t            * infohash,
+                                              const struct tr_address  * addr);
 
 
 /* @} */
index 1c4302452d5e50fb36f2ee942a21a47fb50d1af0..f3ed278e23e1b84ef54d833a5288f95d467f060f 100644 (file)
 
 struct tr_webseed_task
 {
-    struct evbuffer    * content;
-    struct tr_webseed  * webseed;
-    tr_block_index_t     block;
-    tr_piece_index_t     piece_index;
-    uint32_t             piece_offset;
-    uint32_t             length;
-    tr_block_index_t     blocks_done;
-    uint32_t             block_size;
-    struct tr_web_task * web_task;
-    long                 response_code;
+  bool                 dead;
+  struct evbuffer    * content;
+  struct tr_webseed  * webseed;
+  tr_session         * session;
+  tr_block_index_t     block;
+  tr_piece_index_t     piece_index;
+  uint32_t             piece_offset;
+  uint32_t             length;
+  tr_block_index_t     blocks_done;
+  uint32_t             block_size;
+  struct tr_web_task * web_task;
+  long                 response_code;
 };
 
 struct tr_webseed
 {
-    tr_peer              parent;
-    tr_bandwidth         bandwidth;
-    tr_session         * session;
-    tr_peer_callback   * callback;
-    void               * callback_data;
-    tr_list            * tasks;
-    struct event       * timer;
-    char               * base_url;
-    size_t               base_url_len;
-    int                  torrent_id;
-    bool                 is_stopping;
-    int                  consecutive_failures;
-    int                  retry_tickcount;
-    int                  retry_challenge;
-    int                  idle_connections;
-    int                  active_transfers;
-    char              ** file_urls;
+  tr_peer              parent;
+  tr_bandwidth         bandwidth;
+  tr_session         * session;
+  tr_peer_callback   * callback;
+  void               * callback_data;
+  tr_list            * tasks;
+  struct event       * timer;
+  char               * base_url;
+  size_t               base_url_len;
+  int                  torrent_id;
+  int                  consecutive_failures;
+  int                  retry_tickcount;
+  int                  retry_challenge;
+  int                  idle_connections;
+  int                  active_transfers;
+  char              ** file_urls;
 };
 
 enum
 {
-    TR_IDLE_TIMER_MSEC = 2000,
+  TR_IDLE_TIMER_MSEC = 2000,
 
-    FAILURE_RETRY_INTERVAL = 150,
+  FAILURE_RETRY_INTERVAL = 150,
 
-    MAX_CONSECUTIVE_FAILURES = 5,
+  MAX_CONSECUTIVE_FAILURES = 5,
 
-    MAX_WEBSEED_CONNECTIONS = 4
+  MAX_WEBSEED_CONNECTIONS = 4
 };
 
-static void
-webseed_free (struct tr_webseed * w)
-{
-    tr_torrent * tor = tr_torrentFindFromId (w->session, w->torrent_id);
-    const tr_info * inf = tr_torrentInfo (tor);
-    tr_file_index_t i;
-
-    /* if we have an array of file URLs, free it */
-    if (w->file_urls != NULL) {
-        for (i=0; i<inf->fileCount; ++i)
-            tr_free (w->file_urls[i]);
-        tr_free (w->file_urls);
-    }
-
-    /* webseed destruct */
-    event_free (w->timer);
-    tr_bandwidthDestruct (&w->bandwidth);
-    tr_free (w->base_url);
-
-    /* parent class destruct */
-    tr_peerDestruct (tor, &w->parent);
-
-    tr_free (w);
-}
-
 /***
 ****
 ***/
@@ -110,44 +86,50 @@ publish (tr_webseed * w, tr_peer_event * e)
 }
 
 static void
-fire_client_got_rejs (tr_torrent * tor, tr_webseed * w,
-                      tr_block_index_t block, tr_block_index_t count)
+fire_client_got_rejs (tr_torrent        * tor,
+                      tr_webseed        * w,
+                      tr_block_index_t    block,
+                      tr_block_index_t    count)
 {
-    tr_block_index_t i;
-    tr_peer_event e = TR_PEER_EVENT_INIT;
-    e.eventType = TR_PEER_CLIENT_GOT_REJ;
-    tr_torrentGetBlockLocation (tor, block, &e.pieceIndex, &e.offset, &e.length);
-    for (i = 1; i <= count; i++) {
-        if (i == count)
-            e.length = tr_torBlockCountBytes (tor, block + count - 1);
-        publish (w, &e);
-        e.offset += e.length;
+  tr_block_index_t i;
+  tr_peer_event e = TR_PEER_EVENT_INIT;
+  e.eventType = TR_PEER_CLIENT_GOT_REJ;
+  tr_torrentGetBlockLocation (tor, block, &e.pieceIndex, &e.offset, &e.length);
+  for (i = 1; i <= count; i++)
+    {
+      if (i == count)
+        e.length = tr_torBlockCountBytes (tor, block + count - 1);
+      publish (w, &e);
+      e.offset += e.length;
     }
 }
 
 static void
-fire_client_got_blocks (tr_torrent * tor, tr_webseed * w,
-                        tr_block_index_t block, tr_block_index_t count)
+fire_client_got_blocks (tr_torrent        * tor,
+                        tr_webseed        * w,
+                        tr_block_index_t    block,
+                        tr_block_index_t    count)
 {
-    tr_block_index_t i;
-    tr_peer_event e = TR_PEER_EVENT_INIT;
-    e.eventType = TR_PEER_CLIENT_GOT_BLOCK;
-    tr_torrentGetBlockLocation (tor, block, &e.pieceIndex, &e.offset, &e.length);
-    for (i = 1; i <= count; i++) {
-        if (i == count)
-            e.length = tr_torBlockCountBytes (tor, block + count - 1);
-        publish (w, &e);
-        e.offset += e.length;
+  tr_block_index_t i;
+  tr_peer_event e = TR_PEER_EVENT_INIT;
+  e.eventType = TR_PEER_CLIENT_GOT_BLOCK;
+  tr_torrentGetBlockLocation (tor, block, &e.pieceIndex, &e.offset, &e.length);
+  for (i = 1; i <= count; i++)
+    {
+      if (i == count)
+        e.length = tr_torBlockCountBytes (tor, block + count - 1);
+      publish (w, &e);
+      e.offset += e.length;
     }
 }
 
 static void
 fire_client_got_piece_data (tr_webseed * w, uint32_t length)
 {
-    tr_peer_event e = TR_PEER_EVENT_INIT;
-    e.eventType = TR_PEER_CLIENT_GOT_PIECE_DATA;
-    e.length = length;
-    publish (w, &e);
+  tr_peer_event e = TR_PEER_EVENT_INIT;
+  e.eventType = TR_PEER_CLIENT_GOT_PIECE_DATA;
+  e.length = length;
+  publish (w, &e);
 }
 
 /***
@@ -156,43 +138,45 @@ fire_client_got_piece_data (tr_webseed * w, uint32_t length)
 
 struct write_block_data
 {
-    struct tr_webseed  * webseed;
-    struct evbuffer    * content;
-    tr_piece_index_t     piece_index;
-    tr_block_index_t     block_index;
-    tr_block_index_t     count;
-    uint32_t             block_offset;
+  tr_session         * session;
+  int                  torrent_id;
+  struct tr_webseed  * webseed;
+  struct evbuffer    * content;
+  tr_piece_index_t     piece_index;
+  tr_block_index_t     block_index;
+  tr_block_index_t     count;
+  uint32_t             block_offset;
 };
 
 static void
 write_block_func (void * vdata)
 {
-    struct write_block_data * data = vdata;
-    struct tr_webseed * w = data->webseed;
-    struct evbuffer * buf = data->content;
-    struct tr_torrent * tor;
+  struct write_block_data * data = vdata;
+  struct tr_webseed * w = data->webseed;
+  struct evbuffer * buf = data->content;
+  struct tr_torrent * tor;
 
-    tor = tr_torrentFindFromId (w->session, w->torrent_id);
-    if (tor)
+  tor = tr_torrentFindFromId (data->session, data->torrent_id);
+  if (tor != NULL)
     {
-        const uint32_t block_size = tor->blockSize;
-        uint32_t len = evbuffer_get_length (buf);
-        const uint32_t offset_end = data->block_offset + len;
-        tr_cache * cache = w->session->cache;
-        const tr_piece_index_t piece = data->piece_index;
+      const uint32_t block_size = tor->blockSize;
+      uint32_t len = evbuffer_get_length (buf);
+      const uint32_t offset_end = data->block_offset + len;
+      tr_cache * cache = data->session->cache;
+      const tr_piece_index_t piece = data->piece_index;
 
-        while (len > 0)
+      while (len > 0)
         {
-            const uint32_t bytes_this_pass = MIN (len, block_size);
-            tr_cacheWriteBlock (cache, tor, piece, offset_end - len, bytes_this_pass, buf);
-            len -= bytes_this_pass;
+          const uint32_t bytes_this_pass = MIN (len, block_size);
+          tr_cacheWriteBlock (cache, tor, piece, offset_end - len, bytes_this_pass, buf);
+          len -= bytes_this_pass;
         }
 
-        fire_client_got_blocks (tor, w, data->block_index, data->count);
+      fire_client_got_blocks (tor, w, data->block_index, data->count);
     }
 
-    evbuffer_free (buf);
-    tr_free (data);
+  evbuffer_free (buf);
+  tr_free (data);
 }
 
 /***
@@ -201,34 +185,37 @@ write_block_func (void * vdata)
 
 struct connection_succeeded_data
 {
-    struct tr_webseed  * webseed;
-    char               * real_url;
-    tr_piece_index_t     piece_index;
-    uint32_t             piece_offset;
+  struct tr_webseed  * webseed;
+  char               * real_url;
+  tr_piece_index_t     piece_index;
+  uint32_t             piece_offset;
 };
 
 static void
 connection_succeeded (void * vdata)
 {
-    tr_torrent * tor;
-    struct connection_succeeded_data * data = vdata;
-    struct tr_webseed * w = data->webseed;
+  tr_torrent * tor;
+  struct connection_succeeded_data * data = vdata;
+  struct tr_webseed * w = data->webseed;
 
-    if (++w->active_transfers >= w->retry_challenge && w->retry_challenge)
-        /* the server seems to be accepting more connections now */
-        w->consecutive_failures = w->retry_tickcount = w->retry_challenge = 0;
+  if (++w->active_transfers >= w->retry_challenge && w->retry_challenge)
+    /* the server seems to be accepting more connections now */
+    w->consecutive_failures = w->retry_tickcount = w->retry_challenge = 0;
 
-    if (data->real_url &&
-      (tor = tr_torrentFindFromId (w->session, w->torrent_id)))
+  if (data->real_url && (tor = tr_torrentFindFromId (w->session, w->torrent_id)))
     {
-        uint64_t file_offset;
-        tr_file_index_t file_index;
-
-        tr_ioFindFileLocation (tor, data->piece_index, data->piece_offset,
-                               &file_index, &file_offset);
-        tr_free (w->file_urls[file_index]);
-        w->file_urls[file_index] = data->real_url;
+      uint64_t file_offset;
+      tr_file_index_t file_index;
+
+      tr_ioFindFileLocation (tor, data->piece_index, data->piece_offset,
+                             &file_index, &file_offset);
+      tr_free (w->file_urls[file_index]);
+      w->file_urls[file_index] = data->real_url;
+      data->real_url = NULL;
     }
+
+  tr_free (data->real_url);
+  tr_free (data);
 }
 
 /***
@@ -240,145 +227,139 @@ on_content_changed (struct evbuffer                * buf,
                     const struct evbuffer_cb_info  * info,
                     void                           * vtask)
 {
-    uint32_t len;
-    const size_t n_added = info->n_added;
-    struct tr_webseed_task * task = vtask;
-    struct tr_webseed * w = task->webseed;
+  const size_t n_added = info->n_added;
+  struct tr_webseed_task * task = vtask;
+  tr_session * session = task->session;
 
-    if (n_added <= 0)
-        return;
+  tr_sessionLock (session);
 
-    if (!w->is_stopping)
+  if (!task->dead && (n_added>0))
     {
-        tr_bandwidthUsed (&w->bandwidth, TR_DOWN, n_added, true, tr_time_msec ());
-        fire_client_got_piece_data (w, n_added);
-    }
+      uint32_t len;
+      struct tr_webseed * w = task->webseed;
 
-    len = evbuffer_get_length (buf);
+      tr_bandwidthUsed (&w->bandwidth, TR_DOWN, n_added, true, tr_time_msec ());
+      fire_client_got_piece_data (w, n_added);
+      len = evbuffer_get_length (buf);
 
-    if (!task->response_code)
-    {
-        tr_webGetTaskInfo (task->web_task, TR_WEB_GET_CODE, &task->response_code);
+      if (!task->response_code)
+        {
+          tr_webGetTaskInfo (task->web_task, TR_WEB_GET_CODE, &task->response_code);
+
+          if (task->response_code == 206)
+            {
+              const char * url;
+              struct connection_succeeded_data * data;
+
+              url = NULL;
+              tr_webGetTaskInfo (task->web_task, TR_WEB_GET_REAL_URL, &url);
+
+              data = tr_new (struct connection_succeeded_data, 1);
+              data->webseed = w;
+              data->real_url = tr_strdup (url);
+              data->piece_index = task->piece_index;
+              data->piece_offset = task->piece_offset + (task->blocks_done * task->block_size) + (len - 1);
+
+              /* processing this uses a tr_torrent pointer,
+                 so push the work to the libevent thread... */
+              tr_runInEventThread (w->session, connection_succeeded, data);
+            }
+        }
 
-        if (task->response_code == 206)
+      if ((task->response_code == 206) && (len >= task->block_size))
         {
-            const char * url;
-            struct connection_succeeded_data * data;
-
-            url = NULL;
-            tr_webGetTaskInfo (task->web_task, TR_WEB_GET_REAL_URL, &url);
-
-            data = tr_new (struct connection_succeeded_data, 1);
-            data->webseed = w;
-            data->real_url = tr_strdup (url);
-            data->piece_index = task->piece_index;
-            data->piece_offset = task->piece_offset
-                               + (task->blocks_done * task->block_size)
-                               + (len - 1);
-
-            /* processing this uses a tr_torrent pointer,
-               so push the work to the libevent thread... */
-            tr_runInEventThread (w->session, connection_succeeded, data);
+          /* once we've got at least one full block, save it */
+
+          struct write_block_data * data;
+          const uint32_t block_size = task->block_size;
+          const tr_block_index_t completed = len / block_size;
+
+          data = tr_new (struct write_block_data, 1);
+          data->webseed = task->webseed;
+          data->piece_index = task->piece_index;
+          data->block_index = task->block + task->blocks_done;
+          data->count = completed;
+          data->block_offset = task->piece_offset + task->blocks_done * block_size;
+          data->content = evbuffer_new ();
+          data->torrent_id = w->torrent_id;
+          data->session = w->session;
+
+          /* we don't use locking on this evbuffer so we must copy out the data
+             that will be needed when writing the block in a different thread */
+          evbuffer_remove_buffer (task->content, data->content,
+                                  block_size * completed);
+  
+          tr_runInEventThread (w->session, write_block_func, data);
+          task->blocks_done += completed;
         }
     }
 
-    if ((task->response_code == 206) && (len >= task->block_size))
-    {
-        /* once we've got at least one full block, save it */
-
-        struct write_block_data * data;
-        const uint32_t block_size = task->block_size;
-        const tr_block_index_t completed = len / block_size;
-
-        data = tr_new (struct write_block_data, 1);
-        data->webseed = task->webseed;
-        data->piece_index = task->piece_index;
-        data->block_index = task->block + task->blocks_done;
-        data->count = completed;
-        data->block_offset = task->piece_offset + task->blocks_done * block_size;
-        data->content = evbuffer_new ();
-
-        /* we don't use locking on this evbuffer so we must copy out the data
-        that will be needed when writing the block in a different thread */
-        evbuffer_remove_buffer (task->content, data->content,
-                                block_size * completed);
-
-        tr_runInEventThread (w->session, write_block_func, data);
-        task->blocks_done += completed;
-    }
+  tr_sessionUnlock (session);
 }
 
 static void task_request_next_chunk (struct tr_webseed_task * task);
 
-static bool
-webseed_has_tasks (const tr_webseed * w)
-{
-    return w->tasks != NULL;
-}
-
-
 static void
 on_idle (tr_webseed * w)
 {
-    tr_torrent * tor = tr_torrentFindFromId (w->session, w->torrent_id);
-    int want, running_tasks = tr_list_size (w->tasks);
+  int want;
+  int running_tasks = tr_list_size (w->tasks);
+  tr_torrent * tor = tr_torrentFindFromId (w->session, w->torrent_id);
 
-    if (w->consecutive_failures >= MAX_CONSECUTIVE_FAILURES) {
-        want = w->idle_connections;
+  if (w->consecutive_failures >= MAX_CONSECUTIVE_FAILURES)
+    {
+      want = w->idle_connections;
 
-        if (w->retry_tickcount >= FAILURE_RETRY_INTERVAL) {
-            /* some time has passed since our connection attempts failed. try again */
-            ++want;
-            /* if this challenge is fulfilled we will reset consecutive_failures */
-            w->retry_challenge = running_tasks + want;
+      if (w->retry_tickcount >= FAILURE_RETRY_INTERVAL)
+        {
+          /* some time has passed since our connection attempts failed. try again */
+          ++want;
+          /* if this challenge is fulfilled we will reset consecutive_failures */
+          w->retry_challenge = running_tasks + want;
         }
     }
-    else {
-        want = MAX_WEBSEED_CONNECTIONS - running_tasks;
-        w->retry_challenge = running_tasks + w->idle_connections + 1;
-    }
-
-    if (w->is_stopping && !webseed_has_tasks (w))
+  else
     {
-        webseed_free (w);
+      want = MAX_WEBSEED_CONNECTIONS - running_tasks;
+      w->retry_challenge = running_tasks + w->idle_connections + 1;
     }
-    else if (!w->is_stopping && tor
-                             && tor->isRunning
-                             && !tr_torrentIsSeed (tor)
-                             && want)
+
+  if (tor && tor->isRunning && !tr_torrentIsSeed (tor) && want)
     {
-        int i;
-        int got = 0;
-        tr_block_index_t * blocks = NULL;
+      int i;
+      int got = 0;
+      tr_block_index_t * blocks = NULL;
 
-        blocks = tr_new (tr_block_index_t, want*2);
-        tr_peerMgrGetNextRequests (tor, &w->parent, want, blocks, &got, true);
+      blocks = tr_new (tr_block_index_t, want*2);
+      tr_peerMgrGetNextRequests (tor, &w->parent, want, blocks, &got, true);
 
-        w->idle_connections -= MIN (w->idle_connections, got);
-        if (w->retry_tickcount >= FAILURE_RETRY_INTERVAL && got == want)
-            w->retry_tickcount = 0;
+      w->idle_connections -= MIN (w->idle_connections, got);
+      if (w->retry_tickcount >= FAILURE_RETRY_INTERVAL && got == want)
+        w->retry_tickcount = 0;
 
-        for (i=0; i<got; ++i)
+      for (i=0; i<got; ++i)
         {
-            const tr_block_index_t b = blocks[i*2];
-            const tr_block_index_t be = blocks[i*2+1];
-            struct tr_webseed_task * task = tr_new (struct tr_webseed_task, 1);
-            task->webseed = w;
-            task->block = b;
-            task->piece_index = tr_torBlockPiece (tor, b);
-            task->piece_offset = (tor->blockSize * b)
-                                - (tor->info.pieceSize * task->piece_index);
-            task->length = (be - b) * tor->blockSize + tr_torBlockCountBytes (tor, be);
-            task->blocks_done = 0;
-            task->response_code = 0;
-            task->block_size = tor->blockSize;
-            task->content = evbuffer_new ();
-            evbuffer_add_cb (task->content, on_content_changed, task);
-            tr_list_append (&w->tasks, task);
-            task_request_next_chunk (task);
+          const tr_block_index_t b = blocks[i*2];
+          const tr_block_index_t be = blocks[i*2+1];
+          struct tr_webseed_task * task;
+
+          task = tr_new0 (struct tr_webseed_task, 1);
+          task->session = tor->session;
+          task->webseed = w;
+          task->block = b;
+          task->piece_index = tr_torBlockPiece (tor, b);
+          task->piece_offset = (tor->blockSize * b) - (tor->info.pieceSize * task->piece_index);
+          task->length = (be - b) * tor->blockSize + tr_torBlockCountBytes (tor, be);
+          task->blocks_done = 0;
+          task->response_code = 0;
+          task->block_size = tor->blockSize;
+          task->content = evbuffer_new ();
+          evbuffer_add_cb (task->content, on_content_changed, task);
+          tr_list_append (&w->tasks, task);
+          task_request_next_chunk (task);
         }
 
-        tr_free (blocks);
+      tr_free (blocks);
     }
 }
 
@@ -392,67 +373,77 @@ web_response_func (tr_session    * session,
                    size_t          response_byte_count UNUSED,
                    void          * vtask)
 {
-    struct tr_webseed_task * t = vtask;
-    tr_webseed * w = t->webseed;
-    tr_torrent * tor = tr_torrentFindFromId (session, w->torrent_id);
-    const int success = (response_code == 206);
+  tr_webseed * w;
+  tr_torrent * tor;
+  struct tr_webseed_task * t = vtask;
+  const int success = (response_code == 206);
+
+  if (t->dead)
+    {
+      evbuffer_free (t->content);
+      tr_free (t);
+      return;
+    }
 
-    if (tor)
+  w = t->webseed;
+  tor = tr_torrentFindFromId (session, w->torrent_id);
+  if (tor != NULL)
     {
-        /* active_transfers was only increased if the connection was successful */
-        if (t->response_code == 206)
-            --w->active_transfers;
+      /* active_transfers was only increased if the connection was successful */
+      if (t->response_code == 206)
+        --w->active_transfers;
 
-        if (!success)
+      if (!success)
         {
-            const tr_block_index_t blocks_remain = (t->length + tor->blockSize - 1)
+          const tr_block_index_t blocks_remain = (t->length + tor->blockSize - 1)
                                                    / tor->blockSize - t->blocks_done;
 
-            if (blocks_remain)
-                fire_client_got_rejs (tor, w, t->block + t->blocks_done, blocks_remain);
+          if (blocks_remain)
+            fire_client_got_rejs (tor, w, t->block + t->blocks_done, blocks_remain);
 
-            if (t->blocks_done)
-                ++w->idle_connections;
-            else if (++w->consecutive_failures >= MAX_CONSECUTIVE_FAILURES && !w->retry_tickcount)
-                /* now wait a while until retrying to establish a connection */
-                ++w->retry_tickcount;
+          if (t->blocks_done)
+            ++w->idle_connections;
+          else if (++w->consecutive_failures >= MAX_CONSECUTIVE_FAILURES && !w->retry_tickcount)
+            /* now wait a while until retrying to establish a connection */
+            ++w->retry_tickcount;
 
-            tr_list_remove_data (&w->tasks, t);
-            evbuffer_free (t->content);
-            tr_free (t);
+          tr_list_remove_data (&w->tasks, t);
+          evbuffer_free (t->content);
+          tr_free (t);
         }
         else
         {
-            const uint32_t bytes_done = t->blocks_done * tor->blockSize;
-            const uint32_t buf_len = evbuffer_get_length (t->content);
+          const uint32_t bytes_done = t->blocks_done * tor->blockSize;
+          const uint32_t buf_len = evbuffer_get_length (t->content);
 
-            if (bytes_done + buf_len < t->length)
+          if (bytes_done + buf_len < t->length)
             {
-                /* request finished successfully but there's still data missing. that
-                means we've reached the end of a file and need to request the next one */
-                t->response_code = 0;
-                task_request_next_chunk (t);
+              /* request finished successfully but there's still data missing. that
+                 means we've reached the end of a file and need to request the next one */
+              t->response_code = 0;
+              task_request_next_chunk (t);
             }
             else
             {
-                if (buf_len) {
-                    /* on_content_changed () will not write a block if it is smaller than
-                    the torrent's block size, i.e. the torrent's very last block */
-                    tr_cacheWriteBlock (session->cache, tor,
-                                        t->piece_index, t->piece_offset + bytes_done,
-                                        buf_len, t->content);
-
-                    fire_client_got_blocks (tor, t->webseed,
-                                            t->block + t->blocks_done, 1);
+              if (buf_len)
+                {
+                  /* on_content_changed () will not write a block if it is smaller than
+                     the torrent's block size, i.e. the torrent's very last block */
+                  tr_cacheWriteBlock (session->cache, tor,
+                                      t->piece_index, t->piece_offset + bytes_done,
+                                      buf_len, t->content);
+
+                  fire_client_got_blocks (tor, t->webseed,
+                                          t->block + t->blocks_done, 1);
                 }
 
-                ++w->idle_connections;
+              ++w->idle_connections;
 
-                tr_list_remove_data (&w->tasks, t);
-                evbuffer_free (t->content);
-                tr_free (t);
+              tr_list_remove_data (&w->tasks, t);
+              evbuffer_free (t->content);
+              tr_free (t);
 
-                on_idle (w);
+              on_idle (w);
             }
         }
     }
@@ -461,129 +452,172 @@ web_response_func (tr_session    * session,
 static struct evbuffer *
 make_url (tr_webseed * w, const tr_file * file)
 {
-    struct evbuffer * buf = evbuffer_new ();
+  struct evbuffer * buf = evbuffer_new ();
 
-    evbuffer_add (buf, w->base_url, w->base_url_len);
+  evbuffer_add (buf, w->base_url, w->base_url_len);
 
-    /* if url ends with a '/', add the torrent name */
-    if (w->base_url[w->base_url_len - 1] == '/' && file->name)
-        tr_http_escape (buf, file->name, strlen (file->name), false);
+  /* if url ends with a '/', add the torrent name */
+  if (w->base_url[w->base_url_len - 1] == '/' && file->name)
+    tr_http_escape (buf, file->name, strlen (file->name), false);
 
-    return buf;
+  return buf;
 }
 
 static void
 task_request_next_chunk (struct tr_webseed_task * t)
 {
-    tr_webseed * w = t->webseed;
-    tr_torrent * tor = tr_torrentFindFromId (w->session, w->torrent_id);
-    if (tor != NULL)
+  tr_webseed * w = t->webseed;
+  tr_torrent * tor = tr_torrentFindFromId (w->session, w->torrent_id);
+  if (tor != NULL)
     {
-        char range[64];
-        char ** urls = t->webseed->file_urls;
-
-        const tr_info * inf = tr_torrentInfo (tor);
-        const uint64_t remain = t->length - t->blocks_done * tor->blockSize
-                                - evbuffer_get_length (t->content);
-
-        const uint64_t total_offset = tr_pieceOffset (tor, t->piece_index,
-                                                           t->piece_offset,
-                                                           t->length - remain);
-        const tr_piece_index_t step_piece = total_offset / inf->pieceSize;
-        const uint64_t step_piece_offset
-                               = total_offset - (inf->pieceSize * step_piece);
-
-        tr_file_index_t file_index;
-        const tr_file * file;
-        uint64_t file_offset;
-        uint64_t this_pass;
-
-        tr_ioFindFileLocation (tor, step_piece, step_piece_offset,
-                                    &file_index, &file_offset);
-        file = &inf->files[file_index];
-        this_pass = MIN (remain, file->length - file_offset);
-
-        if (!urls[file_index])
-            urls[file_index] = evbuffer_free_to_str (make_url (t->webseed, file));
-
-        tr_snprintf (range, sizeof range, "%"PRIu64"-%"PRIu64,
-                     file_offset, file_offset + this_pass - 1);
-        t->web_task = tr_webRunWithBuffer (w->session, urls[file_index],
-                                           range, NULL, web_response_func, t, t->content);
+      char range[64];
+      char ** urls = t->webseed->file_urls;
+
+      const tr_info * inf = tr_torrentInfo (tor);
+      const uint64_t remain = t->length - t->blocks_done * tor->blockSize
+                            - evbuffer_get_length (t->content);
+
+      const uint64_t total_offset = tr_pieceOffset (tor, t->piece_index,
+                                                         t->piece_offset,
+                                                         t->length - remain);
+      const tr_piece_index_t step_piece = total_offset / inf->pieceSize;
+      const uint64_t step_piece_offset = total_offset - (inf->pieceSize * step_piece);
+
+      tr_file_index_t file_index;
+      const tr_file * file;
+      uint64_t file_offset;
+      uint64_t this_pass;
+
+      tr_ioFindFileLocation (tor, step_piece, step_piece_offset,
+                             &file_index, &file_offset);
+      file = &inf->files[file_index];
+      this_pass = MIN (remain, file->length - file_offset);
+
+      if (!urls[file_index])
+        urls[file_index] = evbuffer_free_to_str (make_url (t->webseed, file));
+
+      tr_snprintf (range, sizeof range, "%"PRIu64"-%"PRIu64,
+                   file_offset, file_offset + this_pass - 1);
+      t->web_task = tr_webRunWithBuffer (w->session, urls[file_index],
+                                         range, NULL, web_response_func, t, t->content);
     }
 }
 
-bool
-tr_webseedGetSpeed_Bps (const tr_webseed * w,
-                        uint64_t           now,
-                        unsigned int     * setme_Bps)
-{
-    const bool is_active = webseed_has_tasks (w);
-    *setme_Bps = is_active ? tr_bandwidthGetPieceSpeed_Bps (&w->bandwidth, now, TR_DOWN) : 0;
-    return is_active;
-}
+/***
+****
+***/
 
-bool
-tr_webseedIsActive (const tr_webseed * w)
+static void
+webseed_timer_func (evutil_socket_t foo UNUSED, short bar UNUSED, void * vw)
 {
-    unsigned int Bps = 0;
-    return tr_webseedGetSpeed_Bps (w, tr_time_msec (), &Bps) && (Bps > 0);
+  tr_webseed * w = vw;
+
+  if (w->retry_tickcount)
+    ++w->retry_tickcount;
+
+  on_idle (w);
+
+  tr_timerAddMsec (w->timer, TR_IDLE_TIMER_MSEC);
 }
 
 /***
-****
+****  tr_peer virtual functions
 ***/
 
+static bool
+webseed_is_transferring_pieces (const tr_peer * peer,
+                                uint64_t        now,
+                                tr_direction    direction,
+                                unsigned int  * setme_Bps)
+{
+  unsigned int Bps = 0;
+  bool is_active = false;
+
+  if (direction == TR_DOWN)
+    {
+      const tr_webseed * w = (const tr_webseed *) peer;
+      is_active = w->tasks != NULL;
+      Bps = tr_bandwidthGetPieceSpeed_Bps (&w->bandwidth, now, direction);
+    }
+
+  if (setme_Bps != NULL)
+    *setme_Bps = Bps;
+
+  return is_active;
+}
+
 static void
-webseed_timer_func (evutil_socket_t foo UNUSED, short bar UNUSED, void * vw)
+webseed_destruct (tr_peer * peer)
 {
-    tr_webseed * w = vw;
-    if (w->retry_tickcount)
-        ++w->retry_tickcount;
-    on_idle (w);
-    tr_timerAddMsec (w->timer, TR_IDLE_TIMER_MSEC);
+  tr_list * l;
+  tr_webseed * w = (tr_webseed *) peer;
+
+  /* flag all the pending tasks as dead */
+  for (l=w->tasks; l!=NULL; l=l->next)
+    {
+      struct tr_webseed_task * task = l->data;
+      task->dead = true;
+    }
+  tr_list_free (&w->tasks, NULL);
+
+  /* if we have an array of file URLs, free it */
+  if (w->file_urls != NULL)
+    {
+      tr_file_index_t i;
+      tr_torrent * tor = tr_torrentFindFromId (w->session, w->torrent_id);
+      const tr_info * inf = tr_torrentInfo (tor);
+
+      for (i=0; i<inf->fileCount; ++i)
+        tr_free (w->file_urls[i]);
+      tr_free (w->file_urls);
+    }
+
+  /* webseed destruct */
+  event_free (w->timer);
+  tr_bandwidthDestruct (&w->bandwidth);
+  tr_free (w->base_url);
+
+  /* parent class destruct */
+  tr_peerDestruct (&w->parent);
 }
 
+static const struct tr_peer_virtual_funcs my_funcs =
+{
+  .destruct = webseed_destruct,
+  .is_transferring_pieces = webseed_is_transferring_pieces
+};
+
+/***
+****
+***/
+
 tr_webseed*
 tr_webseedNew (struct tr_torrent  * tor,
                const char         * url,
                tr_peer_callback   * callback,
                void               * callback_data)
 {
-    tr_webseed * w = tr_new0 (tr_webseed, 1);
-    tr_peer * peer = &w->parent;
-    const tr_info * inf = tr_torrentInfo (tor);
-
-    /* construct parent class */
-    tr_peerConstruct (peer);
-    peer->peerIsChoked = true;
-    peer->clientIsInterested = !tr_torrentIsSeed (tor);
-    peer->client = TR_KEY_webseeds;
-    tr_bitfieldSetHasAll (&peer->have);
-    tr_peerUpdateProgress (tor, peer);
-
-    w->torrent_id = tr_torrentId (tor);
-    w->session = tor->session;
-    w->base_url_len = strlen (url);
-    w->base_url = tr_strndup (url, w->base_url_len);
-    w->callback = callback;
-    w->callback_data = callback_data;
-    w->file_urls = tr_new0 (char *, inf->fileCount);
-    //tr_rcConstruct (&w->download_rate);
-    tr_bandwidthConstruct (&w->bandwidth, tor->session, &tor->bandwidth);
-    w->timer = evtimer_new (w->session->event_base, webseed_timer_func, w);
-    tr_timerAddMsec (w->timer, TR_IDLE_TIMER_MSEC);
-    return w;
-}
-
-void
-tr_webseedFree (tr_webseed * w)
-{
-    if (w)
-    {
-        if (webseed_has_tasks (w))
-            w->is_stopping = true;
-        else
-            webseed_free (w);
-    }
+  tr_webseed * w = tr_new0 (tr_webseed, 1);
+  tr_peer * peer = &w->parent;
+  const tr_info * inf = tr_torrentInfo (tor);
+
+  /* construct parent class */
+  tr_peerConstruct (peer, tor);
+  peer->client = TR_KEY_webseeds;
+  peer->funcs = &my_funcs;
+  tr_bitfieldSetHasAll (&peer->have);
+  tr_peerUpdateProgress (tor, peer);
+
+  w->torrent_id = tr_torrentId (tor);
+  w->session = tor->session;
+  w->base_url_len = strlen (url);
+  w->base_url = tr_strndup (url, w->base_url_len);
+  w->callback = callback;
+  w->callback_data = callback_data;
+  w->file_urls = tr_new0 (char *, inf->fileCount);
+  //tr_rcConstruct (&w->download_rate);
+  tr_bandwidthConstruct (&w->bandwidth, tor->session, &tor->bandwidth);
+  w->timer = evtimer_new (w->session->event_base, webseed_timer_func, w);
+  tr_timerAddMsec (w->timer, TR_IDLE_TIMER_MSEC);
+  return w;
 }
index 47485da967a535f0d93053cf8deb8b7cefc36c34..9099fb64fcdc8626b49e3e44478a25774e646ad9 100644 (file)
@@ -26,15 +26,4 @@ tr_webseed* tr_webseedNew (struct tr_torrent * torrent,
                            tr_peer_callback  * callback,
                            void              * callback_data);
 
-void        tr_webseedFree (tr_webseed *);
-
-/** @return true if a request is being processed, or false if idle */
-bool        tr_webseedGetSpeed_Bps (const tr_webseed * w,
-                                    uint64_t           now,
-                                    unsigned int     * setme_Bps);
-
-/** @return true if a request is being processed, or false if idle */
-bool        tr_webseedIsActive (const tr_webseed * w);
-
-
 #endif