mirror of
https://github.com/transmission/transmission
synced 2025-02-23 14:40:43 +00:00
refactor: remove varargs from libtransmission (#2876)
* refactor: do not use va_arg in peer-msgs.cc * refactor: do not use va_arg in platform.cc * build: enable cert-dcl50-cpp clang-tidy warning * refactor: use some tr_pathbuf where sensible
This commit is contained in:
parent
738431169c
commit
a71f0c762d
4 changed files with 239 additions and 277 deletions
|
@ -7,7 +7,6 @@
|
|||
#include <ctype.h> /* isxdigit() */
|
||||
#include <errno.h>
|
||||
#include <limits.h> /* INT_MAX */
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <giomm.h> /* g_file_trash() */
|
||||
#include <glibmm/i18n.h>
|
||||
|
|
|
@ -7,7 +7,6 @@ Checks: >
|
|||
-bugprone-implicit-widening-of-multiplication-result,
|
||||
-bugprone-narrowing-conversions,
|
||||
cert-*,
|
||||
-cert-dcl50-cpp,
|
||||
-cert-err33-c,
|
||||
-cert-err34-c,
|
||||
-cert-err58-cpp,
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <cerrno>
|
||||
#include <cstdarg>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <memory> // std::unique_ptr
|
||||
|
@ -658,30 +657,25 @@ tr_peerMsgs* tr_peerMsgsNew(tr_torrent* torrent, peer_atom* atom, tr_peerIo* io,
|
|||
***
|
||||
**/
|
||||
|
||||
static void myDebug(char const* file, int line, tr_log_level level, tr_peerMsgsImpl const* msgs, char const* fmt, ...)
|
||||
{
|
||||
if (!tr_logLevelIsActive(level))
|
||||
{
|
||||
return;
|
||||
}
|
||||
#define myLogMacro(msgs, level, text) \
|
||||
do \
|
||||
{ \
|
||||
if (tr_logGetLevel() >= (level)) \
|
||||
{ \
|
||||
tr_logAddMessage( \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
(level), \
|
||||
fmt::format(FMT_STRING("{:s} [{:s}]: {:s}"), (msgs)->io->addrStr(), (msgs)->client, text), \
|
||||
(msgs)->torrent->name()); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
va_list args;
|
||||
char addrstr[TR_ADDRSTRLEN];
|
||||
|
||||
auto* const buf = evbuffer_new();
|
||||
evbuffer_add_printf(buf, "%s [%s]: ", tr_peerIoGetAddrStr(msgs->io, addrstr, sizeof(addrstr)), msgs->client.c_str());
|
||||
va_start(args, fmt);
|
||||
evbuffer_add_vprintf(buf, fmt, args);
|
||||
va_end(args);
|
||||
auto const message = evbuffer_free_to_str(buf);
|
||||
tr_logAddMessage(file, line, level, tr_torrentName(msgs->torrent), message);
|
||||
}
|
||||
|
||||
#define logdbg(msgs, ...) myDebug(__FILE__, __LINE__, TR_LOG_DEBUG, msgs, __VA_ARGS__)
|
||||
#define logtrace(msgs, ...) myDebug(__FILE__, __LINE__, TR_LOG_TRACE, msgs, __VA_ARGS__)
|
||||
#define logdbg(msgs, text) myLogMacro(msgs, TR_LOG_DEBUG, text)
|
||||
#define logtrace(msgs, text) myLogMacro(msgs, TR_LOG_TRACE, text)
|
||||
|
||||
/**
|
||||
***
|
||||
***j
|
||||
**/
|
||||
|
||||
static void pokeBatchPeriod(tr_peerMsgsImpl* msgs, int interval)
|
||||
|
@ -689,13 +683,13 @@ static void pokeBatchPeriod(tr_peerMsgsImpl* msgs, int interval)
|
|||
if (msgs->outMessagesBatchPeriod > interval)
|
||||
{
|
||||
msgs->outMessagesBatchPeriod = interval;
|
||||
logtrace(msgs, "lowering batch interval to %d seconds", interval);
|
||||
logtrace(msgs, fmt::format(FMT_STRING("lowering batch interval to {:d} seconds"), interval));
|
||||
}
|
||||
}
|
||||
|
||||
static void dbgOutMessageLen(tr_peerMsgsImpl* msgs)
|
||||
{
|
||||
logtrace(msgs, "outMessage size is now %zu", evbuffer_get_length(msgs->outMessages));
|
||||
logtrace(msgs, fmt::format(FMT_STRING("outMessage size is now {:d}"), evbuffer_get_length(msgs->outMessages)));
|
||||
}
|
||||
|
||||
static void protocolSendReject(tr_peerMsgsImpl* msgs, struct peer_request const* req)
|
||||
|
@ -710,7 +704,7 @@ static void protocolSendReject(tr_peerMsgsImpl* msgs, struct peer_request const*
|
|||
evbuffer_add_uint32(out, req->offset);
|
||||
evbuffer_add_uint32(out, req->length);
|
||||
|
||||
logtrace(msgs, "rejecting %u:%u->%u...", req->index, req->offset, req->length);
|
||||
logtrace(msgs, fmt::format(FMT_STRING("rejecting {:d}:{:d}->{:d}..."), req->index, req->offset, req->length));
|
||||
dbgOutMessageLen(msgs);
|
||||
}
|
||||
|
||||
|
@ -724,7 +718,7 @@ static void protocolSendRequest(tr_peerMsgsImpl* msgs, struct peer_request const
|
|||
evbuffer_add_uint32(out, req.offset);
|
||||
evbuffer_add_uint32(out, req.length);
|
||||
|
||||
logtrace(msgs, "requesting %u:%u->%u...", req.index, req.offset, req.length);
|
||||
logtrace(msgs, fmt::format(FMT_STRING("requesting {:d}:{:d}->{:d}..."), req.index, req.offset, req.length));
|
||||
dbgOutMessageLen(msgs);
|
||||
pokeBatchPeriod(msgs, ImmediatePriorityIntervalSecs);
|
||||
}
|
||||
|
@ -739,7 +733,7 @@ static void protocolSendCancel(tr_peerMsgsImpl* msgs, peer_request const& req)
|
|||
evbuffer_add_uint32(out, req.offset);
|
||||
evbuffer_add_uint32(out, req.length);
|
||||
|
||||
logtrace(msgs, "cancelling %u:%u->%u...", req.index, req.offset, req.length);
|
||||
logtrace(msgs, fmt::format(FMT_STRING("cancelling {:d}:{:d}->{:d}..."), req.index, req.offset, req.length));
|
||||
dbgOutMessageLen(msgs);
|
||||
pokeBatchPeriod(msgs, ImmediatePriorityIntervalSecs);
|
||||
}
|
||||
|
@ -748,7 +742,7 @@ static void protocolSendPort(tr_peerMsgsImpl* msgs, uint16_t port)
|
|||
{
|
||||
struct evbuffer* out = msgs->outMessages;
|
||||
|
||||
logtrace(msgs, "sending Port %u", port);
|
||||
logtrace(msgs, fmt::format(FMT_STRING("sending Port {:d}"), port));
|
||||
evbuffer_add_uint32(out, 3);
|
||||
evbuffer_add_uint8(out, BtPeerMsgs::Port);
|
||||
evbuffer_add_uint16(out, port);
|
||||
|
@ -762,7 +756,7 @@ static void protocolSendHave(tr_peerMsgsImpl* msgs, tr_piece_index_t index)
|
|||
evbuffer_add_uint8(out, BtPeerMsgs::Have);
|
||||
evbuffer_add_uint32(out, index);
|
||||
|
||||
logtrace(msgs, "sending Have %u", index);
|
||||
logtrace(msgs, fmt::format(FMT_STRING("sending Have {:d}"), index));
|
||||
dbgOutMessageLen(msgs);
|
||||
pokeBatchPeriod(msgs, LowPriorityIntervalSecs);
|
||||
}
|
||||
|
@ -793,7 +787,7 @@ static void protocolSendChoke(tr_peerMsgsImpl* msgs, bool choke)
|
|||
evbuffer_add_uint32(out, sizeof(uint8_t));
|
||||
evbuffer_add_uint8(out, choke ? BtPeerMsgs::Choke : BtPeerMsgs::Unchoke);
|
||||
|
||||
logtrace(msgs, "sending %s...", choke ? "Choke" : "Unchoke");
|
||||
logtrace(msgs, choke ? "sending choke" : "sending unchoked");
|
||||
dbgOutMessageLen(msgs);
|
||||
pokeBatchPeriod(msgs, ImmediatePriorityIntervalSecs);
|
||||
}
|
||||
|
@ -920,7 +914,7 @@ static void sendInterest(tr_peerMsgsImpl* msgs, bool b)
|
|||
|
||||
struct evbuffer* out = msgs->outMessages;
|
||||
|
||||
logtrace(msgs, "Sending %s", b ? "Interested" : "Not Interested");
|
||||
logtrace(msgs, b ? "Sending Interested" : "Sending Not Interested");
|
||||
evbuffer_add_uint32(out, sizeof(uint8_t));
|
||||
evbuffer_add_uint8(out, b ? BtPeerMsgs::Interested : BtPeerMsgs::NotInterested);
|
||||
|
||||
|
@ -1118,11 +1112,11 @@ static void parseLtepHandshake(tr_peerMsgsImpl* msgs, uint32_t len, struct evbuf
|
|||
/* arbitrary limit, should be more than enough */
|
||||
if (len <= 4096)
|
||||
{
|
||||
logtrace(msgs, "here is the handshake: [%*.*s]", TR_ARG_TUPLE(int(len), int(len), tmp));
|
||||
logtrace(msgs, fmt::format(FMT_STRING("here is the handshake: [{:{}.{}s}]"), tmp, len, len));
|
||||
}
|
||||
else
|
||||
{
|
||||
logtrace(msgs, "handshake length is too big (%" PRIu32 "), printing skipped", len);
|
||||
logtrace(msgs, fmt::format(FMT_STRING("handshake length is too big ({:d}), printing skipped"), len));
|
||||
}
|
||||
|
||||
/* does the peer prefer encrypted connections? */
|
||||
|
@ -1148,14 +1142,14 @@ static void parseLtepHandshake(tr_peerMsgsImpl* msgs, uint32_t len, struct evbuf
|
|||
{
|
||||
msgs->peerSupportsPex = i != 0;
|
||||
msgs->ut_pex_id = (uint8_t)i;
|
||||
logtrace(msgs, "msgs->ut_pex is %d", int(msgs->ut_pex_id));
|
||||
logtrace(msgs, fmt::format(FMT_STRING("msgs->ut_pex is {:d}"), static_cast<int>(msgs->ut_pex_id)));
|
||||
}
|
||||
|
||||
if (tr_variantDictFindInt(sub, TR_KEY_ut_metadata, &i))
|
||||
{
|
||||
msgs->peerSupportsMetadataXfer = i != 0;
|
||||
msgs->ut_metadata_id = (uint8_t)i;
|
||||
logtrace(msgs, "msgs->ut_metadata_id is %d", int(msgs->ut_metadata_id));
|
||||
logtrace(msgs, fmt::format(FMT_STRING("msgs->ut_metadata_id is {:d}"), static_cast<int>(msgs->ut_metadata_id)));
|
||||
}
|
||||
|
||||
if (tr_variantDictFindInt(sub, TR_KEY_ut_holepunch, &i))
|
||||
|
@ -1183,7 +1177,7 @@ static void parseLtepHandshake(tr_peerMsgsImpl* msgs, uint32_t len, struct evbuf
|
|||
{
|
||||
pex.port = htons((uint16_t)i);
|
||||
msgs->publishClientGotPort(pex.port);
|
||||
logtrace(msgs, "peer's port is now %d", int(i));
|
||||
logtrace(msgs, fmt::format(FMT_STRING("peer's port is now {:d}"), i));
|
||||
}
|
||||
|
||||
uint8_t const* addr = nullptr;
|
||||
|
@ -1232,7 +1226,9 @@ static void parseUtMetadata(tr_peerMsgsImpl* msgs, uint32_t msglen, struct evbuf
|
|||
tr_variantFree(&dict);
|
||||
}
|
||||
|
||||
logtrace(msgs, "got ut_metadata msg: type %d, piece %d, total_size %d", int(msg_type), int(piece), int(total_size));
|
||||
logtrace(
|
||||
msgs,
|
||||
fmt::format(FMT_STRING("got ut_metadata msg: type {:d}, piece {:d}, total_size {:d}"), msg_type, piece, total_size));
|
||||
|
||||
if (msg_type == MetadataMsgType::Reject)
|
||||
{
|
||||
|
@ -1367,7 +1363,7 @@ static void parseLtep(tr_peerMsgsImpl* msgs, uint32_t msglen, struct evbuffer* i
|
|||
}
|
||||
else
|
||||
{
|
||||
logtrace(msgs, "skipping unknown ltep message (%d)", int(ltep_msgid));
|
||||
logtrace(msgs, fmt::format(FMT_STRING("skipping unknown ltep message ({:d})"), static_cast<int>(ltep_msgid)));
|
||||
evbuffer_drain(inbuf, msglen);
|
||||
}
|
||||
}
|
||||
|
@ -1406,7 +1402,9 @@ static ReadState readBtId(tr_peerMsgsImpl* msgs, struct evbuffer* inbuf, size_t
|
|||
auto id = uint8_t{};
|
||||
tr_peerIoReadUint8(msgs->io, inbuf, &id);
|
||||
msgs->incoming.id = id;
|
||||
logtrace(msgs, "msgs->incoming.id is now %d; msgs->incoming.length is %zu", id, (size_t)msgs->incoming.length);
|
||||
logtrace(
|
||||
msgs,
|
||||
fmt::format(FMT_STRING("msgs->incoming.id is now {:d}: msgs->incoming.length is {:d}"), id, msgs->incoming.length));
|
||||
|
||||
if (id == BtPeerMsgs::Piece)
|
||||
{
|
||||
|
@ -1565,7 +1563,9 @@ static ReadState readBtPiece(tr_peerMsgsImpl* msgs, struct evbuffer* inbuf, size
|
|||
tr_peerIoReadUint32(msgs->io, inbuf, &req->index);
|
||||
tr_peerIoReadUint32(msgs->io, inbuf, &req->offset);
|
||||
req->length = msgs->incoming.length - 9;
|
||||
logtrace(msgs, "got incoming block header %u:%u->%u", req->index, req->offset, req->length);
|
||||
logtrace(
|
||||
msgs,
|
||||
fmt::format(FMT_STRING("got incoming block header {:d}:{:d}->{:d}"), req->index, req->offset, req->length));
|
||||
return READ_NOW;
|
||||
}
|
||||
|
||||
|
@ -1586,12 +1586,13 @@ static ReadState readBtPiece(tr_peerMsgsImpl* msgs, struct evbuffer* inbuf, size
|
|||
*setme_piece_bytes_read += n;
|
||||
logtrace(
|
||||
msgs,
|
||||
"got %zu bytes for block %u:%u->%u ... %d remain",
|
||||
n,
|
||||
req->index,
|
||||
req->offset,
|
||||
req->length,
|
||||
int(req->length - evbuffer_get_length(block_buffer)));
|
||||
fmt::format(
|
||||
FMT_STRING("got {:d} bytes for block {:d}:{:d}->{:d} ... {:d} remain"),
|
||||
n,
|
||||
req->index,
|
||||
req->offset,
|
||||
req->length,
|
||||
req->length - evbuffer_get_length(block_buffer)));
|
||||
|
||||
if (evbuffer_get_length(block_buffer) < req->length)
|
||||
{
|
||||
|
@ -1623,7 +1624,9 @@ static ReadState readBtMessage(tr_peerMsgsImpl* msgs, struct evbuffer* inbuf, si
|
|||
|
||||
--msglen; /* id length */
|
||||
|
||||
logtrace(msgs, "got BT id %d, len %d, buffer size is %zu", int(id), int(msglen), inlen);
|
||||
logtrace(
|
||||
msgs,
|
||||
fmt::format(FMT_STRING("got BT id {:d}, len {:d}, buffer size is {:d}"), static_cast<int>(id), msglen, inlen));
|
||||
|
||||
if (inlen < msglen)
|
||||
{
|
||||
|
@ -1632,7 +1635,9 @@ static ReadState readBtMessage(tr_peerMsgsImpl* msgs, struct evbuffer* inbuf, si
|
|||
|
||||
if (!messageLengthIsCorrect(msgs, id, msglen + 1))
|
||||
{
|
||||
logdbg(msgs, "bad packet - BT message #%d with a length of %d", int(id), int(msglen));
|
||||
logdbg(
|
||||
msgs,
|
||||
fmt::format(FMT_STRING("bad packet - BT message #{:d} with a length of {:d}"), static_cast<int>(id), msglen));
|
||||
msgs->publishError(EMSGSIZE);
|
||||
return READ_ERR;
|
||||
}
|
||||
|
@ -1672,7 +1677,7 @@ static ReadState readBtMessage(tr_peerMsgsImpl* msgs, struct evbuffer* inbuf, si
|
|||
|
||||
case BtPeerMsgs::Have:
|
||||
tr_peerIoReadUint32(msgs->io, inbuf, &ui32);
|
||||
logtrace(msgs, "got Have: %u", ui32);
|
||||
logtrace(msgs, fmt::format(FMT_STRING("got Have: {:d}"), ui32));
|
||||
|
||||
if (msgs->torrent->hasMetainfo() && ui32 >= msgs->torrent->pieceCount())
|
||||
{
|
||||
|
@ -1708,7 +1713,7 @@ static ReadState readBtMessage(tr_peerMsgsImpl* msgs, struct evbuffer* inbuf, si
|
|||
tr_peerIoReadUint32(msgs->io, inbuf, &r.index);
|
||||
tr_peerIoReadUint32(msgs->io, inbuf, &r.offset);
|
||||
tr_peerIoReadUint32(msgs->io, inbuf, &r.length);
|
||||
logtrace(msgs, "got Request: %u:%u->%u", r.index, r.offset, r.length);
|
||||
logtrace(msgs, fmt::format(FMT_STRING("got Request: {:d}:{:d}->{:d}"), r.index, r.offset, r.length));
|
||||
peerMadeRequest(msgs, &r);
|
||||
break;
|
||||
}
|
||||
|
@ -1720,7 +1725,7 @@ static ReadState readBtMessage(tr_peerMsgsImpl* msgs, struct evbuffer* inbuf, si
|
|||
tr_peerIoReadUint32(msgs->io, inbuf, &r.offset);
|
||||
tr_peerIoReadUint32(msgs->io, inbuf, &r.length);
|
||||
msgs->cancelsSentToClient.add(tr_time(), 1);
|
||||
logtrace(msgs, "got a Cancel %u:%u->%u", r.index, r.offset, r.length);
|
||||
logtrace(msgs, fmt::format(FMT_STRING("got a Cancel {:d}:{:d}->{:d}"), r.index, r.offset, r.length));
|
||||
|
||||
for (int i = 0; i < msgs->pendingReqsToClient; ++i)
|
||||
{
|
||||
|
@ -1850,7 +1855,7 @@ static ReadState readBtMessage(tr_peerMsgsImpl* msgs, struct evbuffer* inbuf, si
|
|||
break;
|
||||
|
||||
default:
|
||||
logtrace(msgs, "peer sent us an UNKNOWN: %d", int(id));
|
||||
logtrace(msgs, fmt::format(FMT_STRING("peer sent us an UNKNOWN: {:d}"), static_cast<int>(id)));
|
||||
tr_peerIoDrain(msgs->io, inbuf, msglen);
|
||||
break;
|
||||
}
|
||||
|
@ -1873,17 +1878,22 @@ static int clientGotBlock(tr_peerMsgsImpl* msgs, struct evbuffer* data, struct p
|
|||
|
||||
if (!requestIsValid(msgs, req))
|
||||
{
|
||||
logdbg(msgs, "dropping invalid block %u:%u->%u", req->index, req->offset, req->length);
|
||||
logdbg(msgs, fmt::format(FMT_STRING("dropping invalid block {:d}:{:d}->{:d}"), req->index, req->offset, req->length));
|
||||
return EBADMSG;
|
||||
}
|
||||
|
||||
if (req->length != msgs->torrent->blockSize(block))
|
||||
{
|
||||
logdbg(msgs, "wrong block size -- expected %u, got %d", msgs->torrent->blockSize(block), req->length);
|
||||
logdbg(
|
||||
msgs,
|
||||
fmt::format(
|
||||
FMT_STRING("wrong block size -- expected {:d}, got {:d}"),
|
||||
msgs->torrent->blockSize(block),
|
||||
req->length));
|
||||
return EMSGSIZE;
|
||||
}
|
||||
|
||||
logtrace(msgs, "got block %u:%u->%u", req->index, req->offset, req->length);
|
||||
logtrace(msgs, fmt::format(FMT_STRING("got block {:d}:{:d}->{:d}"), req->index, req->offset, req->length));
|
||||
|
||||
if (!tr_peerMgrDidPeerRequest(msgs->torrent, msgs, block))
|
||||
{
|
||||
|
@ -1934,7 +1944,9 @@ static ReadState canRead(tr_peerIo* io, void* vmsgs, size_t* piece)
|
|||
evbuffer* const in = io->getReadBuffer();
|
||||
size_t const inlen = evbuffer_get_length(in);
|
||||
|
||||
logtrace(msgs, "canRead: inlen is %zu, msgs->state is %d", inlen, int(msgs->state));
|
||||
logtrace(
|
||||
msgs,
|
||||
fmt::format(FMT_STRING("canRead: inlen is {:d}, msgs->state is {:d}"), inlen, static_cast<int>(msgs->state)));
|
||||
|
||||
auto ret = ReadState{};
|
||||
if (inlen == 0)
|
||||
|
@ -1963,7 +1975,7 @@ static ReadState canRead(tr_peerIo* io, void* vmsgs, size_t* piece)
|
|||
|
||||
default:
|
||||
#ifdef TR_ENABLE_ASSERTS
|
||||
TR_ASSERT_MSG(false, fmt::format(FMT_STRING("unhandled peer messages state {:d}"), int(msgs->state)));
|
||||
TR_ASSERT_MSG(false, fmt::format(FMT_STRING("unhandled peer messages state {:d}"), static_cast<int>(msgs->state)));
|
||||
#else
|
||||
ret = READ_ERR;
|
||||
break;
|
||||
|
@ -1971,7 +1983,7 @@ static ReadState canRead(tr_peerIo* io, void* vmsgs, size_t* piece)
|
|||
}
|
||||
}
|
||||
|
||||
logtrace(msgs, "canRead: ret is %d", int(ret));
|
||||
logtrace(msgs, fmt::format(FMT_STRING("canRead: ret is {:d}"), static_cast<int>(ret)));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -2032,7 +2044,7 @@ static void updateMetadataRequests(tr_peerMsgsImpl* msgs, time_t now)
|
|||
tr_variantDictAddInt(&tmp, TR_KEY_piece, piece);
|
||||
auto* const payload = tr_variantToBuf(&tmp, TR_VARIANT_FMT_BENC);
|
||||
|
||||
logtrace(msgs, "requesting metadata piece #%d", piece);
|
||||
logtrace(msgs, fmt::format(FMT_STRING("requesting metadata piece #{:d}"), piece));
|
||||
|
||||
/* write it out as a LTEP message to our outMessages buffer */
|
||||
evbuffer_add_uint32(out, 2 * sizeof(uint8_t) + evbuffer_get_length(payload));
|
||||
|
@ -2094,14 +2106,16 @@ static size_t fillOutputBuffer(tr_peerMsgsImpl* msgs, time_t now)
|
|||
|
||||
if (haveMessages && msgs->outMessagesBatchedAt == 0) /* fresh batch */
|
||||
{
|
||||
logtrace(msgs, "started an outMessages batch (length is %zu)", evbuffer_get_length(msgs->outMessages));
|
||||
logtrace(
|
||||
msgs,
|
||||
fmt::format(FMT_STRING("started an outMessages batch (length is {:d})"), evbuffer_get_length(msgs->outMessages)));
|
||||
msgs->outMessagesBatchedAt = now;
|
||||
}
|
||||
else if (haveMessages && now - msgs->outMessagesBatchedAt >= msgs->outMessagesBatchPeriod)
|
||||
{
|
||||
size_t const len = evbuffer_get_length(msgs->outMessages);
|
||||
/* flush the protocol messages */
|
||||
logtrace(msgs, "flushing outMessages... to %p (length is %zu)", (void*)msgs->io, len);
|
||||
logtrace(msgs, fmt::format(FMT_STRING("flushing outMessages... to {:p} (length is {:d})"), fmt::ptr(msgs->io), len));
|
||||
tr_peerIoWriteBuf(msgs->io, msgs->outMessages, false);
|
||||
msgs->clientSentAnythingAt = now;
|
||||
msgs->outMessagesBatchedAt = 0;
|
||||
|
@ -2224,7 +2238,7 @@ static size_t fillOutputBuffer(tr_peerMsgsImpl* msgs, time_t now)
|
|||
else
|
||||
{
|
||||
size_t const n = evbuffer_get_length(out);
|
||||
logtrace(msgs, "sending block %u:%u->%u", req.index, req.offset, req.length);
|
||||
logtrace(msgs, fmt::format(FMT_STRING("sending block {:d}:{:d}->{:d}"), req.index, req.offset, req.length));
|
||||
TR_ASSERT(n == msglen);
|
||||
tr_peerIoWriteBuf(msgs->io, out, true);
|
||||
bytesWritten += n;
|
||||
|
@ -2292,12 +2306,14 @@ static void gotError(tr_peerIo* /*io*/, short what, void* vmsgs)
|
|||
|
||||
if ((what & BEV_EVENT_TIMEOUT) != 0)
|
||||
{
|
||||
logdbg(msgs, "libevent got a timeout, what=%hd", what);
|
||||
logdbg(msgs, fmt::format(FMT_STRING("libevent got a timeout, what={:d}"), what));
|
||||
}
|
||||
|
||||
if ((what & (BEV_EVENT_EOF | BEV_EVENT_ERROR)) != 0)
|
||||
{
|
||||
logdbg(msgs, "libevent got an error! what=%hd, errno=%d (%s)", what, errno, tr_strerror(errno));
|
||||
logdbg(
|
||||
msgs,
|
||||
fmt::format(FMT_STRING("libevent got an error! what={:d}, errno={:d} ({:s})"), what, errno, tr_strerror(errno)));
|
||||
}
|
||||
|
||||
msgs->publishError(ENOTCONN);
|
||||
|
@ -2313,7 +2329,7 @@ static void sendBitfield(tr_peerMsgsImpl* msgs)
|
|||
evbuffer_add_uint32(out, sizeof(uint8_t) + bytes.size());
|
||||
evbuffer_add_uint8(out, BtPeerMsgs::Bitfield);
|
||||
evbuffer_add(out, bytes.data(), std::size(bytes));
|
||||
logtrace(msgs, "sending bitfield... outMessage size is now %zu", evbuffer_get_length(out));
|
||||
logtrace(msgs, fmt::format(FMT_STRING("sending bitfield... outMessage size is now {:d}"), evbuffer_get_length(out)));
|
||||
pokeBatchPeriod(msgs, ImmediatePriorityIntervalSecs);
|
||||
}
|
||||
|
||||
|
@ -2502,15 +2518,16 @@ static void sendPex(tr_peerMsgsImpl* msgs)
|
|||
&diffs6);
|
||||
logtrace(
|
||||
msgs,
|
||||
"pex: old peer count %d+%d, new peer count %d+%d, added %d+%d, removed %d+%d",
|
||||
msgs->pexCount,
|
||||
msgs->pexCount6,
|
||||
newCount,
|
||||
newCount6,
|
||||
diffs.addedCount,
|
||||
diffs6.addedCount,
|
||||
diffs.droppedCount,
|
||||
diffs6.droppedCount);
|
||||
fmt::format(
|
||||
FMT_STRING("pex: old peer count {:d}+{:d}, new peer count {:d}+{:d}, added {:d}+{:d}, removed {:d}+{:d}"),
|
||||
msgs->pexCount,
|
||||
msgs->pexCount6,
|
||||
newCount,
|
||||
newCount6,
|
||||
diffs.addedCount,
|
||||
diffs6.addedCount,
|
||||
diffs.droppedCount,
|
||||
diffs6.droppedCount));
|
||||
|
||||
if (diffs.addedCount == 0 && diffs.droppedCount == 0 && diffs6.addedCount == 0 && diffs6.droppedCount == 0)
|
||||
{
|
||||
|
@ -2640,7 +2657,9 @@ static void sendPex(tr_peerMsgsImpl* msgs)
|
|||
evbuffer_add_uint8(out, msgs->ut_pex_id);
|
||||
evbuffer_add_buffer(out, payload);
|
||||
pokeBatchPeriod(msgs, HighPriorityIntervalSecs);
|
||||
logtrace(msgs, "sending a pex message; outMessage size is now %zu", evbuffer_get_length(out));
|
||||
logtrace(
|
||||
msgs,
|
||||
fmt::format(FMT_STRING("sending a pex message; outMessage size is now {:d}"), evbuffer_get_length(out)));
|
||||
dbgOutMessageLen(msgs);
|
||||
|
||||
evbuffer_free(payload);
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
// License text can be found in the licenses/ folder.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdarg>
|
||||
#include <cstring>
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
@ -21,6 +20,7 @@
|
|||
#include <windows.h>
|
||||
#include <shlobj.h> /* SHGetKnownFolderPath(), FOLDERID_... */
|
||||
#else
|
||||
#include <pwd.h>
|
||||
#include <unistd.h> /* getuid() */
|
||||
#endif
|
||||
|
||||
|
@ -45,59 +45,10 @@
|
|||
|
||||
using namespace std::literals;
|
||||
|
||||
// TODO: use remove this and use tr_strvPath() instead
|
||||
static char* tr_buildPath(char const* first_element, ...)
|
||||
{
|
||||
// pass 1: allocate enough space for the string
|
||||
va_list vl;
|
||||
va_start(vl, first_element);
|
||||
auto bufLen = size_t{};
|
||||
for (char const* element = first_element; element != nullptr;)
|
||||
{
|
||||
bufLen += strlen(element) + 1;
|
||||
element = va_arg(vl, char const*);
|
||||
}
|
||||
va_end(vl);
|
||||
auto* const buf = tr_new(char, bufLen);
|
||||
if (buf == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* pass 2: build the string piece by piece */
|
||||
char* pch = buf;
|
||||
va_start(vl, first_element);
|
||||
for (char const* element = first_element; element != nullptr;)
|
||||
{
|
||||
size_t const elementLen = strlen(element);
|
||||
pch = std::copy_n(element, elementLen, pch);
|
||||
*pch++ = TR_PATH_DELIMITER;
|
||||
element = va_arg(vl, char const*);
|
||||
}
|
||||
va_end(vl);
|
||||
|
||||
// if nonempty, eat the unwanted trailing slash
|
||||
if (pch != buf)
|
||||
{
|
||||
--pch;
|
||||
}
|
||||
|
||||
// zero-terminate the string
|
||||
*pch++ = '\0';
|
||||
|
||||
/* sanity checks & return */
|
||||
TR_ASSERT(pch - buf == (ptrdiff_t)bufLen);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/***
|
||||
**** PATHS
|
||||
***/
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
static char* win32_get_known_folder_ex(REFKNOWNFOLDERID folder_id, DWORD flags)
|
||||
|
@ -128,31 +79,34 @@ static char const* getHomeDir()
|
|||
if (home == nullptr)
|
||||
{
|
||||
home = tr_env_get_string("HOME", nullptr);
|
||||
}
|
||||
|
||||
if (home == nullptr)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
home = win32_get_known_folder(FOLDERID_Profile);
|
||||
if (home == nullptr)
|
||||
{
|
||||
home = win32_get_known_folder(FOLDERID_Profile);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
struct passwd pwent;
|
||||
struct passwd* pw = nullptr;
|
||||
char buf[4096];
|
||||
getpwuid_r(getuid(), &pwent, buf, sizeof buf, &pw);
|
||||
if (pw != nullptr)
|
||||
{
|
||||
home = tr_strdup(pw->pw_dir);
|
||||
}
|
||||
if (home == nullptr)
|
||||
{
|
||||
struct passwd pwent;
|
||||
struct passwd* pw = nullptr;
|
||||
char buf[4096];
|
||||
getpwuid_r(getuid(), &pwent, buf, sizeof buf, &pw);
|
||||
if (pw != nullptr)
|
||||
{
|
||||
home = tr_strdup(pw->pw_dir);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
if (home == nullptr)
|
||||
{
|
||||
home = tr_strdup("");
|
||||
}
|
||||
if (home == nullptr)
|
||||
{
|
||||
home = tr_strdup("");
|
||||
}
|
||||
|
||||
return home;
|
||||
|
@ -202,19 +156,19 @@ char const* tr_getDefaultConfigDir(char const* appname)
|
|||
{
|
||||
#ifdef __APPLE__
|
||||
|
||||
s = tr_buildPath(getHomeDir(), "Library", "Application Support", appname, nullptr);
|
||||
s = tr_strvDup(tr_strvPath(getHomeDir(), "Library", "Application Support", appname));
|
||||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
char* appdata = win32_get_known_folder(FOLDERID_LocalAppData);
|
||||
s = tr_buildPath(appdata, appname, nullptr);
|
||||
s = tr_strvDup(tr_strvPath(appdata, appname));
|
||||
tr_free(appdata);
|
||||
|
||||
#elif defined(__HAIKU__)
|
||||
|
||||
char buf[PATH_MAX];
|
||||
find_directory(B_USER_SETTINGS_DIRECTORY, -1, true, buf, sizeof(buf));
|
||||
s = tr_buildPath(buf, appname, nullptr);
|
||||
s = tr_strvDup(tr_strvPath(buf, appname));
|
||||
|
||||
#else
|
||||
|
||||
|
@ -222,12 +176,12 @@ char const* tr_getDefaultConfigDir(char const* appname)
|
|||
|
||||
if (xdg_config_home != nullptr)
|
||||
{
|
||||
s = tr_buildPath(xdg_config_home, appname, nullptr);
|
||||
s = tr_strvDup(tr_strvPath(xdg_config_home, appname));
|
||||
tr_free(xdg_config_home);
|
||||
}
|
||||
else
|
||||
{
|
||||
s = tr_buildPath(getHomeDir(), ".config", appname, nullptr);
|
||||
s = tr_strvDup(tr_strvPath(getHomeDir(), ".config", appname));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -301,9 +255,9 @@ char const* tr_getDefaultDownloadDir()
|
|||
if (user_dir == nullptr)
|
||||
{
|
||||
#ifdef __HAIKU__
|
||||
user_dir = tr_buildPath(getHomeDir(), "Desktop", nullptr);
|
||||
user_dir = tr_strvDup(tr_strvPath(getHomeDir(), "Desktop"));
|
||||
#else
|
||||
user_dir = tr_buildPath(getHomeDir(), "Downloads", nullptr);
|
||||
user_dir = tr_strvDup(tr_strvPath(getHomeDir(), "Downloads"));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -317,10 +271,10 @@ char const* tr_getDefaultDownloadDir()
|
|||
|
||||
static bool isWebClientDir(std::string_view path)
|
||||
{
|
||||
auto tmp = tr_strvPath(path, "index.html");
|
||||
bool const ret = tr_sys_path_exists(tmp.c_str());
|
||||
tr_logAddTrace(fmt::format("Searching for web interface file '{}'", tmp));
|
||||
return ret;
|
||||
auto const filename = tr_pathbuf{ path, '/', "index.html"sv };
|
||||
bool const found = tr_sys_path_exists(filename);
|
||||
tr_logAddTrace(fmt::format(FMT_STRING("Searching for web interface file '{:s}'"), filename));
|
||||
return found;
|
||||
}
|
||||
|
||||
char const* tr_getWebClientDir([[maybe_unused]] tr_session const* session)
|
||||
|
@ -330,145 +284,136 @@ char const* tr_getWebClientDir([[maybe_unused]] tr_session const* session)
|
|||
if (s == nullptr)
|
||||
{
|
||||
s = tr_env_get_string("CLUTCH_HOME", nullptr);
|
||||
}
|
||||
|
||||
if (s == nullptr)
|
||||
if (s == nullptr)
|
||||
{
|
||||
s = tr_env_get_string("TRANSMISSION_WEB_HOME", nullptr);
|
||||
}
|
||||
|
||||
#ifdef BUILD_MAC_CLIENT
|
||||
|
||||
// look in the Application Support folder
|
||||
if (s == nullptr)
|
||||
{
|
||||
if (auto path = tr_pathbuf{ session->config_dir, "/public_html"sv }; isWebClientDir(path))
|
||||
{
|
||||
s = tr_env_get_string("TRANSMISSION_WEB_HOME", nullptr);
|
||||
s = tr_strvDup(path);
|
||||
}
|
||||
}
|
||||
|
||||
if (s == nullptr)
|
||||
// look in the resource bundle
|
||||
if (s == nullptr)
|
||||
{
|
||||
auto app_url = CFBundleCopyBundleURL(CFBundleGetMainBundle());
|
||||
auto app_ref = CFURLCopyFileSystemPath(app_url, kCFURLPOSIXPathStyle);
|
||||
auto const buflen = CFStringGetMaximumSizeOfFileSystemRepresentation(app_ref);
|
||||
auto buf = std::vector<char>(buflen, '\0');
|
||||
bool const success = CFStringGetFileSystemRepresentation(app_ref, std::data(buf), std::size(buf));
|
||||
TR_ASSERT(success);
|
||||
CFRelease(app_url);
|
||||
CFRelease(app_ref);
|
||||
|
||||
if (auto const path = tr_pathbuf{ std::string_view{ std::data(buf) }, "/Contents/Resources/public_html"sv };
|
||||
isWebClientDir(path))
|
||||
{
|
||||
#ifdef BUILD_MAC_CLIENT /* on Mac, look in the Application Support folder first, then in the app bundle. */
|
||||
|
||||
/* Look in the Application Support folder */
|
||||
s = tr_buildPath(tr_sessionGetConfigDir(session), "public_html", nullptr);
|
||||
|
||||
if (!isWebClientDir(s))
|
||||
{
|
||||
tr_free(const_cast<char*>(s));
|
||||
|
||||
CFURLRef appURL = CFBundleCopyBundleURL(CFBundleGetMainBundle());
|
||||
CFStringRef appRef = CFURLCopyFileSystemPath(appURL, kCFURLPOSIXPathStyle);
|
||||
CFIndex const appStringLength = CFStringGetMaximumSizeOfFileSystemRepresentation(appRef);
|
||||
|
||||
char* appString = static_cast<char*>(tr_malloc(appStringLength));
|
||||
bool const success = CFStringGetFileSystemRepresentation(appRef, appString, appStringLength);
|
||||
TR_ASSERT(success);
|
||||
|
||||
CFRelease(appURL);
|
||||
CFRelease(appRef);
|
||||
|
||||
/* Fallback to the app bundle */
|
||||
s = tr_buildPath(appString, "Contents", "Resources", "public_html", nullptr);
|
||||
|
||||
if (!isWebClientDir(s))
|
||||
{
|
||||
tr_free(const_cast<char*>(s));
|
||||
s = nullptr;
|
||||
}
|
||||
|
||||
tr_free(appString);
|
||||
}
|
||||
s = tr_strvDup(path);
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
/* Generally, Web interface should be stored in a Web subdir of
|
||||
* calling executable dir. */
|
||||
if (s == nullptr)
|
||||
{
|
||||
/* Generally, Web interface should be stored in a Web subdir of
|
||||
* calling executable dir. */
|
||||
|
||||
static KNOWNFOLDERID const* const known_folder_ids[] = {
|
||||
&FOLDERID_LocalAppData,
|
||||
&FOLDERID_RoamingAppData,
|
||||
&FOLDERID_ProgramData,
|
||||
};
|
||||
static KNOWNFOLDERID const* const known_folder_ids[] = {
|
||||
&FOLDERID_LocalAppData,
|
||||
&FOLDERID_RoamingAppData,
|
||||
&FOLDERID_ProgramData,
|
||||
};
|
||||
|
||||
for (size_t i = 0; s == nullptr && i < TR_N_ELEMENTS(known_folder_ids); ++i)
|
||||
for (size_t i = 0; s == nullptr && i < TR_N_ELEMENTS(known_folder_ids); ++i)
|
||||
{
|
||||
char* dir = win32_get_known_folder(*known_folder_ids[i]);
|
||||
|
||||
if (auto const path = tr_pathbuf{ std::string_view{ dir }, "/Transmission/Web"sv }; isWebClientDir(path))
|
||||
{
|
||||
char* dir = win32_get_known_folder(*known_folder_ids[i]);
|
||||
char* path = tr_buildPath(dir, "Transmission", "Web", nullptr);
|
||||
tr_free(dir);
|
||||
|
||||
if (isWebClientDir(path))
|
||||
{
|
||||
s = path;
|
||||
}
|
||||
else
|
||||
{
|
||||
tr_free(path);
|
||||
}
|
||||
s = tr_strvDup(path);
|
||||
}
|
||||
|
||||
if (s == nullptr) /* check calling module place */
|
||||
{
|
||||
wchar_t wide_module_path[MAX_PATH];
|
||||
GetModuleFileNameW(nullptr, wide_module_path, TR_N_ELEMENTS(wide_module_path));
|
||||
char* module_path = tr_win32_native_to_utf8(wide_module_path, -1);
|
||||
auto const dir = tr_sys_path_dirname(module_path);
|
||||
tr_free(module_path);
|
||||
|
||||
if (!std::empty(dir))
|
||||
{
|
||||
char* path = tr_buildPath(dir.c_str(), "Web", nullptr);
|
||||
|
||||
if (isWebClientDir(path))
|
||||
{
|
||||
s = path;
|
||||
}
|
||||
else
|
||||
{
|
||||
tr_free(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else /* everyone else, follow the XDG spec */
|
||||
|
||||
auto candidates = std::list<std::string>{};
|
||||
|
||||
/* XDG_DATA_HOME should be the first in the list of candidates */
|
||||
char* tmp = tr_env_get_string("XDG_DATA_HOME", nullptr);
|
||||
if (!tr_str_is_empty(tmp))
|
||||
{
|
||||
candidates.emplace_back(tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
candidates.emplace_back(tr_strvPath(getHomeDir(), ".local"sv, "share"sv));
|
||||
}
|
||||
tr_free(tmp);
|
||||
|
||||
/* XDG_DATA_DIRS are the backup directories */
|
||||
{
|
||||
char const* const pkg = PACKAGE_DATA_DIR;
|
||||
auto* xdg = tr_env_get_string("XDG_DATA_DIRS", "");
|
||||
auto const buf = tr_strvJoin(pkg, ":", xdg, ":/usr/local/share:/usr/share");
|
||||
tr_free(xdg);
|
||||
|
||||
auto sv = std::string_view{ buf };
|
||||
auto token = std::string_view{};
|
||||
while (tr_strvSep(&sv, &token, ':'))
|
||||
{
|
||||
token = tr_strvStrip(token);
|
||||
if (!std::empty(token))
|
||||
{
|
||||
candidates.emplace_back(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* walk through the candidates & look for a match */
|
||||
for (auto const& dir : candidates)
|
||||
{
|
||||
auto const path = tr_strvPath(dir, "transmission"sv, "public_html"sv);
|
||||
if (isWebClientDir(path))
|
||||
{
|
||||
s = tr_strvDup(path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
tr_free(dir);
|
||||
}
|
||||
}
|
||||
|
||||
if (s == nullptr) /* check calling module place */
|
||||
{
|
||||
wchar_t wide_module_path[MAX_PATH];
|
||||
GetModuleFileNameW(nullptr, wide_module_path, TR_N_ELEMENTS(wide_module_path));
|
||||
char* module_path = tr_win32_native_to_utf8(wide_module_path, -1);
|
||||
|
||||
if (auto const dir = tr_sys_path_dirname(module_path); !std::empty(dir))
|
||||
{
|
||||
if (auto const path = tr_pathbuf{ dir, "/Web"sv }; isWebClientDir(path))
|
||||
{
|
||||
s = tr_strvDup(path);
|
||||
}
|
||||
}
|
||||
|
||||
tr_free(module_path);
|
||||
}
|
||||
|
||||
#else // everyone else, follow the XDG spec
|
||||
|
||||
if (s == nullptr)
|
||||
{
|
||||
auto candidates = std::list<std::string>{};
|
||||
|
||||
/* XDG_DATA_HOME should be the first in the list of candidates */
|
||||
char* tmp = tr_env_get_string("XDG_DATA_HOME", nullptr);
|
||||
if (!tr_str_is_empty(tmp))
|
||||
{
|
||||
candidates.emplace_back(tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
candidates.emplace_back(tr_strvPath(getHomeDir(), ".local"sv, "share"sv));
|
||||
}
|
||||
tr_free(tmp);
|
||||
|
||||
/* XDG_DATA_DIRS are the backup directories */
|
||||
{
|
||||
char const* const pkg = PACKAGE_DATA_DIR;
|
||||
auto* xdg = tr_env_get_string("XDG_DATA_DIRS", "");
|
||||
auto const buf = tr_strvJoin(pkg, ":", xdg, ":/usr/local/share:/usr/share");
|
||||
tr_free(xdg);
|
||||
|
||||
auto sv = std::string_view{ buf };
|
||||
auto token = std::string_view{};
|
||||
while (tr_strvSep(&sv, &token, ':'))
|
||||
{
|
||||
token = tr_strvStrip(token);
|
||||
if (!std::empty(token))
|
||||
{
|
||||
candidates.emplace_back(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* walk through the candidates & look for a match */
|
||||
for (auto const& dir : candidates)
|
||||
{
|
||||
if (auto const path = tr_pathbuf{ dir, "/transmission/public_html"sv }; isWebClientDir(path))
|
||||
{
|
||||
s = tr_strvDup(path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue