diff --git a/libtransmission/announcer-common.h b/libtransmission/announcer-common.h index 1479c7e02..0bc862ca0 100644 --- a/libtransmission/announcer-common.h +++ b/libtransmission/announcer-common.h @@ -19,6 +19,7 @@ #include "transmission.h" #include "interned-string.h" +#include "net.h" #include "peer-mgr.h" // tr_pex #include "web-utils.h" @@ -134,7 +135,7 @@ struct tr_announce_request bool partial_seed = false; /* the port we listen for incoming peers on */ - int port = 0; + tr_port port; /* per-session key */ int key = 0; diff --git a/libtransmission/announcer-http.cc b/libtransmission/announcer-http.cc index 38d992556..02c94f9dd 100644 --- a/libtransmission/announcer-http.cc +++ b/libtransmission/announcer-http.cc @@ -71,7 +71,7 @@ static tr_urlbuf announce_url_new(tr_session const* session, tr_announce_request fmt::arg("sep", tr_strvContains(req->announce_url.sv(), '?') ? '&' : '?'), fmt::arg("info_hash", std::data(escaped_info_hash)), fmt::arg("peer_id", std::string_view{ std::data(req->peer_id), std::size(req->peer_id) }), - fmt::arg("port", req->port), + fmt::arg("port", req->port.host()), fmt::arg("uploaded", req->up), fmt::arg("downloaded", req->down), fmt::arg("left", req->leftUntilComplete), @@ -211,7 +211,7 @@ void tr_announcerParseHttpAnnounceResponse(tr_announce_response& response, std:: } else if (key == "port"sv) { - pex_.port = htons(uint16_t(value)); + pex_.port.setHost(static_cast(value)); } else { diff --git a/libtransmission/announcer-udp.cc b/libtransmission/announcer-udp.cc index c14d55807..320443967 100644 --- a/libtransmission/announcer-udp.cc +++ b/libtransmission/announcer-udp.cc @@ -47,11 +47,11 @@ static void tau_sockaddr_setport(struct sockaddr* sa, tr_port port) { if (sa->sa_family == AF_INET) { - TR_DISCARD_ALIGN(sa, struct sockaddr_in*)->sin_port = htons(port); + TR_DISCARD_ALIGN(sa, struct sockaddr_in*)->sin_port = port.network(); } else if (sa->sa_family == AF_INET6) { - TR_DISCARD_ALIGN(sa, struct sockaddr_in6*)->sin6_port = htons(port); + TR_DISCARD_ALIGN(sa, struct sockaddr_in6*)->sin6_port = port.network(); } } @@ -370,7 +370,7 @@ static tau_announce_request make_tau_announce_request( evbuffer_add_hton_32(buf, 0); evbuffer_add_hton_32(buf, in->key); evbuffer_add_hton_32(buf, in->numwant); - evbuffer_add_hton_16(buf, in->port); + evbuffer_add_hton_16(buf, in->port.host()); auto const* const payload_begin = evbuffer_pullup(buf, -1); auto const* const payload_end = payload_begin + evbuffer_get_length(buf); @@ -423,7 +423,7 @@ struct tau_tracker tr_interned_string const key; tr_interned_string const host; - int const port; + tr_port const port; evdns_getaddrinfo_request* dns_request = nullptr; std::shared_ptr addr; @@ -439,7 +439,7 @@ struct tau_tracker std::list announces; std::list scrapes; - tau_tracker(tr_session* session_in, tr_interned_string key_in, tr_interned_string host_in, int port_in) + tau_tracker(tr_session* session_in, tr_interned_string key_in, tr_interned_string host_in, tr_port port_in) : session{ session_in } , key{ key_in } , host{ host_in } @@ -744,7 +744,7 @@ static tau_tracker* tau_session_get_tracker(tr_announcer_udp* tau, tr_interned_s } // we don't have it -- build a new one - tau->trackers.emplace_back(tau->session, key, tr_interned_string(parsed->host), parsed->port); + tau->trackers.emplace_back(tau->session, key, tr_interned_string(parsed->host), tr_port::fromHost(parsed->port)); auto* const tracker = &tau->trackers.back(); logtrace(tracker->key, "New tau_tracker created"); return tracker; diff --git a/libtransmission/announcer.cc b/libtransmission/announcer.cc index f3d472109..df5469c07 100644 --- a/libtransmission/announcer.cc +++ b/libtransmission/announcer.cc @@ -877,7 +877,7 @@ static tr_announce_request* announce_request_new( TR_ASSERT(current_tracker != nullptr); auto* const req = new tr_announce_request(); - req->port = tr_sessionGetPublicPeerPort(announcer->session); + req->port = announcer->session->peerPort(); req->announce_url = current_tracker->announce_url; req->tracker_id = current_tracker->tracker_id; req->info_hash = tor->infoHash(); diff --git a/libtransmission/natpmp.cc b/libtransmission/natpmp.cc index d76f3a253..311b1637b 100644 --- a/libtransmission/natpmp.cc +++ b/libtransmission/natpmp.cc @@ -55,8 +55,8 @@ struct tr_natpmp* tr_natpmpInit() { auto* const nat = tr_new0(struct tr_natpmp, 1); nat->state = TR_NATPMP_DISCOVER; - nat->public_port = 0; - nat->private_port = 0; + nat->public_port.clear(); + nat->private_port.clear(); nat->natpmp.s = TR_BAD_SOCKET; /* socket */ return nat; } @@ -125,7 +125,12 @@ tr_port_forwarding tr_natpmpPulse( if (nat->state == TR_NATPMP_SEND_UNMAP && canSendCommand(nat)) { - int const val = sendnewportmappingrequest(&nat->natpmp, NATPMP_PROTOCOL_TCP, nat->private_port, nat->public_port, 0); + int const val = sendnewportmappingrequest( + &nat->natpmp, + NATPMP_PROTOCOL_TCP, + nat->private_port.host(), + nat->public_port.host(), + 0); logVal("sendnewportmappingrequest", val); nat->state = val < 0 ? TR_NATPMP_ERR : TR_NATPMP_RECV_UNMAP; setCommandTime(nat); @@ -139,14 +144,14 @@ tr_port_forwarding tr_natpmpPulse( if (val >= 0) { - int const unmapped_port = resp.pnu.newportmapping.privateport; + auto const unmapped_port = tr_port::fromHost(resp.pnu.newportmapping.privateport); - tr_logAddInfo(fmt::format(_("Port {port} is no longer forwarded"), fmt::arg("port", unmapped_port))); + tr_logAddInfo(fmt::format(_("Port {port} is no longer forwarded"), fmt::arg("port", unmapped_port.host()))); if (nat->private_port == unmapped_port) { - nat->private_port = 0; - nat->public_port = 0; + nat->private_port.clear(); + nat->public_port.clear(); nat->state = TR_NATPMP_IDLE; nat->is_mapped = false; } @@ -171,7 +176,12 @@ tr_port_forwarding tr_natpmpPulse( if (nat->state == TR_NATPMP_SEND_MAP && canSendCommand(nat)) { - int const val = sendnewportmappingrequest(&nat->natpmp, NATPMP_PROTOCOL_TCP, private_port, private_port, LifetimeSecs); + int const val = sendnewportmappingrequest( + &nat->natpmp, + NATPMP_PROTOCOL_TCP, + private_port.host(), + private_port.host(), + LifetimeSecs); logVal("sendnewportmappingrequest", val); nat->state = val < 0 ? TR_NATPMP_ERR : TR_NATPMP_RECV_MAP; setCommandTime(nat); @@ -188,9 +198,9 @@ tr_port_forwarding tr_natpmpPulse( nat->state = TR_NATPMP_IDLE; nat->is_mapped = true; nat->renew_time = tr_time() + (resp.pnu.newportmapping.lifetime / 2); - nat->private_port = resp.pnu.newportmapping.privateport; - nat->public_port = resp.pnu.newportmapping.mappedpublicport; - tr_logAddInfo(fmt::format(_("Port {port} forwarded successfully"), fmt::arg("port", nat->private_port))); + nat->private_port = tr_port::fromHost(resp.pnu.newportmapping.privateport); + nat->public_port = tr_port::fromHost(resp.pnu.newportmapping.mappedpublicport); + tr_logAddInfo(fmt::format(_("Port {port} forwarded successfully"), fmt::arg("port", nat->private_port.host()))); } else if (val != NATPMP_TRYAGAIN) { diff --git a/libtransmission/natpmp_local.h b/libtransmission/natpmp_local.h index ca7241cef..504422518 100644 --- a/libtransmission/natpmp_local.h +++ b/libtransmission/natpmp_local.h @@ -15,6 +15,7 @@ */ #include "natpmp.h" +#include "net.h" // tr_port enum tr_natpmp_state { diff --git a/libtransmission/net.cc b/libtransmission/net.cc index 3677fdb1f..7da9f754d 100644 --- a/libtransmission/net.cc +++ b/libtransmission/net.cc @@ -65,7 +65,7 @@ char const* tr_address_and_port_to_string(char* buf, size_t buflen, tr_address c { char addr_buf[INET6_ADDRSTRLEN]; tr_address_to_string_with_buf(addr, addr_buf, sizeof(addr_buf)); - *fmt::format_to_n(buf, buflen - 1, FMT_STRING("[{:s}]:{:d}"), addr_buf, ntohs(port)).out = '\0'; + *fmt::format_to_n(buf, buflen - 1, FMT_STRING("[{:s}]:{:d}"), addr_buf, port.host()).out = '\0'; return buf; } @@ -145,7 +145,7 @@ std::string tr_address::to_string(tr_port port) const { auto addrbuf = std::array{}; tr_address_to_string_with_buf(this, std::data(addrbuf), std::size(addrbuf)); - return fmt::format("[{}]:{}", std::data(addrbuf), ntohs(port)); + return fmt::format(FMT_STRING("[{:s}]:{:d}"), std::data(addrbuf), port.host()); } tr_address tr_address::from_4byte_ipv4(std::string_view in) @@ -290,7 +290,7 @@ bool tr_address_from_sockaddr_storage(tr_address* setme_addr, tr_port* setme_por auto const* const sin = (struct sockaddr_in const*)from; setme_addr->type = TR_AF_INET; setme_addr->addr.addr4.s_addr = sin->sin_addr.s_addr; - *setme_port = sin->sin_port; + *setme_port = tr_port::fromNetwork(sin->sin_port); return true; } @@ -299,7 +299,7 @@ bool tr_address_from_sockaddr_storage(tr_address* setme_addr, tr_port* setme_por auto const* const sin6 = (struct sockaddr_in6 const*)from; setme_addr->type = TR_AF_INET6; setme_addr->addr.addr6 = sin6->sin6_addr; - *setme_port = sin6->sin6_port; + *setme_port = tr_port::fromNetwork(sin6->sin6_port); return true; } @@ -315,14 +315,14 @@ static socklen_t setup_sockaddr(tr_address const* addr, tr_port port, struct soc sockaddr_in sock4 = {}; sock4.sin_family = AF_INET; sock4.sin_addr.s_addr = addr->addr.addr4.s_addr; - sock4.sin_port = port; + sock4.sin_port = port.network(); memcpy(sockaddr, &sock4, sizeof(sock4)); return sizeof(struct sockaddr_in); } sockaddr_in6 sock6 = {}; sock6.sin6_family = AF_INET6; - sock6.sin6_port = port; + sock6.sin6_port = port.network(); sock6.sin6_flowinfo = 0; sock6.sin6_addr = addr->addr.addr6; memcpy(sockaddr, &sock6, sizeof(sock6)); @@ -372,7 +372,7 @@ struct tr_peer_socket tr_netOpenPeerSocket(tr_session* session, tr_address const /* set source address */ tr_address const* const source_addr = tr_sessionGetPublicAddress(session, addr->type, nullptr); TR_ASSERT(source_addr != nullptr); - socklen_t const sourcelen = setup_sockaddr(source_addr, 0, &source_sock); + socklen_t const sourcelen = setup_sockaddr(source_addr, {}, &source_sock); if (bind(s, (struct sockaddr*)&source_sock, sourcelen) == -1) { @@ -400,7 +400,7 @@ struct tr_peer_socket tr_netOpenPeerSocket(tr_session* session, tr_address const _("Couldn't connect socket {socket} to {address}:{port}: {error} ({error_code})"), fmt::arg("socket", s), fmt::arg("address", addr->to_string()), - fmt::arg("port", ntohs(port)), + fmt::arg("port", port.host()), fmt::arg("error", tr_net_strerror(tmperrno)), fmt::arg("error_code", tmperrno))); } @@ -498,7 +498,7 @@ static tr_socket_t tr_netBindTCPImpl(tr_address const* addr, tr_port port, bool #endif - int const addrlen = setup_sockaddr(addr, htons(port), &sock); + int const addrlen = setup_sockaddr(addr, port, &sock); if (bind(fd, (struct sockaddr*)&sock, addrlen) == -1) { @@ -511,7 +511,7 @@ static tr_socket_t tr_netBindTCPImpl(tr_address const* addr, tr_port port, bool _("Couldn't bind port {port} on {address}: {error} ({error_code}) -- Is another copy of Transmission already running?") : _("Couldn't bind port {port} on {address}: {error} ({error_code})"), fmt::arg("address", addr->to_string()), - fmt::arg("port", port), + fmt::arg("port", port.host()), fmt::arg("error", tr_net_strerror(err)), fmt::arg("error_code", err))); } @@ -523,7 +523,7 @@ static tr_socket_t tr_netBindTCPImpl(tr_address const* addr, tr_port port, bool if (!suppressMsgs) { - tr_logAddDebug(fmt::format("Bound socket {} to port {} on {}", fd, port, addr->to_string())); + tr_logAddDebug(fmt::format(FMT_STRING("Bound socket {:d} to port {:d} on {:s}"), fd, port.host(), addr->to_string())); } #ifdef TCP_FASTOPEN @@ -823,7 +823,7 @@ static bool isMartianAddr(struct tr_address const* a) bool tr_address_is_valid_for_peers(tr_address const* addr, tr_port port) { - return port != 0 && tr_address_is_valid(addr) && !isIPv6LinkLocalAddress(addr) && !isIPv4MappedAddress(addr) && + return !std::empty(port) && tr_address_is_valid(addr) && !isIPv6LinkLocalAddress(addr) && !isIPv4MappedAddress(addr) && !isMartianAddr(addr); } @@ -842,3 +842,16 @@ struct tr_peer_socket tr_peer_socket_utp_create(struct UTPSocket* const handle) ret.handle.utp = handle; return ret; } + +/// tr_port + +static auto constexpr PortLen = size_t{ 2 }; + +std::pair tr_port::fromCompact(uint8_t const* compact) noexcept +{ + static_assert(PortLen == sizeof(uint16_t)); + auto nport = uint16_t{}; + std::copy_n(compact, PortLen, reinterpret_cast(&nport)); + compact += PortLen; + return std::make_pair(tr_port::fromNetwork(nport), compact); +} diff --git a/libtransmission/net.h b/libtransmission/net.h index 2b7fee444..029ae2671 100644 --- a/libtransmission/net.h +++ b/libtransmission/net.h @@ -9,9 +9,11 @@ #endif #include // size_t +#include // uint8_t #include #include #include +#include // std::pair #ifdef _WIN32 #include @@ -71,6 +73,82 @@ struct tr_address; [[nodiscard]] int tr_address_compare(tr_address const* a, tr_address const* b) noexcept; +/** + * Literally just a port number. + * + * Exists so that you never have to wonder what byte order a port variable is in. + */ +class tr_port +{ +public: + tr_port() noexcept = default; + + [[nodiscard]] constexpr static tr_port fromHost(uint16_t hport) noexcept + { + return tr_port{ hport }; + } + + [[nodiscard]] static tr_port fromNetwork(uint16_t nport) noexcept + { + return tr_port{ ntohs(nport) }; + } + + [[nodiscard]] constexpr uint16_t host() const noexcept + { + return hport_; + } + + [[nodiscard]] uint16_t network() const noexcept + { + return htons(hport_); + } + + constexpr void setHost(uint16_t hport) noexcept + { + hport_ = hport; + } + + void setNetwork(uint16_t nport) noexcept + { + hport_ = ntohs(nport); + } + + [[nodiscard]] static std::pair fromCompact(uint8_t const* compact) noexcept; + + [[nodiscard]] constexpr auto operator<(tr_port const& that) const noexcept + { + return hport_ < that.hport_; + } + + [[nodiscard]] constexpr auto operator==(tr_port const& that) const noexcept + { + return hport_ == that.hport_; + } + + [[nodiscard]] constexpr auto operator!=(tr_port const& that) const noexcept + { + return hport_ != that.hport_; + } + + [[nodiscard]] constexpr auto empty() const noexcept + { + return hport_ == 0; + } + + constexpr void clear() noexcept + { + hport_ = 0; + } + +private: + constexpr tr_port(uint16_t hport) noexcept + : hport_{ hport } + { + } + + uint16_t hport_ = 0; +}; + struct tr_address { static tr_address from_4byte_ipv4(std::string_view in); diff --git a/libtransmission/peer-common.h b/libtransmission/peer-common.h index 8359b7532..014debd1a 100644 --- a/libtransmission/peer-common.h +++ b/libtransmission/peer-common.h @@ -16,6 +16,7 @@ #include "bitfield.h" #include "history.h" #include "interned-string.h" +#include "net.h" // tr_port /** * @addtogroup peers Peers diff --git a/libtransmission/peer-mgr.cc b/libtransmission/peer-mgr.cc index 7b5d2a95a..8750305bd 100644 --- a/libtransmission/peer-mgr.cc +++ b/libtransmission/peer-mgr.cc @@ -10,6 +10,7 @@ #include #include /* qsort */ #include // time_t +#include // std::tie #include // std::back_inserter #include #include @@ -1122,16 +1123,15 @@ size_t tr_peerMgrAddPex(tr_torrent* tor, uint8_t from, tr_pex const* pex, size_t std::vector tr_peerMgrCompactToPex(void const* compact, size_t compactLen, uint8_t const* added_f, size_t added_f_len) { size_t n = compactLen / 6; - auto const* walk = static_cast(compact); + auto const* walk = static_cast(compact); auto pex = std::vector(n); for (size_t i = 0; i < n; ++i) { pex[i].addr.type = TR_AF_INET; - std::copy_n(walk, 4, reinterpret_cast(&pex[i].addr.addr)); + std::copy_n(walk, 4, reinterpret_cast(&pex[i].addr.addr)); walk += 4; - std::copy_n(walk, 2, reinterpret_cast(&pex[i].port)); - walk += 2; + std::tie(pex[i].port, walk) = tr_port::fromCompact(walk); if (added_f != nullptr && n == added_f_len) { @@ -1145,16 +1145,15 @@ std::vector tr_peerMgrCompactToPex(void const* compact, size_t compactLe std::vector tr_peerMgrCompact6ToPex(void const* compact, size_t compactLen, uint8_t const* added_f, size_t added_f_len) { size_t n = compactLen / 18; - auto const* walk = static_cast(compact); + auto const* walk = static_cast(compact); auto pex = std::vector(n); for (size_t i = 0; i < n; ++i) { pex[i].addr.type = TR_AF_INET6; - std::copy_n(walk, 16, reinterpret_cast(&pex[i].addr.addr.addr6.s6_addr)); + std::copy_n(walk, 16, reinterpret_cast(&pex[i].addr.addr.addr6.s6_addr)); walk += 16; - std::copy_n(walk, 2, reinterpret_cast(&pex[i].port)); - walk += 2; + std::tie(pex[i].port, walk) = tr_port::fromCompact(walk); if (added_f != nullptr && n == added_f_len) { @@ -1311,7 +1310,10 @@ int tr_peerMgrGetPeers(tr_torrent const* tor, tr_pex** setme_pex, uint8_t af, ui } } - qsort(atoms, atomCount, sizeof(struct peer_atom*), compareAtomsByUsefulness); + if (atoms != nullptr) + { + qsort(atoms, atomCount, sizeof(struct peer_atom*), compareAtomsByUsefulness); + } /** *** add the first N of them into our return list @@ -1338,7 +1340,10 @@ int tr_peerMgrGetPeers(tr_torrent const* tor, tr_pex** setme_pex, uint8_t af, ui } } - qsort(pex, count, sizeof(tr_pex), tr_pexCompare); + if (pex != nullptr) + { + qsort(pex, count, sizeof(tr_pex), tr_pexCompare); + } TR_ASSERT(walk - pex == count); *setme_pex = pex; @@ -1647,7 +1652,7 @@ static auto getPeerStats(tr_peerMsgs const* peer, time_t now, uint64_t now_msec) tr_address_to_string_with_buf(&atom->addr, stats.addr, sizeof(stats.addr)); stats.client = peer->client.c_str(); - stats.port = ntohs(peer->atom->port); + stats.port = peer->atom->port.host(); stats.from = atom->fromFirst; stats.progress = peer->progress; stats.isUTP = peer->is_utp_connection(); diff --git a/libtransmission/peer-msgs.cc b/libtransmission/peer-msgs.cc index 1f4939802..f983858e1 100644 --- a/libtransmission/peer-msgs.cc +++ b/libtransmission/peer-msgs.cc @@ -59,6 +59,8 @@ auto constexpr Bitfield = uint8_t{ 5 }; auto constexpr Request = uint8_t{ 6 }; auto constexpr Piece = uint8_t{ 7 }; auto constexpr Cancel = uint8_t{ 8 }; + +// http://bittorrent.org/beps/bep_0005.html auto constexpr Port = uint8_t{ 9 }; // https://www.bittorrent.org/beps/bep_0006.html @@ -197,7 +199,7 @@ static void pexPulse(evutil_socket_t fd, short what, void* vmsgs); static void protocolSendCancel(tr_peerMsgsImpl* msgs, struct peer_request const& req); static void protocolSendChoke(tr_peerMsgsImpl* msgs, bool choke); static void protocolSendHave(tr_peerMsgsImpl* msgs, tr_piece_index_t index); -static void protocolSendPort(tr_peerMsgsImpl* msgs, uint16_t port); +static void protocolSendPort(tr_peerMsgsImpl* msgs, tr_port port); static void sendInterest(tr_peerMsgsImpl* msgs, bool b); static void sendLtepHandshake(tr_peerMsgsImpl* msgs); static void tellPeerWhatWeHave(tr_peerMsgsImpl* msgs); @@ -600,7 +602,7 @@ public: uint16_t pexCount = 0; uint16_t pexCount6 = 0; - tr_port dht_port = 0; + tr_port dht_port; EncryptionPreference encryption_preference = EncryptionPreference::Unknown; @@ -738,14 +740,14 @@ static void protocolSendCancel(tr_peerMsgsImpl* msgs, peer_request const& req) pokeBatchPeriod(msgs, ImmediatePriorityIntervalSecs); } -static void protocolSendPort(tr_peerMsgsImpl* msgs, uint16_t port) +static void protocolSendPort(tr_peerMsgsImpl* msgs, tr_port port) { struct evbuffer* out = msgs->outMessages; - logtrace(msgs, fmt::format(FMT_STRING("sending Port {:d}"), port)); + logtrace(msgs, fmt::format(FMT_STRING("sending Port {:d}"), port.host())); evbuffer_add_uint32(out, 3); evbuffer_add_uint8(out, BtPeerMsgs::Port); - evbuffer_add_uint16(out, port); + evbuffer_add_uint16(out, port.network()); } static void protocolSendHave(tr_peerMsgsImpl* msgs, tr_piece_index_t index) @@ -1045,7 +1047,7 @@ static void sendLtepHandshake(tr_peerMsgsImpl* msgs) // port number of the other side. Note that there is no need for the // receiving side of the connection to send this extension message, // since its port number is already known. - tr_variantDictAddInt(&val, TR_KEY_p, tr_sessionGetPublicPeerPort(msgs->session)); + tr_variantDictAddInt(&val, TR_KEY_p, msgs->session->peerPort().host()); // http://bittorrent.org/beps/bep_0010.html // An integer, the number of outstanding request messages this @@ -1171,7 +1173,7 @@ static void parseLtepHandshake(tr_peerMsgsImpl* msgs, uint32_t len, struct evbuf /* get peer's listening port */ if (tr_variantDictFindInt(&val, TR_KEY_p, &i)) { - pex.port = htons((uint16_t)i); + pex.port.setHost(i); msgs->publishClientGotPort(pex.port); logtrace(msgs, fmt::format(FMT_STRING("peer's port is now {:d}"), i)); } @@ -1747,14 +1749,23 @@ static ReadState readBtMessage(tr_peerMsgsImpl* msgs, struct evbuffer* inbuf, si break; case BtPeerMsgs::Port: - logtrace(msgs, "Got a BtPeerMsgs::Port"); - tr_peerIoReadUint16(msgs->io, inbuf, &msgs->dht_port); - - if (msgs->dht_port > 0) + // http://bittorrent.org/beps/bep_0005.html + // Peers supporting the DHT set the last bit of the 8-byte reserved flags + // exchanged in the BitTorrent protocol handshake. Peer receiving a handshake + // indicating the remote peer supports the DHT should send a PORT message. + // It begins with byte 0x09 and has a two byte payload containing the UDP + // port of the DHT node in network byte order. { - tr_dhtAddNode(msgs->session, tr_peerAddress(msgs), msgs->dht_port, false); - } + logtrace(msgs, "Got a BtPeerMsgs::Port"); + auto nport = uint16_t{}; + tr_peerIoReadUint16(msgs->io, inbuf, &nport); + if (auto const dht_port = tr_port::fromNetwork(nport); !std::empty(dht_port)) + { + msgs->dht_port = dht_port; + tr_dhtAddNode(msgs->session, tr_peerAddress(msgs), msgs->dht_port, false); + } + } break; case BtPeerMsgs::FextSuggest: diff --git a/libtransmission/port-forwarding.cc b/libtransmission/port-forwarding.cc index bd58ac5ce..8e4f36adf 100644 --- a/libtransmission/port-forwarding.cc +++ b/libtransmission/port-forwarding.cc @@ -92,8 +92,8 @@ static void natPulse(tr_shared* s, bool do_check) session->private_peer_port = received_private_port; tr_logAddInfo(fmt::format( _("Mapped private port {private_port} to public port {public_port}"), - fmt::arg("public_port", session->public_peer_port), - fmt::arg("private_port", session->private_peer_port))); + fmt::arg("public_port", session->public_peer_port.host()), + fmt::arg("private_port", session->private_peer_port.host()))); } s->upnpStatus = tr_upnpPulse( diff --git a/libtransmission/port-forwarding.h b/libtransmission/port-forwarding.h index 5b4933442..0abe69f82 100644 --- a/libtransmission/port-forwarding.h +++ b/libtransmission/port-forwarding.h @@ -9,15 +9,10 @@ #error only libtransmission should #include this header. #endif -#include "transmission.h" - -/** - * @addtogroup port_forwarding Port Forwarding - * @{ - */ +#include "net.h" // tr_port struct tr_bindsockets; - +struct tr_session; struct tr_shared; tr_shared* tr_sharedInit(tr_session*); @@ -33,5 +28,3 @@ tr_port tr_sharedGetPeerPort(tr_shared const* s); bool tr_sharedTraversalIsEnabled(tr_shared const* s); int tr_sharedTraversalStatus(tr_shared const*); - -/** @} */ diff --git a/libtransmission/rpc-server.cc b/libtransmission/rpc-server.cc index b2f9abc60..f62a782b5 100644 --- a/libtransmission/rpc-server.cc +++ b/libtransmission/rpc-server.cc @@ -605,14 +605,13 @@ static char const* tr_rpc_address_to_string(tr_rpc_address const& addr, char* bu static std::string tr_rpc_address_with_port(tr_rpc_server const* server) { - char addr_buf[TrUnixAddrStrLen]; tr_rpc_address_to_string(*server->bindAddress, addr_buf, sizeof(addr_buf)); std::string addr_port_str{ addr_buf }; if (server->bindAddress->type != TR_RPC_AF_UNIX) { - addr_port_str.append(":" + std::to_string(tr_rpcGetPort(server))); + addr_port_str.append(":" + std::to_string(server->port().host())); } return addr_port_str; } @@ -740,11 +739,11 @@ static void startServer(tr_rpc_server* server) char const* address = tr_rpcGetBindAddress(server); - tr_port const port = server->port; + auto const port = server->port(); bool const success = server->bindAddress->type == TR_RPC_AF_UNIX ? bindUnixSocket(base, httpd, address, server->rpc_socket_mode) : - (evhttp_bind_socket(httpd, address, port) != -1); + (evhttp_bind_socket(httpd, address, port.host()) != -1); auto const addr_port_str = tr_rpc_address_with_port(server); @@ -840,24 +839,19 @@ static void restartServer(tr_rpc_server* const server) } } -void tr_rpcSetPort(tr_rpc_server* server, tr_port port) +void tr_rpc_server::setPort(tr_port port) noexcept { - TR_ASSERT(server != nullptr); - - if (server->port != port) + if (port_ == port) { - server->port = port; - - if (server->isEnabled) - { - tr_runInEventThread(server->session, restartServer, server); - } + return; } -} -tr_port tr_rpcGetPort(tr_rpc_server const* server) -{ - return server->port; + port_ = port; + + if (isEnabled) + { + tr_runInEventThread(session, restartServer, this); + } } void tr_rpcSetUrl(tr_rpc_server* server, std::string_view url) @@ -1048,7 +1042,7 @@ tr_rpc_server::tr_rpc_server(tr_session* session_in, tr_variant* settings) } else { - this->port = (tr_port)i; + this->port_.setHost(i); } key = TR_KEY_rpc_url; diff --git a/libtransmission/rpc-server.h b/libtransmission/rpc-server.h index 74b7e44c1..8081a242c 100644 --- a/libtransmission/rpc-server.h +++ b/libtransmission/rpc-server.h @@ -35,6 +35,13 @@ public: tr_rpc_server& operator=(tr_rpc_server&) = delete; tr_rpc_server& operator=(tr_rpc_server&&) = delete; + [[nodiscard]] constexpr tr_port port() const noexcept + { + return port_; + } + + void setPort(tr_port) noexcept; + std::shared_ptr compressor; std::list hostWhitelist; @@ -56,7 +63,7 @@ public: static int constexpr DefaultRpcSocketMode = 0750; int rpc_socket_mode = DefaultRpcSocketMode; - tr_port port = 0; + tr_port port_; bool isAntiBruteForceEnabled = false; bool isEnabled = false; @@ -69,10 +76,6 @@ void tr_rpcSetEnabled(tr_rpc_server* server, bool isEnabled); bool tr_rpcIsEnabled(tr_rpc_server const* server); -void tr_rpcSetPort(tr_rpc_server* server, tr_port port); - -tr_port tr_rpcGetPort(tr_rpc_server const* server); - void tr_rpcSetUrl(tr_rpc_server* server, std::string_view url); std::string const& tr_rpcGetUrl(tr_rpc_server const* server); diff --git a/libtransmission/rpcimpl.cc b/libtransmission/rpcimpl.cc index c1ca8ce0c..54ccf3cd0 100644 --- a/libtransmission/rpcimpl.cc +++ b/libtransmission/rpcimpl.cc @@ -1381,8 +1381,8 @@ static char const* portTest( tr_variant* /*args_out*/, struct tr_rpc_idle_data* idle_data) { - auto const port = tr_sessionGetPeerPort(session); - auto const url = fmt::format(FMT_STRING("https://portcheck.transmissionbt.com/{:d}"), port); + auto const port = session->peerPort(); + auto const url = fmt::format(FMT_STRING("https://portcheck.transmissionbt.com/{:d}"), port.host()); session->web->fetch({ url, onPortTested, idle_data }); return nullptr; } @@ -1943,7 +1943,7 @@ static char const* sessionSet( if (tr_variantDictFindInt(args_in, TR_KEY_peer_port, &i)) { - tr_sessionSetPeerPort(session, i); + session->setPeerPort(tr_port::fromHost(i)); } if (tr_variantDictFindBool(args_in, TR_KEY_port_forwarding_enabled, &boolVal)) @@ -2222,7 +2222,7 @@ static void addSessionField(tr_session* s, tr_variant* d, tr_quark key) break; case TR_KEY_peer_port: - tr_variantDictAddInt(d, key, tr_sessionGetPeerPort(s)); + tr_variantDictAddInt(d, key, s->peerPort().host()); break; case TR_KEY_peer_port_random_on_start: diff --git a/libtransmission/session.cc b/libtransmission/session.cc index 2777ae31b..7b5afa2d0 100644 --- a/libtransmission/session.cc +++ b/libtransmission/session.cc @@ -86,7 +86,10 @@ static auto constexpr BandwidthGroupsFilename = "bandwidth-groups.json"sv; static tr_port getRandomPort(tr_session const* s) { - return tr_port(tr_rand_int_weak(s->randomPortHigh - s->randomPortLow + 1) + s->randomPortLow); + auto const lower = std::min(s->randomPortLow.host(), s->randomPortHigh.host()); + auto const upper = std::max(s->randomPortLow.host(), s->randomPortHigh.host()); + auto const range = upper - lower; + return tr_port::fromHost(lower + tr_rand_int_weak(range + 1)); } /* Generate a peer id : "-TRxyzb-" + 12 random alphanumeric @@ -421,10 +424,10 @@ void tr_sessionGetSettings(tr_session const* s, tr_variant* d) tr_variantDictAddInt(d, TR_KEY_message_level, tr_logGetLevel()); tr_variantDictAddInt(d, TR_KEY_peer_limit_global, s->peerLimit); tr_variantDictAddInt(d, TR_KEY_peer_limit_per_torrent, s->peerLimitPerTorrent); - tr_variantDictAddInt(d, TR_KEY_peer_port, tr_sessionGetPeerPort(s)); + tr_variantDictAddInt(d, TR_KEY_peer_port, s->peerPort().host()); tr_variantDictAddBool(d, TR_KEY_peer_port_random_on_start, s->isPortRandom); - tr_variantDictAddInt(d, TR_KEY_peer_port_random_low, s->randomPortLow); - tr_variantDictAddInt(d, TR_KEY_peer_port_random_high, s->randomPortHigh); + tr_variantDictAddInt(d, TR_KEY_peer_port_random_low, s->randomPortLow.host()); + tr_variantDictAddInt(d, TR_KEY_peer_port_random_high, s->randomPortHigh.host()); tr_variantDictAddStr(d, TR_KEY_peer_socket_tos, tr_netTosToName(s->peer_socket_tos_)); tr_variantDictAddStr(d, TR_KEY_peer_congestion_algorithm, s->peerCongestionAlgorithm()); tr_variantDictAddBool(d, TR_KEY_pex_enabled, s->isPexEnabled); @@ -975,12 +978,12 @@ static void sessionSetImpl(struct init_data* const data) /* incoming peer port */ if (tr_variantDictFindInt(settings, TR_KEY_peer_port_random_low, &i)) { - session->randomPortLow = i; + session->randomPortLow.setHost(i); } if (tr_variantDictFindInt(settings, TR_KEY_peer_port_random_high, &i)) { - session->randomPortHigh = i; + session->randomPortHigh.setHost(i); } if (tr_variantDictFindBool(settings, TR_KEY_peer_port_random_on_start, &boolVal)) @@ -988,12 +991,16 @@ static void sessionSetImpl(struct init_data* const data) tr_sessionSetPeerPortRandomOnStart(session, boolVal); } - if (!tr_variantDictFindInt(settings, TR_KEY_peer_port, &i)) { - i = session->private_peer_port; - } + auto peer_port = session->private_peer_port; - setPeerPort(session, boolVal ? getRandomPort(session) : i); + if (auto port = int64_t{}; tr_variantDictFindInt(settings, TR_KEY_peer_port, &port)) + { + peer_port.setHost(static_cast(port)); + } + + setPeerPort(session, boolVal ? getRandomPort(session) : peer_port); + } if (tr_variantDictFindBool(settings, TR_KEY_port_forwarding_enabled, &boolVal)) { @@ -1244,25 +1251,25 @@ static void setPeerPort(tr_session* session, tr_port port) tr_runInEventThread(session, peerPortChanged, session); } -void tr_sessionSetPeerPort(tr_session* session, tr_port port) +void tr_sessionSetPeerPort(tr_session* session, uint16_t hport) { - if (tr_isSession(session) && session->private_peer_port != port) + if (auto const port = tr_port::fromHost(hport); tr_isSession(session) && session->private_peer_port != port) { setPeerPort(session, port); } } -tr_port tr_sessionGetPeerPort(tr_session const* session) +uint16_t tr_sessionGetPeerPort(tr_session const* session) { - return tr_isSession(session) ? session->public_peer_port : 0; + return tr_isSession(session) ? session->public_peer_port.host() : 0U; } -tr_port tr_sessionSetPeerPortRandom(tr_session* session) +uint16_t tr_sessionSetPeerPortRandom(tr_session* session) { TR_ASSERT(tr_isSession(session)); - tr_sessionSetPeerPort(session, getRandomPort(session)); - return session->private_peer_port; + session->setPeerPort(getRandomPort(session)); + return session->private_peer_port.host(); } void tr_sessionSetPeerPortRandomOnStart(tr_session* session, bool random) @@ -2555,18 +2562,21 @@ bool tr_sessionIsRPCEnabled(tr_session const* session) return tr_rpcIsEnabled(session->rpc_server_.get()); } -void tr_sessionSetRPCPort(tr_session* session, tr_port port) +void tr_sessionSetRPCPort(tr_session* session, uint16_t hport) { TR_ASSERT(tr_isSession(session)); - tr_rpcSetPort(session->rpc_server_.get(), port); + if (session->rpc_server_) + { + session->rpc_server_->setPort(tr_port::fromHost(hport)); + } } -tr_port tr_sessionGetRPCPort(tr_session const* session) +uint16_t tr_sessionGetRPCPort(tr_session const* session) { TR_ASSERT(tr_isSession(session)); - return tr_rpcGetPort(session->rpc_server_.get()); + return session->rpc_server_ ? session->rpc_server_->port().host() : uint16_t{}; } void tr_sessionSetRPCUrl(tr_session* session, char const* url) diff --git a/libtransmission/session.h b/libtransmission/session.h index 125462a98..2622ee633 100644 --- a/libtransmission/session.h +++ b/libtransmission/session.h @@ -337,6 +337,16 @@ public: */ tr_port public_peer_port; + [[nodiscard]] constexpr auto peerPort() const noexcept + { + return public_peer_port; + } + + constexpr auto setPeerPort(tr_port port) noexcept + { + public_peer_port = port; + } + tr_port randomPortLow; tr_port randomPortHigh; @@ -426,11 +436,6 @@ private: bool incomplete_dir_enabled_ = false; }; -constexpr tr_port tr_sessionGetPublicPeerPort(tr_session const* session) -{ - return session->public_peer_port; -} - bool tr_sessionAllowsDHT(tr_session const* session); bool tr_sessionAllowsLPD(tr_session const* session); diff --git a/libtransmission/torrent.cc b/libtransmission/torrent.cc index 0ed6febae..11cef78e8 100644 --- a/libtransmission/torrent.cc +++ b/libtransmission/torrent.cc @@ -687,12 +687,12 @@ static bool isNewTorrentASeed(tr_torrent* tor) static void torrentInit(tr_torrent* tor, tr_ctor const* ctor) { - auto const lock = tor->unique_lock(); - tr_session* session = tr_ctorGetSession(ctor); TR_ASSERT(session != nullptr); - tor->session = session; + + auto const lock = tor->unique_lock(); + tor->queuePosition = tr_sessionCountTorrents(session); torrentInitFromInfoDict(tor); diff --git a/libtransmission/tr-dht.cc b/libtransmission/tr-dht.cc index 2bcfc6f29..a19ffd6fa 100644 --- a/libtransmission/tr-dht.cc +++ b/libtransmission/tr-dht.cc @@ -10,6 +10,7 @@ #include /* memcpy(), memset(), memchr(), strlen() */ #include #include +#include #include #include #include @@ -106,7 +107,7 @@ static void bootstrap_from_name(char const* name, tr_port port, int af) hints.ai_family = af; auto port_str = std::array{}; - *fmt::format_to(std::data(port_str), FMT_STRING("{:d}"), port) = '\0'; + *fmt::format_to(std::data(port_str), FMT_STRING("{:d}"), port.host()) = '\0'; addrinfo* info = nullptr; if (int const rc = getaddrinfo(name, std::data(port_str), &hints, &info); rc != 0) @@ -114,7 +115,7 @@ static void bootstrap_from_name(char const* name, tr_port port, int af) tr_logAddWarn(fmt::format( _("Couldn't look up '{address}:{port}': {error} ({error_code})"), fmt::arg("address", name), - fmt::arg("port", port), + fmt::arg("port", port.host()), fmt::arg("error", gai_strerror(rc)), fmt::arg("error_code", rc))); return; @@ -160,16 +161,16 @@ static void dht_boostrap_from_file(tr_session* session) { auto line_stream = std::istringstream{ line }; auto addrstr = std::string{}; - auto port = tr_port{}; - line_stream >> addrstr >> port; + auto hport = uint16_t{}; + line_stream >> addrstr >> hport; - if (line_stream.bad() || std::empty(addrstr) || port <= 0) + if (line_stream.bad() || std::empty(addrstr)) { tr_logAddWarn(fmt::format(_("Couldn't parse line: '{line}'"), fmt::arg("line", line))); } else { - bootstrap_from_name(addrstr.c_str(), port, bootstrap_af(session_)); + bootstrap_from_name(addrstr.c_str(), tr_port::fromHost(hport), bootstrap_af(session_)); } } } @@ -199,27 +200,21 @@ static void dht_bootstrap(void* closure) { if (i < num && !bootstrap_done(cl->session, AF_INET)) { - auto port = tr_port{}; auto addr = tr_address{}; - memset(&addr, 0, sizeof(addr)); addr.type = TR_AF_INET; memcpy(&addr.addr.addr4, &cl->nodes[i * 6], 4); - memcpy(&port, &cl->nodes[i * 6 + 4], 2); - port = ntohs(port); + auto const [port, out] = tr_port::fromCompact(&cl->nodes[i * 6 + 4]); tr_dhtAddNode(cl->session, &addr, port, true); } if (i < num6 && !bootstrap_done(cl->session, AF_INET6)) { - auto port = tr_port{}; auto addr = tr_address{}; - memset(&addr, 0, sizeof(addr)); addr.type = TR_AF_INET6; memcpy(&addr.addr.addr6, &cl->nodes6[i * 18], 16); - memcpy(&port, &cl->nodes6[i * 18 + 16], 2); - port = ntohs(port); + auto const [port, out] = tr_port::fromCompact(&cl->nodes6[i * 18 + 16]); tr_dhtAddNode(cl->session, &addr, port, true); } @@ -266,7 +261,7 @@ static void dht_bootstrap(void* closure) tr_logAddDebug("Attempting bootstrap from dht.transmissionbt.com"); } - bootstrap_from_name("dht.transmissionbt.com", 6881, bootstrap_af(session_)); + bootstrap_from_name("dht.transmissionbt.com", tr_port::fromHost(6881), bootstrap_af(session_)); } } @@ -532,7 +527,7 @@ int tr_dhtStatus(tr_session* session, int af, int* nodes_return) tr_port tr_dhtPort(tr_session* ss) { - return tr_dhtEnabled(ss) ? ss->udp_port : 0; + return tr_dhtEnabled(ss) ? ss->udp_port : tr_port{}; } bool tr_dhtAddNode(tr_session* ss, tr_address const* address, tr_port port, bool bootstrap) @@ -558,7 +553,7 @@ bool tr_dhtAddNode(tr_session* ss, tr_address const* address, tr_port port, bool memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; memcpy(&sin.sin_addr, &address->addr.addr4, 4); - sin.sin_port = htons(port); + sin.sin_port = port.network(); dht_ping_node((struct sockaddr*)&sin, sizeof(sin)); return true; } @@ -569,7 +564,7 @@ bool tr_dhtAddNode(tr_session* ss, tr_address const* address, tr_port port, bool memset(&sin6, 0, sizeof(sin6)); sin6.sin6_family = AF_INET6; memcpy(&sin6.sin6_addr, &address->addr.addr6, 16); - sin6.sin6_port = htons(port); + sin6.sin6_port = port.network(); dht_ping_node((struct sockaddr*)&sin6, sizeof(sin6)); return true; } @@ -673,7 +668,8 @@ static AnnounceResult tr_dhtAnnounce(tr_torrent* tor, int af, bool announce) } auto const* dht_hash = reinterpret_cast(std::data(tor->infoHash())); - int const rc = dht_search(dht_hash, announce ? tr_sessionGetPeerPort(session_) : 0, af, callback, nullptr); + auto const hport = announce ? session_->peerPort().host() : 0; + int const rc = dht_search(dht_hash, hport, af, callback, nullptr); if (rc < 0) { auto const error_code = errno; diff --git a/libtransmission/tr-lpd.cc b/libtransmission/tr-lpd.cc index e6fb6d60b..c518e78f3 100644 --- a/libtransmission/tr-lpd.cc +++ b/libtransmission/tr-lpd.cc @@ -23,7 +23,7 @@ using in_port_t = uint16_t; /* all missing */ #include #include -#include +#include #include "transmission.h" @@ -263,9 +263,8 @@ int tr_lpdInit(tr_session* ss, tr_address* /*tr_addr*/) TR_ASSERT(lpd_announceInterval > 0); TR_ASSERT(lpd_announceScope > 0); - lpd_port = tr_sessionGetPeerPort(ss); - - if (lpd_port <= 0) + lpd_port = ss->peerPort(); + if (std::empty(lpd_port)) { return -1; } @@ -438,7 +437,7 @@ bool tr_lpdSendAnnounce(tr_torrent const* t) 1, lpd_mcastGroup, lpd_mcastPort, - lpd_port, + lpd_port.host(), tr_strupper(t->infoHashString())); // send the query out using [lpd_socket2] @@ -484,7 +483,6 @@ static int tr_lpdConsiderAnnounce(tr_pex* peer, char const* const msg) char value[MaxValueLen] = { 0 }; char hashString[MaxHashLen] = { 0 }; int res = 0; - int peerPort = 0; if (peer != nullptr && msg != nullptr) { @@ -505,12 +503,13 @@ static int tr_lpdConsiderAnnounce(tr_pex* peer, char const* const msg) } /* determine announced peer port, refuse if value too large */ - if (sscanf(value, "%d", &peerPort) != 1 || peerPort > (in_port_t)-1) + int peer_port = 0; + if (sscanf(value, "%d", &peer_port) != 1 || peer_port > (in_port_t)-1) { return 0; } - peer->port = htons(peerPort); + peer->port.setHost(peer_port); res = -1; /* signal caller side-effect to peer->port via return != 0 */ if (!lpd_extractParam(params, "Infohash", MaxHashLen, hashString)) @@ -524,14 +523,16 @@ static int tr_lpdConsiderAnnounce(tr_pex* peer, char const* const msg) { /* we found a suitable peer, add it to the torrent */ tr_peerMgrAddPex(tor, TR_PEER_FROM_LPD, peer, 1); - tr_logAddDebugTor(tor, fmt::format("Found a local peer from LPD ({})", peer->addr.to_string(peerPort))); + tr_logAddDebugTor( + tor, + fmt::format(FMT_STRING("Found a local peer from LPD ({:s})"), peer->addr.to_string(peer->port))); /* periodic reconnectPulse() deals with the rest... */ return 1; } - tr_logAddDebug(fmt::format("Cannot serve torrent #{}", hashString)); + tr_logAddDebug(fmt::format(FMT_STRING("Cannot serve torrent #{:s}"), hashString)); } return res; diff --git a/libtransmission/tr-udp.cc b/libtransmission/tr-udp.cc index 9d5301114..1bc1cba9c 100644 --- a/libtransmission/tr-udp.cc +++ b/libtransmission/tr-udp.cc @@ -161,7 +161,7 @@ static void rebind_ipv6(tr_session* ss, bool force) memcpy(&sin6.sin6_addr, ipv6, 16); } - sin6.sin6_port = htons(ss->udp_port); + sin6.sin6_port = ss->udp_port.network(); rc = bind(s, (struct sockaddr*)&sin6, sizeof(sin6)); @@ -277,9 +277,8 @@ void tr_udpInit(tr_session* ss) TR_ASSERT(ss->udp_socket == TR_BAD_SOCKET); TR_ASSERT(ss->udp6_socket == TR_BAD_SOCKET); - ss->udp_port = tr_sessionGetPeerPort(ss); - - if (ss->udp_port <= 0) + ss->udp_port = ss->peerPort(); + if (std::empty(ss->udp_port)) { return; } @@ -302,7 +301,7 @@ void tr_udpInit(tr_session* ss) memcpy(&sin.sin_addr, &public_addr->addr.addr4, sizeof(struct in_addr)); } - sin.sin_port = htons(ss->udp_port); + sin.sin_port = ss->udp_port.network(); int const rc = bind(ss->udp_socket, (struct sockaddr*)&sin, sizeof(sin)); if (rc == -1) diff --git a/libtransmission/tr-utp.cc b/libtransmission/tr-utp.cc index 842c3fa36..15ce5e780 100644 --- a/libtransmission/tr-utp.cc +++ b/libtransmission/tr-utp.cc @@ -85,7 +85,7 @@ static void incoming(void* vsession, struct UTPSocket* s) auto* const from = (struct sockaddr*)&from_storage; socklen_t fromlen = sizeof(from_storage); tr_address addr; - tr_port port = 0; + tr_port port; if (!tr_sessionIsUTPEnabled(session)) { diff --git a/libtransmission/transmission.h b/libtransmission/transmission.h index 5bc253a7e..7ca0a1e55 100644 --- a/libtransmission/transmission.h +++ b/libtransmission/transmission.h @@ -32,7 +32,6 @@ using tr_piece_index_t = uint32_t; /* Assuming a 16 KiB block (tr_block_info::BlockSize), a 32-bit block index gives us a maximum torrent size of 64 TiB. * When we ever need to grow past that, change tr_block_index_t and tr_piece_index_t to uint64_t. */ using tr_block_index_t = uint32_t; -using tr_port = uint16_t; using tr_tracker_tier_t = uint32_t; using tr_tracker_id_t = uint32_t; using tr_byte_index_t = uint64_t; @@ -329,12 +328,12 @@ bool tr_sessionIsRPCEnabled(tr_session const* session); /** @brief Specify which port to listen for RPC requests on. @see tr_sessionInit() @see tr_sessionGetRPCPort */ -void tr_sessionSetRPCPort(tr_session* session, tr_port port); +void tr_sessionSetRPCPort(tr_session* session, uint16_t port); /** @brief Get which port to listen for RPC requests on. @see tr_sessionInit() @see tr_sessionSetRPCPort */ -tr_port tr_sessionGetRPCPort(tr_session const* session); +uint16_t tr_sessionGetRPCPort(tr_session const* session); /** * @brief Specify which base URL to use. @@ -491,11 +490,11 @@ void tr_sessionSetPortForwardingEnabled(tr_session* session, bool enabled); bool tr_sessionIsPortForwardingEnabled(tr_session const* session); -void tr_sessionSetPeerPort(tr_session* session, tr_port port); +void tr_sessionSetPeerPort(tr_session* session, uint16_t port); -tr_port tr_sessionGetPeerPort(tr_session const* session); +uint16_t tr_sessionGetPeerPort(tr_session const* session); -tr_port tr_sessionSetPeerPortRandom(tr_session* session); +uint16_t tr_sessionSetPeerPortRandom(tr_session* session); void tr_sessionSetPeerPortRandomOnStart(tr_session* session, bool random); @@ -1262,7 +1261,7 @@ struct tr_peer_stat bool isIncoming; uint8_t from; - tr_port port; + uint16_t port; char addr[TR_INET6_ADDRSTRLEN]; char flagStr[32]; diff --git a/libtransmission/upnp.cc b/libtransmission/upnp.cc index cb2bdad66..6a3ad4587 100644 --- a/libtransmission/upnp.cc +++ b/libtransmission/upnp.cc @@ -79,7 +79,7 @@ struct tr_upnp bool hasDiscovered = false; UPNPUrls urls = {}; IGDdatas data = {}; - int port = -1; + tr_port port; char lanaddr[16] = {}; bool isMapped = false; UpnpState state = UpnpState::WILL_DISCOVER; @@ -144,7 +144,7 @@ static int tr_upnpGetSpecificPortMappingEntry(tr_upnp* handle, char const* proto *intClient = '\0'; *intPort = '\0'; - auto const port_str = fmt::format(FMT_STRING("{:d}"), handle->port); + auto const port_str = fmt::format(FMT_STRING("{:d}"), handle->port.host()); #if (MINIUPNPC_API_VERSION >= 10) /* adds remoteHost arg */ int const err = UPNP_GetSpecificPortMappingEntry( @@ -187,7 +187,7 @@ static int tr_upnpAddPortMapping(tr_upnp const* handle, char const* proto, tr_po int const old_errno = errno; errno = 0; - auto const port_str = fmt::format(FMT_STRING("{:d}"), port); + auto const port_str = fmt::format(FMT_STRING("{:d}"), port.host()); #if (MINIUPNPC_API_VERSION >= 8) int err = UPNP_AddPortMapping( @@ -223,7 +223,7 @@ static int tr_upnpAddPortMapping(tr_upnp const* handle, char const* proto, tr_po static void tr_upnpDeletePortMapping(tr_upnp const* handle, char const* proto, tr_port port) { - auto const port_str = fmt::format(FMT_STRING("{:d}"), port); + auto const port_str = fmt::format(FMT_STRING("{:d}"), port.host()); UPNP_DeletePortMapping(handle->urls.controlURL, handle->data.first.servicetype, port_str.c_str(), proto, nullptr); } @@ -300,7 +300,7 @@ tr_port_forwarding tr_upnpPulse(tr_upnp* handle, tr_port port, bool isEnabled, b ((tr_upnpGetSpecificPortMappingEntry(handle, "TCP") != UPNPCOMMAND_SUCCESS) || (tr_upnpGetSpecificPortMappingEntry(handle, "UDP") != UPNPCOMMAND_SUCCESS))) { - tr_logAddInfo(fmt::format(_("Port {port} is not forwarded"), fmt::arg("port", handle->port))); + tr_logAddInfo(fmt::format(_("Port {port} is not forwarded"), fmt::arg("port", handle->port.host()))); handle->isMapped = false; } @@ -316,7 +316,7 @@ tr_port_forwarding tr_upnpPulse(tr_upnp* handle, tr_port port, bool isEnabled, b handle->isMapped = false; handle->state = UpnpState::IDLE; - handle->port = -1; + handle->port = {}; } if ((handle->state == UpnpState::IDLE) && isEnabled && !handle->isMapped) @@ -334,7 +334,7 @@ tr_port_forwarding tr_upnpPulse(tr_upnp* handle, tr_port port, bool isEnabled, b } else { - auto const desc = fmt::format(FMT_STRING("{:s} at {:d}"), TR_NAME, port); + auto const desc = fmt::format(FMT_STRING("{:s} at {:d}"), TR_NAME, port.host()); int const err_tcp = tr_upnpAddPortMapping(handle, "TCP", port, desc.c_str()); int const err_udp = tr_upnpAddPortMapping(handle, "UDP", port, desc.c_str()); @@ -346,18 +346,18 @@ tr_port_forwarding tr_upnpPulse(tr_upnp* handle, tr_port port, bool isEnabled, b fmt::arg("url", handle->urls.controlURL), fmt::arg("type", handle->data.first.servicetype), fmt::arg("address", handle->lanaddr), - fmt::arg("port", port))); + fmt::arg("port", port.host()))); if (handle->isMapped) { - tr_logAddInfo(fmt::format(_("Port {port} is forwarded"), fmt::arg("port", port))); + tr_logAddInfo(fmt::format(_("Port {port} is forwarded"), fmt::arg("port", port.host()))); handle->port = port; handle->state = UpnpState::IDLE; } else { tr_logAddInfo(_("If your router supports UPnP, please make sure UPnP is enabled!")); - handle->port = -1; + handle->port = {}; handle->state = UpnpState::FAILED; } } diff --git a/libtransmission/web-utils.cc b/libtransmission/web-utils.cc index 7fcffa984..f6185f8b9 100644 --- a/libtransmission/web-utils.cc +++ b/libtransmission/web-utils.cc @@ -203,7 +203,8 @@ auto parsePort(std::string_view port_sv) { auto const port = tr_parseNum(port_sv); - return port && *port >= std::numeric_limits::min() && *port <= std::numeric_limits::max() ? *port : -1; + using PortLimits = std::numeric_limits; + return port && PortLimits::min() <= *port && *port <= PortLimits::max() ? *port : -1; } constexpr std::string_view getPortForScheme(std::string_view scheme) diff --git a/macosx/PrefsController.mm b/macosx/PrefsController.mm index 42fdf8300..90fde3e10 100644 --- a/macosx/PrefsController.mm +++ b/macosx/PrefsController.mm @@ -450,7 +450,7 @@ - (void)setPort:(id)sender { - tr_port const port = [sender intValue]; + uint16_t const port = [sender intValue]; [self.fDefaults setInteger:port forKey:@"BindPort"]; tr_sessionSetPeerPort(self.fHandle, port); @@ -460,7 +460,7 @@ - (void)randomPort:(id)sender { - tr_port const port = tr_sessionSetPeerPortRandom(self.fHandle); + auto const port = tr_sessionSetPeerPortRandom(self.fHandle); [self.fDefaults setInteger:port forKey:@"BindPort"]; self.fPortField.intValue = port; @@ -1392,7 +1392,7 @@ [self.fDefaults setBool:autoStart forKey:@"AutoStartDownload"]; //port - tr_port const port = tr_sessionGetPeerPort(self.fHandle); + auto const port = tr_sessionGetPeerPort(self.fHandle); [self.fDefaults setInteger:port forKey:@"BindPort"]; BOOL const nat = tr_sessionIsPortForwardingEnabled(self.fHandle); diff --git a/qt/Session.cc b/qt/Session.cc index c65abacc6..31f25ae49 100644 --- a/qt/Session.cc +++ b/qt/Session.cc @@ -244,7 +244,7 @@ void Session::updatePref(int key) case Prefs::RPC_PORT: if (session_ != nullptr) { - tr_sessionSetRPCPort(session_, static_cast(prefs_.getInt(key))); + tr_sessionSetRPCPort(session_, static_cast(prefs_.getInt(key))); } break;