From: Jordan Lee Date: Mon, 4 Feb 2013 16:23:33 +0000 (+0000) Subject: (libT) make the class hierarchy between tr_peer, tr_peerMsgs, and tr_webseed a little... X-Git-Tag: 2.80~130 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=96691dd0194ffc12e367b4169d7d23d54576c021;p=transmission (libT) make the class hierarchy between tr_peer, tr_peerMsgs, and tr_webseed a little less ad-hoc --- diff --git a/libtransmission/clients.c b/libtransmission/clients.c index 7c2df0a1e..659086d5e 100644 --- a/libtransmission/clients.c +++ b/libtransmission/clients.c @@ -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; } diff --git a/libtransmission/clients.h b/libtransmission/clients.h index dc18d5cab..c260ef1c2 100644 --- a/libtransmission/clients.h +++ b/libtransmission/clients.h @@ -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 diff --git a/libtransmission/peer-common.h b/libtransmission/peer-common.h index f9a7adef0..0598fae52 100644 --- a/libtransmission/peer-common.h +++ b/libtransmission/peer-common.h @@ -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 *); diff --git a/libtransmission/peer-io.h b/libtransmission/peer-io.h index 82b30ca3e..a592ed1f4 100644 --- a/libtransmission/peer-io.h +++ b/libtransmission/peer-io.h @@ -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); diff --git a/libtransmission/peer-mgr.c b/libtransmission/peer-mgr.c index 3da034b4f..82bdad3be 100644 --- a/libtransmission/peer-mgr.c +++ b/libtransmission/peer-mgr.c @@ -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_ihave, piece_i)) - ++r; + for (peer_i=0; peer_ipeers, 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; iwebseedCount; ++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; iwebseeds,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; ipeers, 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; ipeers, 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; ipeers, 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; iwebseeds,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; iatom; 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; ipeers, 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; imsgs, iinterestedCount); + tr_peerMsgsSetInterested (PEER_MSGS(rechoke[i].peer), iinterestedCount); /* 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; iatom; 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; yisChoked = 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; imsgs, 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; jpeers); ++j) - { - tr_peer * peer = tr_ptrArrayNth (&s->peers, j); - tr_peerMsgsPulse (peer->msgs); - } + tr_peerMsgsPulse (tr_ptrArrayNth (&s->peers, j)); } } diff --git a/libtransmission/peer-mgr.h b/libtransmission/peer-mgr.h index 85aa67ab7..ca65948e1 100644 --- a/libtransmission/peer-mgr.h +++ b/libtransmission/peer-mgr.h @@ -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); diff --git a/libtransmission/peer-msgs.c b/libtransmission/peer-msgs.c index fcef213e6..8b150b32c 100644 --- a/libtransmission/peer-msgs.c +++ b/libtransmission/peer-msgs.c @@ -42,71 +42,73 @@ 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, <ep_msgid); + tr_peerIoReadUint8 (msgs->io, inbuf, <ep_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; ipeer->pendingReqsToClient && iprefetchCount; ipeer.pendingReqsToClient && ipeerAskedFor + 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; ipeer->pendingReqsToClient; ++i) { + for (i=0; ipeer.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; ioutMessages) != 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; } diff --git a/libtransmission/peer-msgs.h b/libtransmission/peer-msgs.h index 9955c4c2e..459166bba 100644 --- a/libtransmission/peer-msgs.h +++ b/libtransmission/peer-msgs.h @@ -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); /* @} */ diff --git a/libtransmission/webseed.c b/libtransmission/webseed.c index 1c4302452..f3ed278e2 100644 --- a/libtransmission/webseed.c +++ b/libtransmission/webseed.c @@ -29,75 +29,51 @@ 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; ifileCount; ++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; iwebseed = 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; ifileCount; ++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; } diff --git a/libtransmission/webseed.h b/libtransmission/webseed.h index 47485da96..9099fb64f 100644 --- a/libtransmission/webseed.h +++ b/libtransmission/webseed.h @@ -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