return true;
}
-void
+char *
tr_clientForId (char * buf, size_t buflen, const void * id_in)
{
const uint8_t * id = id_in;
*buf = '\0';
if (!id)
- return;
+ return buf;
/* Azureus-style */
if (id[0] == '-' && id[7] == '-')
}
if (*buf)
- return;
+ return buf;
}
/* uTorrent will replace the trailing dash with an extra digit for longer version numbers */
}
if (*buf)
- return;
+ return buf;
}
/* Mainline */
{
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)");
if (name)
{
tr_snprintf (buf, buflen, "%s %d.%d.%d", name, a, b, c);
- return;
+ return buf;
}
}
}
*walk = '\0';
tr_strlcpy (buf, out, buflen);
}
+
+ return buf;
}
* @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
* @{
*/
+struct tr_peer;
+struct tr_swarm;
+
enum
{
/* this is the maximum size of a block request.
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
{
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;
/* 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;
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 *);
tr_port port;
int socket;
- struct UTPSocket *utp_socket;
+ struct UTPSocket * utp_socket;
int refCount;
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);
* for banned peers.
*
* @see tr_peer
- * @see tr_peermsgs
+ * @see tr_peerMsgs
*/
struct peer_atom
{
{
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;
} \
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;
+}
+
/**
***
**/
|| 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)
{
{
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));
int peer_i;
uint16_t r = 0;
- for (peer_i=0; peer_i<peer_count; ++peer_i)
- if (tr_bitfieldHas (&peers[peer_i]->have, piece_i))
- ++r;
+ for (peer_i=0; peer_i<n; ++peer_i)
+ {
+ tr_peer * peer = tr_ptrArrayNth (&s->peers, peer_i);
+ if (tr_bitfieldHas (&peer->have, piece_i))
+ ++r;
+ }
s->pieceReplication[piece_i] = r;
}
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);
const tr_info * inf = &tor->info;
/* clear the array */
- tr_ptrArrayDestruct (&s->webseeds, (PtrArrayForeachFunc)tr_webseedFree);
+ tr_ptrArrayDestruct (&s->webseeds, (PtrArrayForeachFunc)tr_peerFree);
s->webseeds = TR_PTR_ARRAY_INIT;
/* repopulate it */
- for (i = 0; i < inf->webseedCount; ++i)
+ for (i=0; i<inf->webseedCount; ++i)
{
tr_webseed * w = tr_webseedNew (tor, inf->webseeds[i], peerCallbackFunc, s);
tr_ptrArrayAppend (&s->webseeds, w);
}
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);
}
/***
}
static int
-countActiveWebseeds (const tr_swarm * s)
+countActiveWebseeds (tr_swarm * s)
{
+ int i;
int activeCount = 0;
- const tr_webseed ** w = (const tr_webseed **) tr_ptrArrayBase (&s->webseeds);
- const tr_webseed ** const wend = w + tr_ptrArraySize (&s->webseeds);
+ const int n = tr_ptrArraySize (&s->webseeds);
+ const uint64_t now = tr_time_msec ();
- for (; w!=wend; ++w)
- if (tr_webseedIsActive (*w))
+ for (i=0; i<n; ++i)
+ if (tr_peerIsTransferringPieces (tr_ptrArrayNth(&s->webseeds,i), now, TR_DOWN, NULL))
++activeCount;
return activeCount;
}
else if (!s->endgame) /* only recalculate when endgame first begins */
{
+ int i;
int numDownloading = 0;
- const tr_peer ** p = (const tr_peer **) tr_ptrArrayBase (&s->peers);
- const tr_peer ** const pend = p + tr_ptrArraySize (&s->peers);
+ const int n = tr_ptrArraySize (&s->peers);
/* add the active bittorrent peers... */
- for (; p!=pend; ++p)
- if ((*p)->pendingReqsToPeer > 0)
- ++numDownloading;
+ for (i=0; i<n; ++i)
+ {
+ const tr_peer * p = tr_ptrArrayNth (&s->peers, i);
+ if (p->pendingReqsToPeer > 0)
+ ++numDownloading;
+ }
/* add the active webseeds... */
numDownloading += countActiveWebseeds (s);
/* 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 */
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
{
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);
}
}
{
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);
void
tr_peerMgrPieceCompleted (tr_torrent * tor, tr_piece_index_t p)
{
+ int i;
bool pieceCameFromPeers = false;
tr_swarm * const s = tor->swarm;
- const tr_peer ** peer = (const tr_peer **) tr_ptrArrayBase (&s->peers);
- const tr_peer ** const pend = peer + tr_ptrArraySize (&s->peers);
+ const int n = tr_ptrArraySize (&s->peers);
/* walk through our peers */
- for ( ; peer!=pend; ++peer)
+ for (i=0; i<n; ++i)
{
+ tr_peer * peer = tr_ptrArrayNth (&s->peers, i);
+
/* notify the peer that we now have this piece */
- tr_peerMsgsHave ((*peer)->msgs, p);
+ tr_peerMsgsHave (PEER_MSGS(peer), p);
if (!pieceCameFromPeers)
- pieceCameFromPeers = tr_bitfieldHas (&(*peer)->blame, p);
+ pieceCameFromPeers = tr_bitfieldHas (&peer->blame, p);
}
if (pieceCameFromPeers) /* webseed downloads don't belong in announce totals */
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,
}
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;
}
/* 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... */
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 */
int * setmePeersFrom)
{
int i;
- int size;
+ int n;
tr_swarm * s;
- const tr_peer ** peers;
assert (tr_isTorrent (tor));
*setmeWebseedsSendingToUs = 0;
s = tor->swarm;
- size = tr_ptrArraySize (&s->peers);
- peers = (const tr_peer **) tr_ptrArrayBase (&s->peers);
+ n = tr_ptrArraySize (&s->peers);
for (i=0; i<TR_PEER_FROM__MAX; ++i)
setmePeersFrom[i] = 0;
- for (i=0; i<size; ++i)
+ for (i=0; i<n; ++i)
{
- const tr_peer * peer = peers[i];
+ tr_peer * peer = tr_ptrArrayNth (&s->peers, i);
+ tr_peerMsgs * msgs = PEER_MSGS (peer);
const struct peer_atom * atom = peer->atom;
- if (peer->io == NULL) /* not connected */
- continue;
+ assert (msgs != NULL);
++*setmePeersConnected;
++setmePeersFrom[atom->fromFirst];
- if (clientIsDownloadingFrom (tor, peer))
+ if (clientIsDownloadingFrom (tor, msgs))
++*setmePeersSendingToUs;
- if (clientIsUploadingTo (peer))
+ if (clientIsUploadingTo (msgs))
++*setmePeersGettingFromUs;
}
tr_peerMgrWebSpeeds_KBps (const tr_torrent * tor)
{
unsigned int i;
- unsigned int webseedCount;
- const tr_swarm * s;
- const tr_webseed ** webseeds;
+ tr_swarm * s;
+ unsigned int n;
double * ret = NULL;
const uint64_t now = tr_time_msec ();
assert (tr_isTorrent (tor));
s = tor->swarm;
- webseedCount = tr_ptrArraySize (&s->webseeds);
- webseeds = (const tr_webseed**) tr_ptrArrayBase (&s->webseeds);
- ret = tr_new0 (double, webseedCount);
+ n = tr_ptrArraySize (&s->webseeds);
+ ret = tr_new0 (double, n);
assert (s->manager != NULL);
- assert (webseedCount == tor->info.webseedCount);
+ assert (n == tor->info.webseedCount);
- for (i=0; i<webseedCount; ++i)
+ for (i=0; i<n; ++i)
{
- unsigned int Bps;
- if (tr_webseedGetSpeed_Bps (webseeds[i], now, &Bps))
+ unsigned int Bps = 0;
+ if (tr_peerIsTransferringPieces (tr_ptrArrayNth(&s->webseeds,i), now, TR_DOWN, &Bps))
ret[i] = Bps / (double)tr_speed_K;
else
ret[i] = -1.0;
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)
{
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 ();
assert (tor->swarm->manager != NULL);
s = tor->swarm;
- peers = (const tr_peer**) tr_ptrArrayBase (&s->peers);
+ peers = (tr_peer**) tr_ptrArrayBase (&s->peers);
size = tr_ptrArraySize (&s->peers);
ret = tr_new0 (tr_peer_stat, size);
for (i=0; i<size; ++i)
{
char * pch;
- const tr_peer * peer = peers[i];
+ tr_peer * peer = peers[i];
+ tr_peerMsgs * msgs = PEER_MSGS (peer);
const struct peer_atom * atom = peer->atom;
tr_peer_stat * stat = ret + i;
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);
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';
assert (tr_torrentIsLocked (tor));
for (i=0; i<peerCount; ++i)
- {
- const tr_peer * peer = tr_ptrArrayNth (&s->peers, i);
- tr_peerMsgsSetInterested (peer->msgs, false);
- }
+ tr_peerMsgsSetInterested (tr_ptrArrayNth (&s->peers, i), false);
}
/* does this peer have any pieces that we want? */
if (!isPeerInteresting (s->tor, piece_is_interesting, peer))
{
- tr_peerMsgsSetInterested (peer->msgs, false);
+ tr_peerMsgsSetInterested (PEER_MSGS(peer), false);
}
else
{
qsort (rechoke, rechoke_count, sizeof (struct tr_rechoke_info), compare_rechoke_info);
s->interestedCount = MIN (maxPeers, rechoke_count);
for (i=0; i<rechoke_count; ++i)
- tr_peerMsgsSetInterested (rechoke[i].peer->msgs, i<s->interestedCount);
+ tr_peerMsgsSetInterested (PEER_MSGS(rechoke[i].peer), i<s->interestedCount);
/* cleanup */
tr_free (rechoke);
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
}
/* 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. */
for (i=0, size=0; i<peerCount; ++i)
{
tr_peer * peer = peers[i];
+ tr_peerMsgs * msgs = PEER_MSGS (peer);
+
struct peer_atom * atom = peer->atom;
if (peerIsSeed (peer)) /* choke seeds and partial seeds */
{
- tr_peerMsgsSetChoke (peer->msgs, true);
+ tr_peerMsgsSetChoke (PEER_MSGS(peer), true);
}
else if (chokeAll) /* choke everyone if we're not uploading */
{
- tr_peerMsgsSetChoke (peer->msgs, true);
+ tr_peerMsgsSetChoke (PEER_MSGS(peer), true);
}
- else if (peer != s->optimistic)
+ else if (msgs != s->optimistic)
{
struct ChokeData * n = &choke[size++];
- n->peer = peer;
- n->isInterested = peer->peerIsInterested;
- n->wasChoked = peer->peerIsChoked;
+ n->msgs = msgs;
+ n->isInterested = tr_peerMsgsIsPeerInterested (msgs);
+ n->wasChoked = tr_peerMsgsIsPeerChoked (msgs);
n->rate = getRate (s->tor, atom, now);
n->salt = tr_cryptoWeakRandInt (INT_MAX);
n->isChoked = true;
{
if (choke[i].isInterested)
{
- const tr_peer * peer = choke[i].peer;
+ const tr_peerMsgs * msgs = choke[i].msgs;
int x = 1, y;
- if (isNew (peer)) x *= 3;
+ if (isNew (msgs)) x *= 3;
for (y=0; y<x; ++y)
tr_ptrArrayAppend (&randPool, &choke[i]);
}
{
c = tr_ptrArrayNth (&randPool, tr_cryptoWeakRandInt (n));
c->isChoked = false;
- s->optimistic = c->peer;
+ s->optimistic = c->msgs;
s->optimisticUnchokeTimeScaler = OPTIMISTIC_UNCHOKE_MULTIPLIER;
}
}
for (i=0; i<size; ++i)
- tr_peerMsgsSetChoke (choke[i].peer->msgs, choke[i].isChoked);
+ tr_peerMsgsSetChoke (choke[i].msgs, choke[i].isChoked);
/* cleanup */
tr_free (choke);
tr_decrReplicationFromBitfield (s, &peer->have);
assert (removed == peer);
- peerDelete (s, removed);
+ tr_peerFree (removed);
}
static void
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);
}
tr_swarm * s = tor->swarm;
for (j=0; j<tr_ptrArraySize (&s->peers); ++j)
- {
- tr_peer * peer = tr_ptrArrayNth (&s->peers, j);
- tr_peerMsgsPulse (peer->msgs);
- }
+ tr_peerMsgsPulse (tr_ptrArrayNth (&s->peers, j));
}
}
}
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);
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
}
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
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);
}
/**
* 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 */
};
/**
* @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;
};
/**
**/
static inline tr_session*
-getSession (struct tr_peermsgs * msgs)
+getSession (struct tr_peerMsgs * msgs)
{
- return msgs->torrent->session;
+ return msgs->torrent->session;
}
/**
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);
}
}
**/
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);
}
/**
**/
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);
}
}
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);
**/
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;
}
}
**/
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);
}
/**
**/
static bool
-reqIsValid (const tr_peermsgs * peer,
+reqIsValid (const tr_peerMsgs * peer,
uint32_t index,
uint32_t offset,
uint32_t length)
}
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);*/
**/
static void
-sendLtepHandshake (tr_peermsgs * msgs)
+sendLtepHandshake (tr_peerMsgs * msgs)
{
tr_variant val;
bool allow_pex;
}
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;
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))
/* 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);
}
}
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))
{
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))
{
}
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;
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))
}
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);
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))))
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);
}
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");
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);
}
static void
-updatePeerProgress (tr_peermsgs * msgs)
+updatePeerProgress (tr_peerMsgs * msgs)
{
- tr_peerUpdateProgress (msgs->torrent, msgs->peer);
+ tr_peerUpdateProgress (msgs->torrent, &msgs->peer);
- /*updateFastSet (msgs);*/
- updateInterest (msgs);
+ /*updateFastSet (msgs);*/
+ updateInterest (msgs);
}
static void
-prefetchPieces (tr_peermsgs *msgs)
+prefetchPieces (tr_peerMsgs *msgs)
{
- int i;
+ int i;
- if (!getSession (msgs)->isPrefetchEnabled)
- return;
+ if (!getSession (msgs)->isPrefetchEnabled)
+ return;
- for (i=msgs->prefetchCount; i<msgs->peer->pendingReqsToClient && i<PREFETCH_SIZE; ++i)
+ for (i=msgs->prefetchCount; i<msgs->peer.pendingReqsToClient && i<PREFETCH_SIZE; ++i)
{
- const struct peer_request * req = msgs->peerAskedFor + i;
- if (requestIsValid (msgs, req))
+ const struct peer_request * req = msgs->peerAskedFor + i;
+ if (requestIsValid (msgs, req))
{
- tr_cachePrefetchBlock (getSession (msgs)->cache, msgs->torrent, req->index, req->offset, req->length);
- ++msgs->prefetchCount;
+ tr_cachePrefetchBlock (getSession (msgs)->cache, msgs->torrent, req->index, req->offset, req->length);
+ ++msgs->prefetchCount;
}
}
}
static void
-peerMadeRequest (tr_peermsgs * msgs, const struct peer_request * req)
+peerMadeRequest (tr_peerMsgs * msgs, const struct peer_request * req)
{
- const bool fext = tr_peerIoSupportsFEXT (msgs->peer->io);
+ const bool fext = tr_peerIoSupportsFEXT (msgs->io);
const int reqIsValid = requestIsValid (msgs, req);
const int clientHasPiece = reqIsValid && tr_cpPieceIsComplete (&msgs->torrent->completion, req->index);
- const int peerIsChoked = msgs->peer->peerIsChoked;
+ const int peerIsChoked = msgs->peer_is_choked;
int allow = false;
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);
}
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)
{
}
}
-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)
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;
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;
}
}
-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;
#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 */
{
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))
}
/* 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);
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;
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;
{
int i;
struct peer_request r;
- tr_peerIoReadUint32 (msgs->peer->io, inbuf, &r.index);
- tr_peerIoReadUint32 (msgs->peer->io, inbuf, &r.offset);
- tr_peerIoReadUint32 (msgs->peer->io, inbuf, &r.length);
- tr_historyAdd (&msgs->peer->cancelsSentToClient, tr_time (), 1);
+ tr_peerIoReadUint32 (msgs->io, inbuf, &r.index);
+ tr_peerIoReadUint32 (msgs->io, inbuf, &r.offset);
+ tr_peerIoReadUint32 (msgs->io, inbuf, &r.length);
+ tr_historyAdd (&msgs->peer.cancelsSentToClient, tr_time (), 1);
dbgmsg (msgs, "got a Cancel %u:%u->%u", r.index, r.offset, r.length);
- for (i=0; i<msgs->peer->pendingReqsToClient; ++i) {
+ for (i=0; i<msgs->peer.pendingReqsToClient; ++i) {
const struct peer_request * req = msgs->peerAskedFor + i;
if ((req->index == r.index) && (req->offset == r.offset) && (req->length == r.length))
break;
}
- if (i < msgs->peer->pendingReqsToClient)
+ if (i < msgs->peer.pendingReqsToClient)
tr_removeElementFromArray (msgs->peerAskedFor, i, sizeof (struct peer_request),
- msgs->peer->pendingReqsToClient--);
+ msgs->peer.pendingReqsToClient--);
break;
}
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 {
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 {
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 {
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 {
{
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 {
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;
}
/* 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)
{
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;
}
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;
}
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);
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);
}
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;
**/
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;
}
/* 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));
}
static void
-updateMetadataRequests (tr_peermsgs * msgs, time_t now)
+updateMetadataRequests (tr_peerMsgs * msgs, time_t now)
{
int piece;
}
static void
-updateBlockRequests (tr_peermsgs * msgs)
+updateBlockRequests (tr_peerMsgs * msgs)
{
if (tr_torrentIsPieceTransferAllowed (msgs->torrent, TR_PEER_TO_CLIENT)
&& (msgs->desiredRequestCount > 0)
- && (msgs->peer->pendingReqsToPeer <= (msgs->desiredRequestCount * 0.66)))
+ && (msgs->peer.pendingReqsToPeer <= (msgs->desiredRequestCount * 0.66)))
{
int i;
int n;
- const int numwant = msgs->desiredRequestCount - msgs->peer->pendingReqsToPeer;
- tr_block_index_t * blocks = tr_new (tr_block_index_t, numwant);
+ tr_block_index_t * blocks;
+ const int numwant = msgs->desiredRequestCount - msgs->peer.pendingReqsToPeer;
- tr_peerMgrGetNextRequests (msgs->torrent, msgs->peer, numwant, blocks, &n, false);
+ assert (tr_peerMsgsIsClientInterested (msgs));
+ assert (!tr_peerMsgsIsClientChoked (msgs));
+
+ blocks = tr_new (tr_block_index_t, numwant);
+ tr_peerMgrGetNextRequests (msgs->torrent, &msgs->peer, numwant, blocks, &n, false);
for (i=0; i<n; ++i)
{
}
static size_t
-fillOutputBuffer (tr_peermsgs * msgs, time_t now)
+fillOutputBuffer (tr_peerMsgs * msgs, time_t now)
{
int piece;
size_t bytesWritten = 0;
struct peer_request req;
const bool haveMessages = evbuffer_get_length (msgs->outMessages) != 0;
- const bool fext = tr_peerIoSupportsFEXT (msgs->peer->io);
+ const bool fext = tr_peerIoSupportsFEXT (msgs->io);
/**
*** Protocol messages
{
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;
*** 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;
*** 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;
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);
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);
}
void
-tr_peerMsgsPulse (tr_peermsgs * msgs)
+tr_peerMsgsPulse (tr_peerMsgs * msgs)
{
if (msgs != NULL)
peerPulse (msgs);
}
static void
-sendBitfield (tr_peermsgs * msgs)
+sendBitfield (tr_peerMsgs * msgs)
{
void * bytes;
size_t byte_count = 0;
}
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))
{
static void
-sendPex (tr_peermsgs * msgs)
+sendPex (tr_peerMsgs * msgs)
{
if (msgs->peerSupportsPex && tr_torrentAllowsPex (msgs->torrent))
{
static void
pexPulse (int foo UNUSED, short bar UNUSED, void * vmsgs)
{
- struct tr_peermsgs * msgs = vmsgs;
+ struct tr_peerMsgs * msgs = vmsgs;
sendPex (msgs);
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;
}
*/
#ifndef __TRANSMISSION__
-#error only libtransmission should #include this header.
+ #error only libtransmission should #include this header.
#endif
#ifndef TR_PEER_MSGS_H
struct tr_address;
struct tr_bitfield;
struct tr_peer;
+struct tr_peerIo;
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);
/* @} */
struct tr_webseed_task
{
- struct evbuffer * content;
- struct tr_webseed * webseed;
- tr_block_index_t block;
- tr_piece_index_t piece_index;
- uint32_t piece_offset;
- uint32_t length;
- tr_block_index_t blocks_done;
- uint32_t block_size;
- struct tr_web_task * web_task;
- long response_code;
+ bool dead;
+ struct evbuffer * content;
+ struct tr_webseed * webseed;
+ tr_session * session;
+ tr_block_index_t block;
+ tr_piece_index_t piece_index;
+ uint32_t piece_offset;
+ uint32_t length;
+ tr_block_index_t blocks_done;
+ uint32_t block_size;
+ struct tr_web_task * web_task;
+ long response_code;
};
struct tr_webseed
{
- tr_peer parent;
- tr_bandwidth bandwidth;
- tr_session * session;
- tr_peer_callback * callback;
- void * callback_data;
- tr_list * tasks;
- struct event * timer;
- char * base_url;
- size_t base_url_len;
- int torrent_id;
- bool is_stopping;
- int consecutive_failures;
- int retry_tickcount;
- int retry_challenge;
- int idle_connections;
- int active_transfers;
- char ** file_urls;
+ tr_peer parent;
+ tr_bandwidth bandwidth;
+ tr_session * session;
+ tr_peer_callback * callback;
+ void * callback_data;
+ tr_list * tasks;
+ struct event * timer;
+ char * base_url;
+ size_t base_url_len;
+ int torrent_id;
+ int consecutive_failures;
+ int retry_tickcount;
+ int retry_challenge;
+ int idle_connections;
+ int active_transfers;
+ char ** file_urls;
};
enum
{
- TR_IDLE_TIMER_MSEC = 2000,
+ TR_IDLE_TIMER_MSEC = 2000,
- FAILURE_RETRY_INTERVAL = 150,
+ FAILURE_RETRY_INTERVAL = 150,
- MAX_CONSECUTIVE_FAILURES = 5,
+ MAX_CONSECUTIVE_FAILURES = 5,
- MAX_WEBSEED_CONNECTIONS = 4
+ MAX_WEBSEED_CONNECTIONS = 4
};
-static void
-webseed_free (struct tr_webseed * w)
-{
- tr_torrent * tor = tr_torrentFindFromId (w->session, w->torrent_id);
- const tr_info * inf = tr_torrentInfo (tor);
- tr_file_index_t i;
-
- /* if we have an array of file URLs, free it */
- if (w->file_urls != NULL) {
- for (i=0; i<inf->fileCount; ++i)
- tr_free (w->file_urls[i]);
- tr_free (w->file_urls);
- }
-
- /* webseed destruct */
- event_free (w->timer);
- tr_bandwidthDestruct (&w->bandwidth);
- tr_free (w->base_url);
-
- /* parent class destruct */
- tr_peerDestruct (tor, &w->parent);
-
- tr_free (w);
-}
-
/***
****
***/
}
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);
}
/***
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);
}
/***
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);
}
/***
const struct evbuffer_cb_info * info,
void * vtask)
{
- uint32_t len;
- const size_t n_added = info->n_added;
- struct tr_webseed_task * task = vtask;
- struct tr_webseed * w = task->webseed;
+ const size_t n_added = info->n_added;
+ struct tr_webseed_task * task = vtask;
+ tr_session * session = task->session;
- if (n_added <= 0)
- return;
+ tr_sessionLock (session);
- if (!w->is_stopping)
+ if (!task->dead && (n_added>0))
{
- tr_bandwidthUsed (&w->bandwidth, TR_DOWN, n_added, true, tr_time_msec ());
- fire_client_got_piece_data (w, n_added);
- }
+ uint32_t len;
+ struct tr_webseed * w = task->webseed;
- len = evbuffer_get_length (buf);
+ tr_bandwidthUsed (&w->bandwidth, TR_DOWN, n_added, true, tr_time_msec ());
+ fire_client_got_piece_data (w, n_added);
+ len = evbuffer_get_length (buf);
- if (!task->response_code)
- {
- tr_webGetTaskInfo (task->web_task, TR_WEB_GET_CODE, &task->response_code);
+ if (!task->response_code)
+ {
+ tr_webGetTaskInfo (task->web_task, TR_WEB_GET_CODE, &task->response_code);
+
+ if (task->response_code == 206)
+ {
+ const char * url;
+ struct connection_succeeded_data * data;
+
+ url = NULL;
+ tr_webGetTaskInfo (task->web_task, TR_WEB_GET_REAL_URL, &url);
+
+ data = tr_new (struct connection_succeeded_data, 1);
+ data->webseed = w;
+ data->real_url = tr_strdup (url);
+ data->piece_index = task->piece_index;
+ data->piece_offset = task->piece_offset + (task->blocks_done * task->block_size) + (len - 1);
+
+ /* processing this uses a tr_torrent pointer,
+ so push the work to the libevent thread... */
+ tr_runInEventThread (w->session, connection_succeeded, data);
+ }
+ }
- if (task->response_code == 206)
+ if ((task->response_code == 206) && (len >= task->block_size))
{
- const char * url;
- struct connection_succeeded_data * data;
-
- url = NULL;
- tr_webGetTaskInfo (task->web_task, TR_WEB_GET_REAL_URL, &url);
-
- data = tr_new (struct connection_succeeded_data, 1);
- data->webseed = w;
- data->real_url = tr_strdup (url);
- data->piece_index = task->piece_index;
- data->piece_offset = task->piece_offset
- + (task->blocks_done * task->block_size)
- + (len - 1);
-
- /* processing this uses a tr_torrent pointer,
- so push the work to the libevent thread... */
- tr_runInEventThread (w->session, connection_succeeded, data);
+ /* once we've got at least one full block, save it */
+
+ struct write_block_data * data;
+ const uint32_t block_size = task->block_size;
+ const tr_block_index_t completed = len / block_size;
+
+ data = tr_new (struct write_block_data, 1);
+ data->webseed = task->webseed;
+ data->piece_index = task->piece_index;
+ data->block_index = task->block + task->blocks_done;
+ data->count = completed;
+ data->block_offset = task->piece_offset + task->blocks_done * block_size;
+ data->content = evbuffer_new ();
+ data->torrent_id = w->torrent_id;
+ data->session = w->session;
+
+ /* we don't use locking on this evbuffer so we must copy out the data
+ that will be needed when writing the block in a different thread */
+ evbuffer_remove_buffer (task->content, data->content,
+ block_size * completed);
+
+ tr_runInEventThread (w->session, write_block_func, data);
+ task->blocks_done += completed;
}
}
- if ((task->response_code == 206) && (len >= task->block_size))
- {
- /* once we've got at least one full block, save it */
-
- struct write_block_data * data;
- const uint32_t block_size = task->block_size;
- const tr_block_index_t completed = len / block_size;
-
- data = tr_new (struct write_block_data, 1);
- data->webseed = task->webseed;
- data->piece_index = task->piece_index;
- data->block_index = task->block + task->blocks_done;
- data->count = completed;
- data->block_offset = task->piece_offset + task->blocks_done * block_size;
- data->content = evbuffer_new ();
-
- /* we don't use locking on this evbuffer so we must copy out the data
- that will be needed when writing the block in a different thread */
- evbuffer_remove_buffer (task->content, data->content,
- block_size * completed);
-
- tr_runInEventThread (w->session, write_block_func, data);
- task->blocks_done += completed;
- }
+ tr_sessionUnlock (session);
}
static void task_request_next_chunk (struct tr_webseed_task * task);
-static bool
-webseed_has_tasks (const tr_webseed * w)
-{
- return w->tasks != NULL;
-}
-
-
static void
on_idle (tr_webseed * w)
{
- tr_torrent * tor = tr_torrentFindFromId (w->session, w->torrent_id);
- int want, running_tasks = tr_list_size (w->tasks);
+ int want;
+ int running_tasks = tr_list_size (w->tasks);
+ tr_torrent * tor = tr_torrentFindFromId (w->session, w->torrent_id);
- if (w->consecutive_failures >= MAX_CONSECUTIVE_FAILURES) {
- want = w->idle_connections;
+ if (w->consecutive_failures >= MAX_CONSECUTIVE_FAILURES)
+ {
+ want = w->idle_connections;
- if (w->retry_tickcount >= FAILURE_RETRY_INTERVAL) {
- /* some time has passed since our connection attempts failed. try again */
- ++want;
- /* if this challenge is fulfilled we will reset consecutive_failures */
- w->retry_challenge = running_tasks + want;
+ if (w->retry_tickcount >= FAILURE_RETRY_INTERVAL)
+ {
+ /* some time has passed since our connection attempts failed. try again */
+ ++want;
+ /* if this challenge is fulfilled we will reset consecutive_failures */
+ w->retry_challenge = running_tasks + want;
}
}
- else {
- want = MAX_WEBSEED_CONNECTIONS - running_tasks;
- w->retry_challenge = running_tasks + w->idle_connections + 1;
- }
-
- if (w->is_stopping && !webseed_has_tasks (w))
+ else
{
- webseed_free (w);
+ want = MAX_WEBSEED_CONNECTIONS - running_tasks;
+ w->retry_challenge = running_tasks + w->idle_connections + 1;
}
- else if (!w->is_stopping && tor
- && tor->isRunning
- && !tr_torrentIsSeed (tor)
- && want)
+
+ if (tor && tor->isRunning && !tr_torrentIsSeed (tor) && want)
{
- int i;
- int got = 0;
- tr_block_index_t * blocks = NULL;
+ int i;
+ int got = 0;
+ tr_block_index_t * blocks = NULL;
- blocks = tr_new (tr_block_index_t, want*2);
- tr_peerMgrGetNextRequests (tor, &w->parent, want, blocks, &got, true);
+ blocks = tr_new (tr_block_index_t, want*2);
+ tr_peerMgrGetNextRequests (tor, &w->parent, want, blocks, &got, true);
- w->idle_connections -= MIN (w->idle_connections, got);
- if (w->retry_tickcount >= FAILURE_RETRY_INTERVAL && got == want)
- w->retry_tickcount = 0;
+ w->idle_connections -= MIN (w->idle_connections, got);
+ if (w->retry_tickcount >= FAILURE_RETRY_INTERVAL && got == want)
+ w->retry_tickcount = 0;
- for (i=0; i<got; ++i)
+ for (i=0; i<got; ++i)
{
- const tr_block_index_t b = blocks[i*2];
- const tr_block_index_t be = blocks[i*2+1];
- struct tr_webseed_task * task = tr_new (struct tr_webseed_task, 1);
- task->webseed = w;
- task->block = b;
- task->piece_index = tr_torBlockPiece (tor, b);
- task->piece_offset = (tor->blockSize * b)
- - (tor->info.pieceSize * task->piece_index);
- task->length = (be - b) * tor->blockSize + tr_torBlockCountBytes (tor, be);
- task->blocks_done = 0;
- task->response_code = 0;
- task->block_size = tor->blockSize;
- task->content = evbuffer_new ();
- evbuffer_add_cb (task->content, on_content_changed, task);
- tr_list_append (&w->tasks, task);
- task_request_next_chunk (task);
+ const tr_block_index_t b = blocks[i*2];
+ const tr_block_index_t be = blocks[i*2+1];
+ struct tr_webseed_task * task;
+
+ task = tr_new0 (struct tr_webseed_task, 1);
+ task->session = tor->session;
+ task->webseed = w;
+ task->block = b;
+ task->piece_index = tr_torBlockPiece (tor, b);
+ task->piece_offset = (tor->blockSize * b) - (tor->info.pieceSize * task->piece_index);
+ task->length = (be - b) * tor->blockSize + tr_torBlockCountBytes (tor, be);
+ task->blocks_done = 0;
+ task->response_code = 0;
+ task->block_size = tor->blockSize;
+ task->content = evbuffer_new ();
+ evbuffer_add_cb (task->content, on_content_changed, task);
+ tr_list_append (&w->tasks, task);
+ task_request_next_chunk (task);
}
- tr_free (blocks);
+ tr_free (blocks);
}
}
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);
}
}
}
static struct evbuffer *
make_url (tr_webseed * w, const tr_file * file)
{
- struct evbuffer * buf = evbuffer_new ();
+ struct evbuffer * buf = evbuffer_new ();
- evbuffer_add (buf, w->base_url, w->base_url_len);
+ evbuffer_add (buf, w->base_url, w->base_url_len);
- /* if url ends with a '/', add the torrent name */
- if (w->base_url[w->base_url_len - 1] == '/' && file->name)
- tr_http_escape (buf, file->name, strlen (file->name), false);
+ /* if url ends with a '/', add the torrent name */
+ if (w->base_url[w->base_url_len - 1] == '/' && file->name)
+ tr_http_escape (buf, file->name, strlen (file->name), false);
- return buf;
+ return buf;
}
static void
task_request_next_chunk (struct tr_webseed_task * t)
{
- tr_webseed * w = t->webseed;
- tr_torrent * tor = tr_torrentFindFromId (w->session, w->torrent_id);
- if (tor != NULL)
+ tr_webseed * w = t->webseed;
+ tr_torrent * tor = tr_torrentFindFromId (w->session, w->torrent_id);
+ if (tor != NULL)
{
- char range[64];
- char ** urls = t->webseed->file_urls;
-
- const tr_info * inf = tr_torrentInfo (tor);
- const uint64_t remain = t->length - t->blocks_done * tor->blockSize
- - evbuffer_get_length (t->content);
-
- const uint64_t total_offset = tr_pieceOffset (tor, t->piece_index,
- t->piece_offset,
- t->length - remain);
- const tr_piece_index_t step_piece = total_offset / inf->pieceSize;
- const uint64_t step_piece_offset
- = total_offset - (inf->pieceSize * step_piece);
-
- tr_file_index_t file_index;
- const tr_file * file;
- uint64_t file_offset;
- uint64_t this_pass;
-
- tr_ioFindFileLocation (tor, step_piece, step_piece_offset,
- &file_index, &file_offset);
- file = &inf->files[file_index];
- this_pass = MIN (remain, file->length - file_offset);
-
- if (!urls[file_index])
- urls[file_index] = evbuffer_free_to_str (make_url (t->webseed, file));
-
- tr_snprintf (range, sizeof range, "%"PRIu64"-%"PRIu64,
- file_offset, file_offset + this_pass - 1);
- t->web_task = tr_webRunWithBuffer (w->session, urls[file_index],
- range, NULL, web_response_func, t, t->content);
+ char range[64];
+ char ** urls = t->webseed->file_urls;
+
+ const tr_info * inf = tr_torrentInfo (tor);
+ const uint64_t remain = t->length - t->blocks_done * tor->blockSize
+ - evbuffer_get_length (t->content);
+
+ const uint64_t total_offset = tr_pieceOffset (tor, t->piece_index,
+ t->piece_offset,
+ t->length - remain);
+ const tr_piece_index_t step_piece = total_offset / inf->pieceSize;
+ const uint64_t step_piece_offset = total_offset - (inf->pieceSize * step_piece);
+
+ tr_file_index_t file_index;
+ const tr_file * file;
+ uint64_t file_offset;
+ uint64_t this_pass;
+
+ tr_ioFindFileLocation (tor, step_piece, step_piece_offset,
+ &file_index, &file_offset);
+ file = &inf->files[file_index];
+ this_pass = MIN (remain, file->length - file_offset);
+
+ if (!urls[file_index])
+ urls[file_index] = evbuffer_free_to_str (make_url (t->webseed, file));
+
+ tr_snprintf (range, sizeof range, "%"PRIu64"-%"PRIu64,
+ file_offset, file_offset + this_pass - 1);
+ t->web_task = tr_webRunWithBuffer (w->session, urls[file_index],
+ range, NULL, web_response_func, t, t->content);
}
}
-bool
-tr_webseedGetSpeed_Bps (const tr_webseed * w,
- uint64_t now,
- unsigned int * setme_Bps)
-{
- const bool is_active = webseed_has_tasks (w);
- *setme_Bps = is_active ? tr_bandwidthGetPieceSpeed_Bps (&w->bandwidth, now, TR_DOWN) : 0;
- return is_active;
-}
+/***
+****
+***/
-bool
-tr_webseedIsActive (const tr_webseed * w)
+static void
+webseed_timer_func (evutil_socket_t foo UNUSED, short bar UNUSED, void * vw)
{
- unsigned int Bps = 0;
- return tr_webseedGetSpeed_Bps (w, tr_time_msec (), &Bps) && (Bps > 0);
+ tr_webseed * w = vw;
+
+ if (w->retry_tickcount)
+ ++w->retry_tickcount;
+
+ on_idle (w);
+
+ tr_timerAddMsec (w->timer, TR_IDLE_TIMER_MSEC);
}
/***
-****
+**** tr_peer virtual functions
***/
+static bool
+webseed_is_transferring_pieces (const tr_peer * peer,
+ uint64_t now,
+ tr_direction direction,
+ unsigned int * setme_Bps)
+{
+ unsigned int Bps = 0;
+ bool is_active = false;
+
+ if (direction == TR_DOWN)
+ {
+ const tr_webseed * w = (const tr_webseed *) peer;
+ is_active = w->tasks != NULL;
+ Bps = tr_bandwidthGetPieceSpeed_Bps (&w->bandwidth, now, direction);
+ }
+
+ if (setme_Bps != NULL)
+ *setme_Bps = Bps;
+
+ return is_active;
+}
+
static void
-webseed_timer_func (evutil_socket_t foo UNUSED, short bar UNUSED, void * vw)
+webseed_destruct (tr_peer * peer)
{
- tr_webseed * w = vw;
- if (w->retry_tickcount)
- ++w->retry_tickcount;
- on_idle (w);
- tr_timerAddMsec (w->timer, TR_IDLE_TIMER_MSEC);
+ tr_list * l;
+ tr_webseed * w = (tr_webseed *) peer;
+
+ /* flag all the pending tasks as dead */
+ for (l=w->tasks; l!=NULL; l=l->next)
+ {
+ struct tr_webseed_task * task = l->data;
+ task->dead = true;
+ }
+ tr_list_free (&w->tasks, NULL);
+
+ /* if we have an array of file URLs, free it */
+ if (w->file_urls != NULL)
+ {
+ tr_file_index_t i;
+ tr_torrent * tor = tr_torrentFindFromId (w->session, w->torrent_id);
+ const tr_info * inf = tr_torrentInfo (tor);
+
+ for (i=0; i<inf->fileCount; ++i)
+ tr_free (w->file_urls[i]);
+ tr_free (w->file_urls);
+ }
+
+ /* webseed destruct */
+ event_free (w->timer);
+ tr_bandwidthDestruct (&w->bandwidth);
+ tr_free (w->base_url);
+
+ /* parent class destruct */
+ tr_peerDestruct (&w->parent);
}
+static const struct tr_peer_virtual_funcs my_funcs =
+{
+ .destruct = webseed_destruct,
+ .is_transferring_pieces = webseed_is_transferring_pieces
+};
+
+/***
+****
+***/
+
tr_webseed*
tr_webseedNew (struct tr_torrent * tor,
const char * url,
tr_peer_callback * callback,
void * callback_data)
{
- tr_webseed * w = tr_new0 (tr_webseed, 1);
- tr_peer * peer = &w->parent;
- const tr_info * inf = tr_torrentInfo (tor);
-
- /* construct parent class */
- tr_peerConstruct (peer);
- peer->peerIsChoked = true;
- peer->clientIsInterested = !tr_torrentIsSeed (tor);
- peer->client = TR_KEY_webseeds;
- tr_bitfieldSetHasAll (&peer->have);
- tr_peerUpdateProgress (tor, peer);
-
- w->torrent_id = tr_torrentId (tor);
- w->session = tor->session;
- w->base_url_len = strlen (url);
- w->base_url = tr_strndup (url, w->base_url_len);
- w->callback = callback;
- w->callback_data = callback_data;
- w->file_urls = tr_new0 (char *, inf->fileCount);
- //tr_rcConstruct (&w->download_rate);
- tr_bandwidthConstruct (&w->bandwidth, tor->session, &tor->bandwidth);
- w->timer = evtimer_new (w->session->event_base, webseed_timer_func, w);
- tr_timerAddMsec (w->timer, TR_IDLE_TIMER_MSEC);
- return w;
-}
-
-void
-tr_webseedFree (tr_webseed * w)
-{
- if (w)
- {
- if (webseed_has_tasks (w))
- w->is_stopping = true;
- else
- webseed_free (w);
- }
+ tr_webseed * w = tr_new0 (tr_webseed, 1);
+ tr_peer * peer = &w->parent;
+ const tr_info * inf = tr_torrentInfo (tor);
+
+ /* construct parent class */
+ tr_peerConstruct (peer, tor);
+ peer->client = TR_KEY_webseeds;
+ peer->funcs = &my_funcs;
+ tr_bitfieldSetHasAll (&peer->have);
+ tr_peerUpdateProgress (tor, peer);
+
+ w->torrent_id = tr_torrentId (tor);
+ w->session = tor->session;
+ w->base_url_len = strlen (url);
+ w->base_url = tr_strndup (url, w->base_url_len);
+ w->callback = callback;
+ w->callback_data = callback_data;
+ w->file_urls = tr_new0 (char *, inf->fileCount);
+ //tr_rcConstruct (&w->download_rate);
+ tr_bandwidthConstruct (&w->bandwidth, tor->session, &tor->bandwidth);
+ w->timer = evtimer_new (w->session->event_base, webseed_timer_func, w);
+ tr_timerAddMsec (w->timer, TR_IDLE_TIMER_MSEC);
+ return w;
}
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