Switch to clang-format for code formatting, include Mac client

This commit is contained in:
Mike Gelfand 2021-08-15 12:41:48 +03:00
parent 409f59889b
commit db3d40d0ed
349 changed files with 16657 additions and 12081 deletions

73
.clang-format Normal file
View File

@ -0,0 +1,73 @@
---
AlignAfterOpenBracket: AlwaysBreak
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignConsecutiveMacros: false
AlignEscapedNewlines: DontAlign
AlignOperands: false
AlignTrailingComments: false
AllowAllArgumentsOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: false
AllowShortLambdasOnASingleLine: Inline
AllowShortLoopsOnASingleLine: false
AlwaysBreakBeforeMultilineStrings: true
BinPackArguments: false
BinPackParameters: false
BreakBeforeBraces: Allman
BreakBeforeTernaryOperators: false
BreakStringLiterals: false
ColumnLimit: 128
ContinuationIndentWidth: 4
Cpp11BracedListStyle: false
DerivePointerAlignment: false
ExperimentalAutoDetectBinPacking: false
IndentCaseBlocks: true
IndentPPDirectives: None
IndentWidth: 4
MaxEmptyLinesToKeep: 1
PenaltyBreakAssignment: 1000
PenaltyBreakBeforeFirstCallParameter: 0
PenaltyReturnTypeOnItsOwnLine: 1000
PointerAlignment: Left
ReflowComments: false
SortIncludes: false
SpaceAfterCStyleCast: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
TabWidth: 4
UseTab: Never
---
Language: Cpp
Standard: c++17
AccessModifierOffset: -4
AllowAllConstructorInitializersOnNextLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakTemplateDeclarations: Yes
BreakConstructorInitializers: BeforeComma
BreakInheritanceList: BeforeComma
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
FixNamespaceComments: true
IndentGotoLabels: false
KeepEmptyLinesAtTheStartOfBlocks: true
SortUsingDeclarations: true
SpaceAfterTemplateKeyword: false
StatementMacros:
- TR_DEFINE_QUARK
WhitespaceSensitiveMacros:
- API_HEADER
- API_HEADER_CRYPT
---
Language: ObjC
KeepEmptyLinesAtTheStartOfBlocks: false
ObjCBlockIndentWidth: 4
ObjCBreakBeforeNestedBlockParam: false
ObjCSpaceBeforeProtocolList: false
PenaltyExcessCharacter: 1

View File

@ -45,14 +45,14 @@
#define MEM_T_STR "TiB" #define MEM_T_STR "TiB"
#define DISK_K 1000 #define DISK_K 1000
#define DISK_B_STR "B" #define DISK_B_STR "B"
#define DISK_K_STR "kB" #define DISK_K_STR "kB"
#define DISK_M_STR "MB" #define DISK_M_STR "MB"
#define DISK_G_STR "GB" #define DISK_G_STR "GB"
#define DISK_T_STR "TB" #define DISK_T_STR "TB"
#define SPEED_K 1000 #define SPEED_K 1000
#define SPEED_B_STR "B/s" #define SPEED_B_STR "B/s"
#define SPEED_K_STR "kB/s" #define SPEED_K_STR "kB/s"
#define SPEED_M_STR "MB/s" #define SPEED_M_STR "MB/s"
#define SPEED_G_STR "GB/s" #define SPEED_G_STR "GB/s"
@ -73,11 +73,10 @@ static sig_atomic_t manualUpdate = false;
static char const* torrentPath = NULL; static char const* torrentPath = NULL;
static struct tr_option const options[] = static struct tr_option const options[] = {
{
{ 'b', "blocklist", "Enable peer blocklists", "b", false, NULL }, { 'b', "blocklist", "Enable peer blocklists", "b", false, NULL },
{ 'B', "no-blocklist", "Disable peer blocklists", "B", false, NULL }, { 'B', "no-blocklist", "Disable peer blocklists", "B", false, NULL },
{ 'd', "downlimit", "Set max download speed in "SPEED_K_STR, "d", true, "<speed>" }, { 'd', "downlimit", "Set max download speed in " SPEED_K_STR, "d", true, "<speed>" },
{ 'D', "no-downlimit", "Don't limit the download speed", "D", false, NULL }, { 'D', "no-downlimit", "Don't limit the download speed", "D", false, NULL },
{ 910, "encryption-required", "Encrypt all peer connections", "er", false, NULL }, { 910, "encryption-required", "Encrypt all peer connections", "er", false, NULL },
{ 911, "encryption-preferred", "Prefer encrypted peer connections", "ep", false, NULL }, { 911, "encryption-preferred", "Prefer encrypted peer connections", "ep", false, NULL },
@ -88,7 +87,7 @@ static struct tr_option const options[] =
{ 'M', "no-portmap", "Disable portmapping", "M", false, NULL }, { 'M', "no-portmap", "Disable portmapping", "M", false, NULL },
{ 'p', "port", "Port for incoming peers (Default: " TR_DEFAULT_PEER_PORT_STR ")", "p", true, "<port>" }, { 'p', "port", "Port for incoming peers (Default: " TR_DEFAULT_PEER_PORT_STR ")", "p", true, "<port>" },
{ 't', "tos", "Peer socket TOS (0 to 255, default=" TR_DEFAULT_PEER_SOCKET_TOS_STR ")", "t", true, "<tos>" }, { 't', "tos", "Peer socket TOS (0 to 255, default=" TR_DEFAULT_PEER_SOCKET_TOS_STR ")", "t", true, "<tos>" },
{ 'u', "uplimit", "Set max upload speed in "SPEED_K_STR, "u", true, "<speed>" }, { 'u', "uplimit", "Set max upload speed in " SPEED_K_STR, "u", true, "<speed>" },
{ 'U', "no-uplimit", "Don't limit the upload speed", "U", false, NULL }, { 'U', "no-uplimit", "Don't limit the upload speed", "U", false, NULL },
{ 'v', "verify", "Verify the specified torrent", "v", false, NULL }, { 'v', "verify", "Verify the specified torrent", "v", false, NULL },
{ 'V', "version", "Show version number and exit", "V", false, NULL }, { 'V', "version", "Show version number and exit", "V", false, NULL },
@ -98,9 +97,12 @@ static struct tr_option const options[] =
static char const* getUsage(void) static char const* getUsage(void)
{ {
return "A fast and easy BitTorrent client\n" // clang-format off
return
"A fast and easy BitTorrent client\n"
"\n" "\n"
"Usage: " MY_READABLE_NAME " [options] <file|url|magnet>"; "Usage: " MY_READABLE_NAME " [options] <file|url|magnet>";
// clang-format on
} }
static int parseCommandLine(tr_variant*, int argc, char const** argv); static int parseCommandLine(tr_variant*, int argc, char const** argv);
@ -135,8 +137,14 @@ static char* tr_strlratio(char* buf, double ratio, size_t buflen)
static bool waitingOnWeb; static bool waitingOnWeb;
static void onTorrentFileDownloaded(tr_session* session, bool did_connect, bool did_timeout, long response_code, static void onTorrentFileDownloaded(
void const* response, size_t response_byte_count, void* ctor) tr_session* session,
bool did_connect,
bool did_timeout,
long response_code,
void const* response,
size_t response_byte_count,
void* ctor)
{ {
TR_UNUSED(session); TR_UNUSED(session);
TR_UNUSED(did_connect); TR_UNUSED(did_connect);
@ -155,7 +163,11 @@ static void getStatusStr(tr_stat const* st, char* buf, size_t buflen)
} }
else if (st->activity == TR_STATUS_CHECK) else if (st->activity == TR_STATUS_CHECK)
{ {
tr_snprintf(buf, buflen, "Verifying local files (%.2f%%, %.2f%% valid)", tr_truncd(100 * st->recheckProgress, 2), tr_snprintf(
buf,
buflen,
"Verifying local files (%.2f%%, %.2f%% valid)",
tr_truncd(100 * st->recheckProgress, 2),
tr_truncd(100 * st->percentDone, 2)); tr_truncd(100 * st->percentDone, 2));
} }
else if (st->activity == TR_STATUS_DOWNLOAD) else if (st->activity == TR_STATUS_DOWNLOAD)
@ -168,8 +180,16 @@ static void getStatusStr(tr_stat const* st, char* buf, size_t buflen)
tr_formatter_speed_KBps(dnStr, st->pieceDownloadSpeed_KBps, sizeof(dnStr)); tr_formatter_speed_KBps(dnStr, st->pieceDownloadSpeed_KBps, sizeof(dnStr));
tr_strlratio(ratioStr, st->ratio, sizeof(ratioStr)); tr_strlratio(ratioStr, st->ratio, sizeof(ratioStr));
tr_snprintf(buf, buflen, "Progress: %.1f%%, dl from %d of %d peers (%s), ul to %d (%s) [%s]", tr_snprintf(
tr_truncd(100 * st->percentDone, 1), st->peersSendingToUs, st->peersConnected, dnStr, st->peersGettingFromUs, upStr, buf,
buflen,
"Progress: %.1f%%, dl from %d of %d peers (%s), ul to %d (%s) [%s]",
tr_truncd(100 * st->percentDone, 1),
st->peersSendingToUs,
st->peersConnected,
dnStr,
st->peersGettingFromUs,
upStr,
ratioStr); ratioStr);
} }
else if (st->activity == TR_STATUS_SEED) else if (st->activity == TR_STATUS_SEED)
@ -180,8 +200,14 @@ static void getStatusStr(tr_stat const* st, char* buf, size_t buflen)
tr_formatter_speed_KBps(upStr, st->pieceUploadSpeed_KBps, sizeof(upStr)); tr_formatter_speed_KBps(upStr, st->pieceUploadSpeed_KBps, sizeof(upStr));
tr_strlratio(ratioStr, st->ratio, sizeof(ratioStr)); tr_strlratio(ratioStr, st->ratio, sizeof(ratioStr));
tr_snprintf(buf, buflen, "Seeding, uploading to %d of %d peer(s), %s [%s]", st->peersGettingFromUs, st->peersConnected, tr_snprintf(
upStr, ratioStr); buf,
buflen,
"Seeding, uploading to %d of %d peer(s), %s [%s]",
st->peersGettingFromUs,
st->peersConnected,
upStr,
ratioStr);
} }
else else
{ {
@ -262,8 +288,7 @@ int tr_main(int argc, char* argv[])
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (tr_variantDictFindStr(&settings, TR_KEY_download_dir, &str, NULL) && if (tr_variantDictFindStr(&settings, TR_KEY_download_dir, &str, NULL) && !tr_sys_path_exists(str, NULL))
!tr_sys_path_exists(str, NULL))
{ {
tr_error* error = NULL; tr_error* error = NULL;
@ -337,12 +362,11 @@ int tr_main(int argc, char* argv[])
{ {
char line[LINEWIDTH]; char line[LINEWIDTH];
tr_stat const* st; tr_stat const* st;
char const* messageName[] = char const* messageName[] = {
{
NULL, NULL,
"Tracker gave a warning:", "Tracker gave a warning:",
"Tracker gave an error:", "Tracker gave an error:",
"Error:" "Error:",
}; };
tr_wait_msec(200); tr_wait_msec(200);
@ -377,7 +401,7 @@ int tr_main(int argc, char* argv[])
} }
getStatusStr(st, line, sizeof(line)); getStatusStr(st, line, sizeof(line));
printf("\r%-*s", LINEWIDTH, line); printf("\r%-*s", TR_ARG_TUPLE(LINEWIDTH, line));
if (messageName[st->error]) if (messageName[st->error])
{ {

View File

@ -3,70 +3,69 @@
# Usage: ./code_style.sh # Usage: ./code_style.sh
# Usage: ./code_style.sh --check # Usage: ./code_style.sh --check
set -o noglob
if [[ "x$1" == *"check"* ]]; then if [[ "x$1" == *"check"* ]]; then
echo "checking code format" echo "checking code format"
else else
fix=1 fix=1
fi fi
root="$(git rev-parse --show-toplevel)" root="$(dirname "$0")"
if [ -n "${root}" ]; then root="$(cd "${root}" && pwd)"
cd "${root}" || exit 1 cd "${root}" || exit 1
fi
skipfiles=( cfile_includes=(
libtransmission/ConvertUTF\.[ch] '*.c'
libtransmission/jsonsl\.[ch] '*.cc'
libtransmission/wildmat\.c '*.h'
'*.m'
) )
cfile_candidates=( cfile_excludes=(
cli/*\.[ch] 'libtransmission/ConvertUTF.*'
daemon/*\.[ch] 'libtransmission/jsonsl.*'
gtk/*\.[ch] 'libtransmission/wildmat.*'
libtransmission/*\.[ch] 'macosx/Sparkle.framework/*'
qt/*\.cc 'macosx/VDKQueue/*'
qt/*\.h 'third-party/*'
tests/*/*\.cc 'web/*'
tests/*/*\.h
utils/*\.[ch]
) )
for file in "${cfile_candidates[@]}"; do
if [[ ! " ${skipfiles[*]} " =~ ${file} ]]; then get_find_path_args() {
cfiles+=("${file}"); local args=$(printf " -o -path ./%s" "$@")
fi echo "${args:4}"
done }
find_cfiles() {
find . \( $(get_find_path_args "${cfile_includes[@]}") \) ! \( $(get_find_path_args "${cfile_excludes[@]}") \) "$@"
}
# format C/C++ # format C/C++
cores=$(($(nproc) + 1)) clang_format_args="$([ -n "$fix" ] && echo '-i' || echo '--dry-run --Werror')"
if [ -n "$fix" ]; then if ! find_cfiles -exec clang-format $clang_format_args '{}' '+'; then
printf "%s\0" "${cfiles[@]}" | xargs -0 -P$cores -I FILE uncrustify -c uncrustify.cfg --no-backup -q FILE [ -n "$fix" ] || echo 'C/C++ code needs formatting'
else exitcode=1
printf "%s\0" "${cfiles[@]}" | xargs -0 -P$cores -I FILE uncrustify -c uncrustify.cfg --check FILE > /dev/null
if [ "${PIPESTATUS[1]}" -ne "0" ]; then
echo 'C/C++ code needs formatting'
exitcode=1
fi
fi fi
# enforce east const # enforce east const
matches="$(perl -ne 'print "west const:",$ARGV,":",$_ if /((?:^|[(,;]|\bstatic\s+)\s*)\b(const)\b(?!\s+\w+\s*\[)/' "${cfiles[@]}")" matches="$(find_cfiles -exec perl -ne 'print "west const:",$ARGV,":",$_ if /((?:^|[(,;]|\bstatic\s+)\s*)\b(const)\b(?!\s+\w+\s*\[)/' '{}' '+')"
if [ -n "$matches" ]; then if [ -n "$matches" ]; then
echo "$matches" echo "$matches"
exitcode=1 exitcode=1
fi fi
if [ -n "$fix" ]; then if [ -n "$fix" ]; then
perl -pi -e 's/((?:^|[(,;]|\bstatic\s+)\s*)\b(const)\b(?!\s+\w+\s*\[)/\1>\2</g' "${cfiles[@]}" find_cfiles -exec perl -pi -e 's/((?:^|[(,;]|\bstatic\s+)\s*)\b(const)\b(?!\s+\w+\s*\[)/\1>\2</g' '{}' '+'
fi fi
# format JS # format JS
cd "${root}/web" || exit 1 cd "${root}/web" || exit 1
if [ -n "$fix" ]; then yarn_args='--silent --no-progress --non-interactive'
cd "${root}/web" && yarn --silent install && yarn --silent 'lint:fix' yarn_lint_args="$([ -n "$fix" ] && echo 'lint:fix' || echo 'lint')"
elif ! yarn -s install; then if ! yarn $yarn_args install; then
echo 'JS code could not be checked -- "yarn install" failed' [ -n "$fix" ] || echo 'JS code could not be checked -- "yarn install" failed'
exitcode=1 exitcode=1
elif ! yarn --silent lint; then elif ! yarn $yarn_args $yarn_lint_args; then
echo 'JS code needs formatting' [ -n "$fix" ] || echo 'JS code needs formatting'
exitcode=1 exitcode=1
fi fi

View File

@ -61,13 +61,12 @@ static void do_log_system_error(char const* file, int line, tr_log_level level,
do \ do \
{ \ { \
DWORD const local_code = (code); \ DWORD const local_code = (code); \
\ \
if (tr_logLevelIsActive((level))) \ if (tr_logLevelIsActive((level))) \
{ \ { \
do_log_system_error(__FILE__, __LINE__, (level), local_code, (message)); \ do_log_system_error(__FILE__, __LINE__, (level), local_code, (message)); \
} \ } \
} \ } while (0)
while (0)
/*** /***
**** ****
@ -81,14 +80,19 @@ static BOOL WINAPI handle_console_ctrl(DWORD control_type)
return TRUE; return TRUE;
} }
static void update_service_status(DWORD new_state, DWORD win32_exit_code, DWORD service_specific_exit_code, DWORD check_point, static void update_service_status(
DWORD new_state,
DWORD win32_exit_code,
DWORD service_specific_exit_code,
DWORD check_point,
DWORD wait_hint) DWORD wait_hint)
{ {
SERVICE_STATUS status; SERVICE_STATUS status;
status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
status.dwCurrentState = new_state; status.dwCurrentState = new_state;
status.dwControlsAccepted = new_state != SERVICE_RUNNING ? 0 : SERVICE_ACCEPT_PRESHUTDOWN | SERVICE_ACCEPT_SHUTDOWN | status.dwControlsAccepted = new_state != SERVICE_RUNNING ?
SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PARAMCHANGE; 0 :
SERVICE_ACCEPT_PRESHUTDOWN | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PARAMCHANGE;
status.dwWin32ExitCode = service_specific_exit_code == 0 ? win32_exit_code : ERROR_SERVICE_SPECIFIC_ERROR; status.dwWin32ExitCode = service_specific_exit_code == 0 ? win32_exit_code : ERROR_SERVICE_SPECIFIC_ERROR;
status.dwServiceSpecificExitCode = service_specific_exit_code; status.dwServiceSpecificExitCode = service_specific_exit_code;
status.dwCheckPoint = check_point; status.dwCheckPoint = check_point;
@ -244,10 +248,9 @@ bool dtr_daemon(dtr_callbacks const* cb, void* cb_arg, bool foreground, int* exi
} }
else else
{ {
SERVICE_TABLE_ENTRY const service_table[] = SERVICE_TABLE_ENTRY const service_table[] = {
{
{ (LPWSTR)service_name, &service_main }, { (LPWSTR)service_name, &service_main },
{ NULL, NULL } { NULL, NULL },
}; };
if (!StartServiceCtrlDispatcherW(service_table)) if (!StartServiceCtrlDispatcherW(service_table))

View File

@ -91,7 +91,9 @@ static struct event_base* ev_base = NULL;
static char const* getUsage(void) static char const* getUsage(void)
{ {
return "Transmission " LONG_VERSION_STRING " https://transmissionbt.com/\n" // clang-format off
return
"Transmission " LONG_VERSION_STRING " https://transmissionbt.com/\n"
"A fast and easy BitTorrent client\n" "A fast and easy BitTorrent client\n"
"\n" "\n"
MY_NAME " is a headless Transmission session\n" MY_NAME " is a headless Transmission session\n"
@ -99,10 +101,10 @@ static char const* getUsage(void)
"or the web interface.\n" "or the web interface.\n"
"\n" "\n"
"Usage: " MY_NAME " [options]"; "Usage: " MY_NAME " [options]";
// clang-format on
} }
static struct tr_option const options[] = static struct tr_option const options[] = {
{
{ 'a', "allowed", "Allowed IP addresses. (Default: " TR_DEFAULT_RPC_WHITELIST ")", "a", true, "<list>" }, { 'a', "allowed", "Allowed IP addresses. (Default: " TR_DEFAULT_RPC_WHITELIST ")", "a", true, "<list>" },
{ 'b', "blocklist", "Enable peer blocklists", "b", false, NULL }, { 'b', "blocklist", "Enable peer blocklists", "b", false, NULL },
{ 'B', "no-blocklist", "Disable peer blocklists", "B", false, NULL }, { 'B', "no-blocklist", "Disable peer blocklists", "B", false, NULL },
@ -134,20 +136,36 @@ static struct tr_option const options[] =
{ 'P', "peerport", "Port for incoming peers (Default: " TR_DEFAULT_PEER_PORT_STR ")", "P", true, "<port>" }, { 'P', "peerport", "Port for incoming peers (Default: " TR_DEFAULT_PEER_PORT_STR ")", "P", true, "<port>" },
{ 'm', "portmap", "Enable portmapping via NAT-PMP or UPnP", "m", false, NULL }, { 'm', "portmap", "Enable portmapping via NAT-PMP or UPnP", "m", false, NULL },
{ 'M', "no-portmap", "Disable portmapping", "M", false, NULL }, { 'M', "no-portmap", "Disable portmapping", "M", false, NULL },
{ 'L', "peerlimit-global", "Maximum overall number of peers (Default: " TR_DEFAULT_PEER_LIMIT_GLOBAL_STR ")", "L", true, { 'L',
"<limit>" }, "peerlimit-global",
{ 'l', "peerlimit-torrent", "Maximum number of peers per torrent (Default: " TR_DEFAULT_PEER_LIMIT_TORRENT_STR ")", "l", "Maximum overall number of peers (Default: " TR_DEFAULT_PEER_LIMIT_GLOBAL_STR ")",
true, "<limit>" }, "L",
true,
"<limit>" },
{ 'l',
"peerlimit-torrent",
"Maximum number of peers per torrent (Default: " TR_DEFAULT_PEER_LIMIT_TORRENT_STR ")",
"l",
true,
"<limit>" },
{ 910, "encryption-required", "Encrypt all peer connections", "er", false, NULL }, { 910, "encryption-required", "Encrypt all peer connections", "er", false, NULL },
{ 911, "encryption-preferred", "Prefer encrypted peer connections", "ep", false, NULL }, { 911, "encryption-preferred", "Prefer encrypted peer connections", "ep", false, NULL },
{ 912, "encryption-tolerated", "Prefer unencrypted peer connections", "et", false, NULL }, { 912, "encryption-tolerated", "Prefer unencrypted peer connections", "et", false, NULL },
{ 'i', "bind-address-ipv4", "Where to listen for peer connections", "i", true, "<ipv4 addr>" }, { 'i', "bind-address-ipv4", "Where to listen for peer connections", "i", true, "<ipv4 addr>" },
{ 'I', "bind-address-ipv6", "Where to listen for peer connections", "I", true, "<ipv6 addr>" }, { 'I', "bind-address-ipv6", "Where to listen for peer connections", "I", true, "<ipv6 addr>" },
{ 'r', "rpc-bind-address", "Where to listen for RPC connections", "r", true, "<ip addr>" }, { 'r', "rpc-bind-address", "Where to listen for RPC connections", "r", true, "<ip addr>" },
{ 953, "global-seedratio", "All torrents, unless overridden by a per-torrent setting, should seed until a specific ratio", { 953,
"gsr", true, "ratio" }, "global-seedratio",
{ 954, "no-global-seedratio", "All torrents, unless overridden by a per-torrent setting, should seed regardless of ratio", "All torrents, unless overridden by a per-torrent setting, should seed until a specific ratio",
"GSR", false, NULL }, "gsr",
true,
"ratio" },
{ 954,
"no-global-seedratio",
"All torrents, unless overridden by a per-torrent setting, should seed regardless of ratio",
"GSR",
false,
NULL },
{ 'x', "pid-file", "Enable PID file", "x", true, "<pid-file>" }, { 'x', "pid-file", "Enable PID file", "x", true, "<pid-file>" },
{ 0, NULL, NULL, NULL, false, NULL } { 0, NULL, NULL, NULL, false, NULL }
}; };
@ -156,8 +174,11 @@ static bool reopen_log_file(char const* filename)
{ {
tr_error* error = NULL; tr_error* error = NULL;
tr_sys_file_t const old_log_file = logfile; tr_sys_file_t const old_log_file = logfile;
tr_sys_file_t const new_log_file = tr_sys_file_open(filename, TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE | TR_SYS_FILE_APPEND, tr_sys_file_t const new_log_file = tr_sys_file_open(
0666, &error); filename,
TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE | TR_SYS_FILE_APPEND,
0666,
&error);
if (new_log_file == TR_BAD_SYS_FILE) if (new_log_file == TR_BAD_SYS_FILE)
{ {
@ -359,7 +380,10 @@ static void periodicUpdate(evutil_socket_t fd, short what, void* context)
reportStatus(); reportStatus();
} }
static tr_rpc_callback_status on_rpc_callback(tr_session* session, tr_rpc_callback_type type, struct tr_torrent* tor, static tr_rpc_callback_status on_rpc_callback(
tr_session* session,
tr_rpc_callback_type type,
struct tr_torrent* tor,
void* user_data) void* user_data)
{ {
TR_UNUSED(session); TR_UNUSED(session);
@ -374,7 +398,13 @@ static tr_rpc_callback_status on_rpc_callback(tr_session* session, tr_rpc_callba
return TR_RPC_OK; return TR_RPC_OK;
} }
static bool parse_args(int argc, char const** argv, tr_variant* settings, bool* paused, bool* dump_settings, bool* foreground, static bool parse_args(
int argc,
char const** argv,
tr_variant* settings,
bool* paused,
bool* dump_settings,
bool* foreground,
int* exit_code) int* exit_code)
{ {
int c; int c;
@ -668,7 +698,10 @@ static int daemon_start(void* raw_arg, bool foreground)
if (!tr_str_is_empty(pid_filename)) if (!tr_str_is_empty(pid_filename))
{ {
tr_error* error = NULL; tr_error* error = NULL;
tr_sys_file_t fp = tr_sys_file_open(pid_filename, TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE | TR_SYS_FILE_TRUNCATE, 0666, tr_sys_file_t fp = tr_sys_file_open(
pid_filename,
TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE | TR_SYS_FILE_TRUNCATE,
0666,
&error); &error);
if (fp != TR_BAD_SYS_FILE) if (fp != TR_BAD_SYS_FILE)
@ -872,8 +905,7 @@ int tr_main(int argc, char* argv[])
return ret; return ret;
} }
dtr_callbacks const cb = dtr_callbacks const cb = {
{
.on_start = &daemon_start, .on_start = &daemon_start,
.on_stop = &daemon_stop, .on_stop = &daemon_stop,
.on_reconfigure = &daemon_reconfigure, .on_reconfigure = &daemon_reconfigure,

View File

@ -12,10 +12,9 @@ struct tr_error;
typedef struct dtr_callbacks typedef struct dtr_callbacks
{ {
int (* on_start)(void* arg, bool foreground); int (*on_start)(void* arg, bool foreground);
void (* on_stop)(void* arg); void (*on_stop)(void* arg);
void (* on_reconfigure)(void* arg); void (*on_reconfigure)(void* arg);
} } dtr_callbacks;
dtr_callbacks;
bool dtr_daemon(dtr_callbacks const* cb, void* cb_arg, bool foreground, int* exit_code, struct tr_error** error); bool dtr_daemon(dtr_callbacks const* cb, void* cb_arg, bool foreground, int* exit_code, struct tr_error** error);

View File

@ -4,7 +4,10 @@ services:
code_style: code_style:
build: docker/code_style build: docker/code_style
volumes: volumes:
- .:/src - .:/src
- ./code_style.sh:/code_style.sh:ro working_dir: /src
- ./format:/format:ro command:
command: ["/bin/bash", "-c", "cd /src && ./code_style.sh --check"] - ./code_style.sh
- --check
environment:
HOME: /tmp

View File

@ -1,3 +1,20 @@
FROM alpine FROM mikedld/clang-format:12-debian AS clang_format
RUN apk add --no-cache bash git perl uncrustify yarn FROM debian:bullseye-slim AS final
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates \
curl \
gnupg2 \
&& curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
&& echo "deb https://dl.yarnpkg.com/debian/ stable main" >> /etc/apt/sources.list.d/yarn.list \
&& apt-get update \
&& apt-get install -y --no-install-recommends \
bash \
nodejs \
perl \
yarn \
&& rm -rf /var/lib/apt/lists/*
COPY --from=clang_format /usr/bin/clang-format /usr/bin/

View File

@ -26,8 +26,7 @@ static void action_cb(GtkAction* a, gpointer user_data)
gtr_actions_handler(gtk_action_get_name(a), user_data); gtr_actions_handler(gtk_action_get_name(a), user_data);
} }
static GtkRadioActionEntry sort_radio_entries[] = static GtkRadioActionEntry sort_radio_entries[] = {
{
{ "sort-by-activity", NULL, N_("Sort by _Activity"), NULL, NULL, 0 }, { "sort-by-activity", NULL, N_("Sort by _Activity"), NULL, NULL, 0 },
{ "sort-by-name", NULL, N_("Sort by _Name"), NULL, NULL, 1 }, { "sort-by-name", NULL, N_("Sort by _Name"), NULL, NULL, 1 },
{ "sort-by-progress", NULL, N_("Sort by _Progress"), NULL, NULL, 2 }, { "sort-by-progress", NULL, N_("Sort by _Progress"), NULL, NULL, 2 },
@ -36,7 +35,7 @@ static GtkRadioActionEntry sort_radio_entries[] =
{ "sort-by-state", NULL, N_("Sort by Stat_e"), NULL, NULL, 5 }, { "sort-by-state", NULL, N_("Sort by Stat_e"), NULL, NULL, 5 },
{ "sort-by-age", NULL, N_("Sort by A_ge"), NULL, NULL, 6 }, { "sort-by-age", NULL, N_("Sort by A_ge"), NULL, NULL, 6 },
{ "sort-by-time-left", NULL, N_("Sort by Time _Left"), NULL, NULL, 7 }, { "sort-by-time-left", NULL, N_("Sort by Time _Left"), NULL, NULL, 7 },
{ "sort-by-size", NULL, N_("Sort by Si_ze"), NULL, NULL, 8 } { "sort-by-size", NULL, N_("Sort by Si_ze"), NULL, NULL, 8 },
}; };
static void sort_changed_cb(GtkAction* action, GtkRadioAction* current, gpointer user_data) static void sort_changed_cb(GtkAction* action, GtkRadioAction* current, gpointer user_data)
@ -51,10 +50,9 @@ static void sort_changed_cb(GtkAction* action, GtkRadioAction* current, gpointer
gtr_core_set_pref(myCore, key, val); gtr_core_set_pref(myCore, key, val);
} }
static GtkToggleActionEntry show_toggle_entries[] = static GtkToggleActionEntry show_toggle_entries[] = {
{
{ "toggle-main-window", NULL, N_("_Show Transmission"), NULL, NULL, G_CALLBACK(action_cb), TRUE }, { "toggle-main-window", NULL, N_("_Show Transmission"), NULL, NULL, G_CALLBACK(action_cb), TRUE },
{ "toggle-message-log", NULL, N_("Message _Log"), NULL, NULL, G_CALLBACK(action_cb), FALSE } { "toggle-message-log", NULL, N_("Message _Log"), NULL, NULL, G_CALLBACK(action_cb), FALSE },
}; };
static void toggle_pref_cb(GtkToggleAction* action, gpointer user_data) static void toggle_pref_cb(GtkToggleAction* action, gpointer user_data)
@ -67,18 +65,16 @@ static void toggle_pref_cb(GtkToggleAction* action, gpointer user_data)
gtr_core_set_pref_bool(myCore, tr_quark_new(key, TR_BAD_SIZE), val); gtr_core_set_pref_bool(myCore, tr_quark_new(key, TR_BAD_SIZE), val);
} }
static GtkToggleActionEntry pref_toggle_entries[] = static GtkToggleActionEntry pref_toggle_entries[] = {
{
{ "alt-speed-enabled", NULL, N_("Enable Alternative Speed _Limits"), NULL, NULL, G_CALLBACK(toggle_pref_cb), FALSE }, { "alt-speed-enabled", NULL, N_("Enable Alternative Speed _Limits"), NULL, NULL, G_CALLBACK(toggle_pref_cb), FALSE },
{ "compact-view", NULL, N_("_Compact View"), "<alt>C", NULL, G_CALLBACK(toggle_pref_cb), FALSE }, { "compact-view", NULL, N_("_Compact View"), "<alt>C", NULL, G_CALLBACK(toggle_pref_cb), FALSE },
{ "sort-reversed", NULL, N_("Re_verse Sort Order"), NULL, NULL, G_CALLBACK(toggle_pref_cb), FALSE }, { "sort-reversed", NULL, N_("Re_verse Sort Order"), NULL, NULL, G_CALLBACK(toggle_pref_cb), FALSE },
{ "show-filterbar", NULL, N_("_Filterbar"), NULL, NULL, G_CALLBACK(toggle_pref_cb), FALSE }, { "show-filterbar", NULL, N_("_Filterbar"), NULL, NULL, G_CALLBACK(toggle_pref_cb), FALSE },
{ "show-statusbar", NULL, N_("_Statusbar"), NULL, NULL, G_CALLBACK(toggle_pref_cb), FALSE }, { "show-statusbar", NULL, N_("_Statusbar"), NULL, NULL, G_CALLBACK(toggle_pref_cb), FALSE },
{ "show-toolbar", NULL, N_("_Toolbar"), NULL, NULL, G_CALLBACK(toggle_pref_cb), FALSE } { "show-toolbar", NULL, N_("_Toolbar"), NULL, NULL, G_CALLBACK(toggle_pref_cb), FALSE },
}; };
static GtkActionEntry entries[] = static GtkActionEntry entries[] = {
{
{ "file-menu", NULL, N_("_File"), NULL, NULL, NULL }, { "file-menu", NULL, N_("_File"), NULL, NULL, NULL },
{ "torrent-menu", NULL, N_("_Torrent"), NULL, NULL, NULL }, { "torrent-menu", NULL, N_("_Torrent"), NULL, NULL, NULL },
{ "view-menu", NULL, N_("_View"), NULL, NULL, NULL }, { "view-menu", NULL, N_("_View"), NULL, NULL, NULL },
@ -91,8 +87,12 @@ static GtkActionEntry entries[] =
{ "open-torrent-toolbar", "document-open", N_("_Open"), NULL, N_("Open a torrent"), G_CALLBACK(action_cb) }, { "open-torrent-toolbar", "document-open", N_("_Open"), NULL, N_("Open a torrent"), G_CALLBACK(action_cb) },
{ "open-torrent-menu", "document-open", N_("_Open"), NULL, N_("Open a torrent"), G_CALLBACK(action_cb) }, { "open-torrent-menu", "document-open", N_("_Open"), NULL, N_("Open a torrent"), G_CALLBACK(action_cb) },
{ "torrent-start", "media-playback-start", N_("_Start"), "<control>S", N_("Start torrent"), G_CALLBACK(action_cb) }, { "torrent-start", "media-playback-start", N_("_Start"), "<control>S", N_("Start torrent"), G_CALLBACK(action_cb) },
{ "torrent-start-now", "media-playback-start", N_("Start _Now"), "<shift><control>S", N_("Start torrent now"), { "torrent-start-now",
G_CALLBACK(action_cb) }, "media-playback-start",
N_("Start _Now"),
"<shift><control>S",
N_("Start torrent now"),
G_CALLBACK(action_cb) },
{ "show-stats", NULL, N_("_Statistics"), NULL, NULL, G_CALLBACK(action_cb) }, { "show-stats", NULL, N_("_Statistics"), NULL, NULL, G_CALLBACK(action_cb) },
{ "donate", NULL, N_("_Donate"), NULL, NULL, G_CALLBACK(action_cb) }, { "donate", NULL, N_("_Donate"), NULL, NULL, G_CALLBACK(action_cb) },
{ "torrent-verify", NULL, N_("_Verify Local Data"), "<control>V", NULL, G_CALLBACK(action_cb) }, { "torrent-verify", NULL, N_("_Verify Local Data"), "<control>V", NULL, G_CALLBACK(action_cb) },
@ -107,8 +107,12 @@ static GtkActionEntry entries[] =
{ "select-all", "edit-select-all", N_("Select _All"), "<control>A", NULL, G_CALLBACK(action_cb) }, { "select-all", "edit-select-all", N_("Select _All"), "<control>A", NULL, G_CALLBACK(action_cb) },
{ "deselect-all", NULL, N_("Dese_lect All"), "<shift><control>A", NULL, G_CALLBACK(action_cb) }, { "deselect-all", NULL, N_("Dese_lect All"), "<shift><control>A", NULL, G_CALLBACK(action_cb) },
{ "edit-preferences", "preferences-system", N_("_Preferences"), NULL, NULL, G_CALLBACK(action_cb) }, { "edit-preferences", "preferences-system", N_("_Preferences"), NULL, NULL, G_CALLBACK(action_cb) },
{ "show-torrent-properties", "document-properties", N_("_Properties"), "<alt>Return", N_("Torrent properties"), G_CALLBACK( { "show-torrent-properties",
action_cb) }, "document-properties",
N_("_Properties"),
"<alt>Return",
N_("Torrent properties"),
G_CALLBACK(action_cb) },
{ "open-torrent-folder", "document-open", N_("Open Fold_er"), "<control>E", NULL, G_CALLBACK(action_cb) }, { "open-torrent-folder", "document-open", N_("Open Fold_er"), "<control>E", NULL, G_CALLBACK(action_cb) },
{ "show-about-dialog", "help-about", N_("_About"), NULL, NULL, G_CALLBACK(action_cb) }, { "show-about-dialog", "help-about", N_("_About"), NULL, NULL, G_CALLBACK(action_cb) },
{ "help", "help-browser", N_("_Contents"), "F1", NULL, G_CALLBACK(action_cb) }, { "help", "help-browser", N_("_Contents"), "F1", NULL, G_CALLBACK(action_cb) },
@ -117,26 +121,24 @@ static GtkActionEntry entries[] =
{ "queue-move-up", "go-up", N_("Move _Up"), "<control>Up", NULL, G_CALLBACK(action_cb) }, { "queue-move-up", "go-up", N_("Move _Up"), "<control>Up", NULL, G_CALLBACK(action_cb) },
{ "queue-move-down", "go-down", N_("Move _Down"), "<control>Down", NULL, G_CALLBACK(action_cb) }, { "queue-move-down", "go-down", N_("Move _Down"), "<control>Down", NULL, G_CALLBACK(action_cb) },
{ "queue-move-bottom", "go-bottom", N_("Move to _Bottom"), NULL, NULL, G_CALLBACK(action_cb) }, { "queue-move-bottom", "go-bottom", N_("Move to _Bottom"), NULL, NULL, G_CALLBACK(action_cb) },
{ "present-main-window", NULL, N_("Present Main Window"), NULL, NULL, G_CALLBACK(action_cb) } { "present-main-window", NULL, N_("Present Main Window"), NULL, NULL, G_CALLBACK(action_cb) },
}; };
typedef struct typedef struct
{ {
char const* filename; char const* filename;
char const* name; char const* name;
} } BuiltinIconInfo;
BuiltinIconInfo;
static BuiltinIconInfo const my_fallback_icons[] = static BuiltinIconInfo const my_fallback_icons[] = {
{ { "logo-48", WINDOW_ICON }, //
{ "logo-48", WINDOW_ICON }, { "logo-24", TRAY_ICON }, //
{ "logo-24", TRAY_ICON }, { "logo-48", NOTIFICATION_ICON }, //
{ "logo-48", NOTIFICATION_ICON }, { "lock", "transmission-lock" }, //
{ "lock", "transmission-lock" }, { "utilities", "utilities" }, //
{ "utilities", "utilities" }, { "turtle-blue", "alt-speed-on" }, //
{ "turtle-blue", "alt-speed-on" }, { "turtle-grey", "alt-speed-off" }, //
{ "turtle-grey", "alt-speed-off" }, { "ratio", "ratio" }, //
{ "ratio", "ratio" }
}; };
static void register_my_icons(void) static void register_my_icons(void)
@ -210,10 +212,18 @@ void gtr_actions_init(GtkUIManager* ui_manager, gpointer callback_user_data)
} }
} }
gtk_action_group_add_radio_actions(action_group, sort_radio_entries, G_N_ELEMENTS(sort_radio_entries), active, gtk_action_group_add_radio_actions(
G_CALLBACK(sort_changed_cb), NULL); action_group,
sort_radio_entries,
G_N_ELEMENTS(sort_radio_entries),
active,
G_CALLBACK(sort_changed_cb),
NULL);
gtk_action_group_add_toggle_actions(action_group, show_toggle_entries, G_N_ELEMENTS(show_toggle_entries), gtk_action_group_add_toggle_actions(
action_group,
show_toggle_entries,
G_N_ELEMENTS(show_toggle_entries),
callback_user_data); callback_user_data);
for (size_t i = 0; i < G_N_ELEMENTS(pref_toggle_entries); ++i) for (size_t i = 0; i < G_N_ELEMENTS(pref_toggle_entries); ++i)
@ -221,7 +231,10 @@ void gtr_actions_init(GtkUIManager* ui_manager, gpointer callback_user_data)
pref_toggle_entries[i].is_active = gtr_pref_flag_get(tr_quark_new(pref_toggle_entries[i].name, TR_BAD_SIZE)); pref_toggle_entries[i].is_active = gtr_pref_flag_get(tr_quark_new(pref_toggle_entries[i].name, TR_BAD_SIZE));
} }
gtk_action_group_add_toggle_actions(action_group, pref_toggle_entries, G_N_ELEMENTS(pref_toggle_entries), gtk_action_group_add_toggle_actions(
action_group,
pref_toggle_entries,
G_N_ELEMENTS(pref_toggle_entries),
callback_user_data); callback_user_data);
gtk_action_group_add_actions(action_group, entries, n_entries, callback_user_data); gtk_action_group_add_actions(action_group, entries, n_entries, callback_user_data);

View File

@ -477,9 +477,9 @@ static void onComboEnumChanged(GtkComboBox* combo_box, struct DetailsImpl* di)
static GtkWidget* ratio_combo_new(void) static GtkWidget* ratio_combo_new(void)
{ {
GtkWidget* w = gtr_combo_box_new_enum( GtkWidget* w = gtr_combo_box_new_enum(
_("Use global settings"), TR_RATIOLIMIT_GLOBAL, TR_ARG_TUPLE(_("Use global settings"), TR_RATIOLIMIT_GLOBAL),
_("Seed regardless of ratio"), TR_RATIOLIMIT_UNLIMITED, TR_ARG_TUPLE(_("Seed regardless of ratio"), TR_RATIOLIMIT_UNLIMITED),
_("Stop seeding at ratio:"), TR_RATIOLIMIT_SINGLE, TR_ARG_TUPLE(_("Stop seeding at ratio:"), TR_RATIOLIMIT_SINGLE),
NULL); NULL);
g_object_set_qdata(G_OBJECT(w), ARG_KEY, GINT_TO_POINTER(TR_KEY_seedRatioMode)); g_object_set_qdata(G_OBJECT(w), ARG_KEY, GINT_TO_POINTER(TR_KEY_seedRatioMode));
return w; return w;
@ -488,9 +488,9 @@ static GtkWidget* ratio_combo_new(void)
static GtkWidget* idle_combo_new(void) static GtkWidget* idle_combo_new(void)
{ {
GtkWidget* w = gtr_combo_box_new_enum( GtkWidget* w = gtr_combo_box_new_enum(
_("Use global settings"), TR_IDLELIMIT_GLOBAL, TR_ARG_TUPLE(_("Use global settings"), TR_IDLELIMIT_GLOBAL),
_("Seed regardless of activity"), TR_IDLELIMIT_UNLIMITED, TR_ARG_TUPLE(_("Seed regardless of activity"), TR_IDLELIMIT_UNLIMITED),
_("Stop seeding if idle for N minutes:"), TR_IDLELIMIT_SINGLE, TR_ARG_TUPLE(_("Stop seeding if idle for N minutes:"), TR_IDLELIMIT_SINGLE),
NULL); NULL);
g_object_set_qdata(G_OBJECT(w), ARG_KEY, GINT_TO_POINTER(TR_KEY_seedIdleMode)); g_object_set_qdata(G_OBJECT(w), ARG_KEY, GINT_TO_POINTER(TR_KEY_seedIdleMode));
return w; return w;
@ -908,8 +908,13 @@ static void refreshInfo(struct DetailsImpl* di, tr_torrent** torrents, int n)
{ {
char piecebuf[128]; char piecebuf[128];
tr_formatter_mem_B(piecebuf, pieceSize, sizeof(piecebuf)); tr_formatter_mem_B(piecebuf, pieceSize, sizeof(piecebuf));
g_snprintf(buf, sizeof(buf), ngettext("%1$s (%2$'d piece @ %3$s)", "%1$s (%2$'d pieces @ %3$s)", pieces), sizebuf, g_snprintf(
pieces, piecebuf); buf,
sizeof(buf),
ngettext("%1$s (%2$'d piece @ %3$s)", "%1$s (%2$'d pieces @ %3$s)", pieces),
sizebuf,
pieces,
piecebuf);
str = buf; str = buf;
} }
else else
@ -966,7 +971,13 @@ static void refreshInfo(struct DetailsImpl* di, tr_torrent** torrents, int n)
} }
else else
{ {
g_snprintf(buf, sizeof(buf), _("%1$s (%2$s%% of %3$s%% Available); %4$s Unverified"), total, buf2, avail, g_snprintf(
buf,
sizeof(buf),
_("%1$s (%2$s%% of %3$s%% Available); %4$s Unverified"),
total,
buf2,
avail,
unver); unver);
} }
@ -1258,7 +1269,8 @@ static char const* getWebseedColumnNames(int column)
static GtkListStore* webseed_model_new(void) static GtkListStore* webseed_model_new(void)
{ {
return gtk_list_store_new(N_WEBSEED_COLS, return gtk_list_store_new(
N_WEBSEED_COLS,
G_TYPE_STRING, /* key */ G_TYPE_STRING, /* key */
G_TYPE_BOOLEAN, /* was-updated */ G_TYPE_BOOLEAN, /* was-updated */
G_TYPE_STRING, /* url */ G_TYPE_STRING, /* url */
@ -1351,7 +1363,8 @@ static char const* getPeerColumnName(int column)
static GtkListStore* peer_store_new(void) static GtkListStore* peer_store_new(void)
{ {
return gtk_list_store_new(N_PEER_COLS, return gtk_list_store_new(
N_PEER_COLS,
G_TYPE_STRING, /* key */ G_TYPE_STRING, /* key */
G_TYPE_BOOLEAN, /* was-updated */ G_TYPE_BOOLEAN, /* was-updated */
G_TYPE_STRING, /* address */ G_TYPE_STRING, /* address */
@ -1379,7 +1392,11 @@ static GtkListStore* peer_store_new(void)
G_TYPE_STRING); /* torrent name */ G_TYPE_STRING); /* torrent name */
} }
static void initPeerRow(GtkListStore* store, GtkTreeIter* iter, char const* key, char const* torrentName, static void initPeerRow(
GtkListStore* store,
GtkTreeIter* iter,
char const* key,
char const* torrentName,
tr_peer_stat const* peer) tr_peer_stat const* peer)
{ {
g_return_if_fail(peer != NULL); g_return_if_fail(peer != NULL);
@ -1401,13 +1418,15 @@ static void initPeerRow(GtkListStore* store, GtkTreeIter* iter, char const* key,
g_snprintf(collated_name, sizeof(collated_name), "%03d.%03d.%03d.%03d", q[0], q[1], q[2], q[3]); g_snprintf(collated_name, sizeof(collated_name), "%03d.%03d.%03d.%03d", q[0], q[1], q[2], q[3]);
} }
gtk_list_store_set(store, iter, gtk_list_store_set(
PEER_COL_ADDRESS, peer->addr, store,
PEER_COL_ADDRESS_COLLATED, collated_name, iter,
PEER_COL_CLIENT, client, TR_ARG_TUPLE(PEER_COL_ADDRESS, peer->addr),
PEER_COL_ENCRYPTION_STOCK_ID, peer->isEncrypted ? "transmission-lock" : NULL, TR_ARG_TUPLE(PEER_COL_ADDRESS_COLLATED, collated_name),
PEER_COL_KEY, key, TR_ARG_TUPLE(PEER_COL_CLIENT, client),
PEER_COL_TORRENT_NAME, torrentName, TR_ARG_TUPLE(PEER_COL_ENCRYPTION_STOCK_ID, peer->isEncrypted ? "transmission-lock" : NULL),
TR_ARG_TUPLE(PEER_COL_KEY, key),
TR_ARG_TUPLE(PEER_COL_TORRENT_NAME, torrentName),
-1); -1);
} }
@ -1464,26 +1483,28 @@ static void refreshPeerRow(GtkListStore* store, GtkTreeIter* iter, tr_peer_stat
g_snprintf(cancelled_by_peer, sizeof(cancelled_by_peer), "%" PRIu32, peer->cancelsToClient); g_snprintf(cancelled_by_peer, sizeof(cancelled_by_peer), "%" PRIu32, peer->cancelsToClient);
} }
gtk_list_store_set(store, iter, gtk_list_store_set(
PEER_COL_PROGRESS, (int)(100.0 * peer->progress), store,
PEER_COL_UPLOAD_REQUEST_COUNT_INT, peer->pendingReqsToClient, iter,
PEER_COL_UPLOAD_REQUEST_COUNT_STRING, up_count, TR_ARG_TUPLE(PEER_COL_PROGRESS, (int)(100.0 * peer->progress)),
PEER_COL_DOWNLOAD_REQUEST_COUNT_INT, peer->pendingReqsToPeer, TR_ARG_TUPLE(PEER_COL_UPLOAD_REQUEST_COUNT_INT, peer->pendingReqsToClient),
PEER_COL_DOWNLOAD_REQUEST_COUNT_STRING, down_count, TR_ARG_TUPLE(PEER_COL_UPLOAD_REQUEST_COUNT_STRING, up_count),
PEER_COL_DOWNLOAD_RATE_DOUBLE, peer->rateToClient_KBps, TR_ARG_TUPLE(PEER_COL_DOWNLOAD_REQUEST_COUNT_INT, peer->pendingReqsToPeer),
PEER_COL_DOWNLOAD_RATE_STRING, down_speed, TR_ARG_TUPLE(PEER_COL_DOWNLOAD_REQUEST_COUNT_STRING, down_count),
PEER_COL_UPLOAD_RATE_DOUBLE, peer->rateToPeer_KBps, TR_ARG_TUPLE(PEER_COL_DOWNLOAD_RATE_DOUBLE, peer->rateToClient_KBps),
PEER_COL_UPLOAD_RATE_STRING, up_speed, TR_ARG_TUPLE(PEER_COL_DOWNLOAD_RATE_STRING, down_speed),
PEER_COL_FLAGS, peer->flagStr, TR_ARG_TUPLE(PEER_COL_UPLOAD_RATE_DOUBLE, peer->rateToPeer_KBps),
PEER_COL_WAS_UPDATED, TRUE, TR_ARG_TUPLE(PEER_COL_UPLOAD_RATE_STRING, up_speed),
PEER_COL_BLOCKS_DOWNLOADED_COUNT_INT, (int)peer->blocksToClient, TR_ARG_TUPLE(PEER_COL_FLAGS, peer->flagStr),
PEER_COL_BLOCKS_DOWNLOADED_COUNT_STRING, blocks_to_client, TR_ARG_TUPLE(PEER_COL_WAS_UPDATED, TRUE),
PEER_COL_BLOCKS_UPLOADED_COUNT_INT, (int)peer->blocksToPeer, TR_ARG_TUPLE(PEER_COL_BLOCKS_DOWNLOADED_COUNT_INT, (int)peer->blocksToClient),
PEER_COL_BLOCKS_UPLOADED_COUNT_STRING, blocks_to_peer, TR_ARG_TUPLE(PEER_COL_BLOCKS_DOWNLOADED_COUNT_STRING, blocks_to_client),
PEER_COL_REQS_CANCELLED_BY_CLIENT_COUNT_INT, (int)peer->cancelsToPeer, TR_ARG_TUPLE(PEER_COL_BLOCKS_UPLOADED_COUNT_INT, (int)peer->blocksToPeer),
PEER_COL_REQS_CANCELLED_BY_CLIENT_COUNT_STRING, cancelled_by_client, TR_ARG_TUPLE(PEER_COL_BLOCKS_UPLOADED_COUNT_STRING, blocks_to_peer),
PEER_COL_REQS_CANCELLED_BY_PEER_COUNT_INT, (int)peer->cancelsToClient, TR_ARG_TUPLE(PEER_COL_REQS_CANCELLED_BY_CLIENT_COUNT_INT, (int)peer->cancelsToPeer),
PEER_COL_REQS_CANCELLED_BY_PEER_COUNT_STRING, cancelled_by_peer, TR_ARG_TUPLE(PEER_COL_REQS_CANCELLED_BY_CLIENT_COUNT_STRING, cancelled_by_client),
TR_ARG_TUPLE(PEER_COL_REQS_CANCELLED_BY_PEER_COUNT_INT, (int)peer->cancelsToClient),
TR_ARG_TUPLE(PEER_COL_REQS_CANCELLED_BY_PEER_COUNT_STRING, cancelled_by_peer),
-1); -1);
} }
@ -1510,8 +1531,7 @@ static void refreshPeerList(struct DetailsImpl* di, tr_torrent** torrents, int n
do do
{ {
gtk_list_store_set(store, &iter, PEER_COL_WAS_UPDATED, FALSE, -1); gtk_list_store_set(store, &iter, PEER_COL_WAS_UPDATED, FALSE, -1);
} } while (gtk_tree_model_iter_next(model, &iter));
while (gtk_tree_model_iter_next(model, &iter));
} }
/* step 3: add any new peers */ /* step 3: add any new peers */
@ -1608,8 +1628,7 @@ static void refreshWebseedList(struct DetailsImpl* di, tr_torrent** torrents, in
do do
{ {
gtk_list_store_set(store, &iter, WEBSEED_COL_WAS_UPDATED, FALSE, -1); gtk_list_store_set(store, &iter, WEBSEED_COL_WAS_UPDATED, FALSE, -1);
} } while (gtk_tree_model_iter_next(model, &iter));
while (gtk_tree_model_iter_next(model, &iter));
} }
/* step 2: add any new webseeds */ /* step 2: add any new webseeds */
@ -1630,10 +1649,7 @@ static void refreshWebseedList(struct DetailsImpl* di, tr_torrent** torrents, in
{ {
GtkTreePath* p; GtkTreePath* p;
gtk_list_store_append(store, &iter); gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter, gtk_list_store_set(store, &iter, TR_ARG_TUPLE(WEBSEED_COL_URL, url), TR_ARG_TUPLE(WEBSEED_COL_KEY, key), -1);
WEBSEED_COL_URL, url,
WEBSEED_COL_KEY, key,
-1);
p = gtk_tree_model_get_path(model, &iter); p = gtk_tree_model_get_path(model, &iter);
g_hash_table_insert(hash, g_strdup(key), gtk_tree_row_reference_new(model, p)); g_hash_table_insert(hash, g_strdup(key), gtk_tree_row_reference_new(model, p));
gtk_tree_path_free(p); gtk_tree_path_free(p);
@ -1664,10 +1680,12 @@ static void refreshWebseedList(struct DetailsImpl* di, tr_torrent** torrents, in
tr_formatter_speed_KBps(buf, speeds_KBps[j], sizeof(buf)); tr_formatter_speed_KBps(buf, speeds_KBps[j], sizeof(buf));
} }
gtk_list_store_set(store, &iter, gtk_list_store_set(
WEBSEED_COL_DOWNLOAD_RATE_DOUBLE, speeds_KBps[j], store,
WEBSEED_COL_DOWNLOAD_RATE_STRING, buf, &iter,
WEBSEED_COL_WAS_UPDATED, TRUE, TR_ARG_TUPLE(WEBSEED_COL_DOWNLOAD_RATE_DOUBLE, speeds_KBps[j]),
TR_ARG_TUPLE(WEBSEED_COL_DOWNLOAD_RATE_STRING, buf),
TR_ARG_TUPLE(WEBSEED_COL_WAS_UPDATED, TRUE),
-1); -1);
gtk_tree_path_free(p); gtk_tree_path_free(p);
@ -1717,7 +1735,12 @@ static void refreshPeers(struct DetailsImpl* di, tr_torrent** torrents, int n)
refreshWebseedList(di, torrents, n); refreshWebseedList(di, torrents, n);
} }
static gboolean onPeerViewQueryTooltip(GtkWidget* widget, gint x, gint y, gboolean keyboard_tip, GtkTooltip* tooltip, static gboolean onPeerViewQueryTooltip(
GtkWidget* widget,
gint x,
gint y,
gboolean keyboard_tip,
GtkTooltip* tooltip,
gpointer gdi) gpointer gdi)
{ {
GtkTreeIter iter; GtkTreeIter iter;
@ -1732,10 +1755,12 @@ static gboolean onPeerViewQueryTooltip(GtkWidget* widget, gint x, gint y, gboole
struct DetailsImpl* di = gdi; struct DetailsImpl* di = gdi;
GString* gstr = di->gstr; GString* gstr = di->gstr;
gtk_tree_model_get(model, &iter, gtk_tree_model_get(
PEER_COL_TORRENT_NAME, &name, model,
PEER_COL_ADDRESS, &addr, &iter,
PEER_COL_FLAGS, &flagstr, TR_ARG_TUPLE(PEER_COL_TORRENT_NAME, &name),
TR_ARG_TUPLE(PEER_COL_ADDRESS, &addr),
TR_ARG_TUPLE(PEER_COL_FLAGS, &flagstr),
-1); -1);
g_string_truncate(gstr, 0); g_string_truncate(gstr, 0);
@ -2064,11 +2089,17 @@ static GtkWidget* peer_page_new(struct DetailsImpl* di)
gtk_box_pack_start(GTK_BOX(vbox), w, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), w, FALSE, FALSE, 0);
/* ip-to-GtkTreeRowReference */ /* ip-to-GtkTreeRowReference */
di->peer_hash = g_hash_table_new_full(g_str_hash, g_str_equal, (GDestroyNotify)g_free, di->peer_hash = g_hash_table_new_full(
g_str_hash,
g_str_equal,
(GDestroyNotify)g_free,
(GDestroyNotify)gtk_tree_row_reference_free); (GDestroyNotify)gtk_tree_row_reference_free);
/* url-to-GtkTreeRowReference */ /* url-to-GtkTreeRowReference */
di->webseed_hash = g_hash_table_new_full(g_str_hash, g_str_equal, (GDestroyNotify)g_free, di->webseed_hash = g_hash_table_new_full(
g_str_hash,
g_str_equal,
(GDestroyNotify)g_free,
(GDestroyNotify)gtk_tree_row_reference_free); (GDestroyNotify)gtk_tree_row_reference_free);
ret = vbox; ret = vbox;
return ret; return ret;
@ -2109,18 +2140,32 @@ static void appendAnnounceInfo(tr_tracker_stat const* const st, time_t const now
if (st->lastAnnounceSucceeded) if (st->lastAnnounceSucceeded)
{ {
g_string_append_printf(gstr, _("Got a list of %1$s%2$'d peers%3$s %4$s ago"), g_string_append_printf(
success_markup_begin, st->lastAnnouncePeerCount, success_markup_end, timebuf); gstr,
_("Got a list of %1$s%2$'d peers%3$s %4$s ago"),
success_markup_begin,
st->lastAnnouncePeerCount,
success_markup_end,
timebuf);
} }
else if (st->lastAnnounceTimedOut) else if (st->lastAnnounceTimedOut)
{ {
g_string_append_printf(gstr, _("Peer list request %1$stimed out%2$s %3$s ago; will retry"), g_string_append_printf(
timeout_markup_begin, timeout_markup_end, timebuf); gstr,
_("Peer list request %1$stimed out%2$s %3$s ago; will retry"),
timeout_markup_begin,
timeout_markup_end,
timebuf);
} }
else else
{ {
g_string_append_printf(gstr, _("Got an error %1$s\"%2$s\"%3$s %4$s ago"), err_markup_begin, g_string_append_printf(
st->lastAnnounceResult, err_markup_end, timebuf); gstr,
_("Got an error %1$s\"%2$s\"%3$s %4$s ago"),
err_markup_begin,
st->lastAnnounceResult,
err_markup_end,
timebuf);
} }
} }
@ -2161,13 +2206,24 @@ static void appendScrapeInfo(tr_tracker_stat const* const st, time_t const now,
if (st->lastScrapeSucceeded) if (st->lastScrapeSucceeded)
{ {
g_string_append_printf(gstr, _("Tracker had %s%'d seeders and %'d leechers%s %s ago"), success_markup_begin, g_string_append_printf(
st->seederCount, st->leecherCount, success_markup_end, timebuf); gstr,
_("Tracker had %s%'d seeders and %'d leechers%s %s ago"),
success_markup_begin,
st->seederCount,
st->leecherCount,
success_markup_end,
timebuf);
} }
else else
{ {
g_string_append_printf(gstr, _("Got a scrape error \"%s%s%s\" %s ago"), err_markup_begin, g_string_append_printf(
st->lastScrapeResult, err_markup_end, timebuf); gstr,
_("Got a scrape error \"%s%s%s\" %s ago"),
err_markup_begin,
st->lastScrapeResult,
err_markup_end,
timebuf);
} }
} }
@ -2199,9 +2255,7 @@ static void buildTrackerSummary(GString* gstr, char const* key, tr_tracker_stat
{ {
// hostname // hostname
g_string_append(gstr, st->isBackup ? "<i>" : "<b>"); g_string_append(gstr, st->isBackup ? "<i>" : "<b>");
char* const str = key != NULL ? char* const str = key != NULL ? g_markup_printf_escaped("%s - %s", st->host, key) : g_markup_printf_escaped("%s", st->host);
g_markup_printf_escaped("%s - %s", st->host, key) :
g_markup_printf_escaped("%s", st->host);
g_string_append(gstr, str); g_string_append(gstr, str);
g_free(str); g_free(str);
g_string_append(gstr, st->isBackup ? "</i>" : "</b>"); g_string_append(gstr, st->isBackup ? "</i>" : "</b>");
@ -2327,8 +2381,7 @@ static void refreshTracker(struct DetailsImpl* di, tr_torrent** torrents, int n)
do do
{ {
gtk_list_store_set(store, &iter, TRACKER_COL_WAS_UPDATED, FALSE, -1); gtk_list_store_set(store, &iter, TRACKER_COL_WAS_UPDATED, FALSE, -1);
} } while (gtk_tree_model_iter_next(model, &iter));
while (gtk_tree_model_iter_next(model, &iter));
} }
/* step 3: add any new trackers */ /* step 3: add any new trackers */
@ -2348,10 +2401,13 @@ static void refreshTracker(struct DetailsImpl* di, tr_torrent** torrents, int n)
if (g_hash_table_lookup(hash, gstr->str) == NULL) if (g_hash_table_lookup(hash, gstr->str) == NULL)
{ {
gtk_list_store_insert_with_values(store, &iter, -1, gtk_list_store_insert_with_values(
TRACKER_COL_TORRENT_ID, torrent_id, store,
TRACKER_COL_TRACKER_ID, st->id, &iter,
TRACKER_COL_KEY, gstr->str, -1,
TR_ARG_TUPLE(TRACKER_COL_TORRENT_ID, torrent_id),
TR_ARG_TUPLE(TRACKER_COL_TRACKER_ID, st->id),
TR_ARG_TUPLE(TRACKER_COL_KEY, gstr->str),
-1); -1);
GtkTreePath* const p = gtk_tree_model_get_path(model, &iter); GtkTreePath* const p = gtk_tree_model_get_path(model, &iter);
@ -2384,11 +2440,13 @@ static void refreshTracker(struct DetailsImpl* di, tr_torrent** torrents, int n)
/* update the row */ /* update the row */
g_string_truncate(gstr, 0); g_string_truncate(gstr, 0);
buildTrackerSummary(gstr, summary_name, st, showScrape); buildTrackerSummary(gstr, summary_name, st, showScrape);
gtk_list_store_set(store, &iter, gtk_list_store_set(
TRACKER_COL_TEXT, gstr->str, store,
TRACKER_COL_IS_BACKUP, st->isBackup, &iter,
TRACKER_COL_TRACKER_ID, st->id, TR_ARG_TUPLE(TRACKER_COL_TEXT, gstr->str),
TRACKER_COL_WAS_UPDATED, TRUE, TR_ARG_TUPLE(TRACKER_COL_IS_BACKUP, st->isBackup),
TR_ARG_TUPLE(TRACKER_COL_TRACKER_ID, st->id),
TR_ARG_TUPLE(TRACKER_COL_WAS_UPDATED, TRUE),
-1); -1);
/* cleanup */ /* cleanup */
@ -2497,10 +2555,16 @@ static void on_edit_trackers_response(GtkDialog* dialog, int response, gpointer
else else
{ {
char const* text = _("List contains invalid URLs"); char const* text = _("List contains invalid URLs");
GtkWidget* w = gtk_message_dialog_new(GTK_WINDOW( GtkWidget* w = gtk_message_dialog_new(
dialog), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", GTK_WINDOW(dialog),
GTK_DIALOG_MODAL,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
"%s",
text); text);
gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(w), "%s", gtk_message_dialog_format_secondary_text(
GTK_MESSAGE_DIALOG(w),
"%s",
_("Please correct the errors and try again.")); _("Please correct the errors and try again."));
gtk_dialog_run(GTK_DIALOG(w)); gtk_dialog_run(GTK_DIALOG(w));
gtk_widget_destroy(w); gtk_widget_destroy(w);
@ -2564,9 +2628,12 @@ static void on_edit_trackers(GtkButton* button, gpointer data)
g_string_truncate(gstr, 0); g_string_truncate(gstr, 0);
g_string_append_printf(gstr, _("%s - Edit Trackers"), tr_torrentName(tor)); g_string_append_printf(gstr, _("%s - Edit Trackers"), tr_torrentName(tor));
d = gtk_dialog_new_with_buttons(gstr->str, win, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, d = gtk_dialog_new_with_buttons(
_("_Cancel"), GTK_RESPONSE_CANCEL, gstr->str,
_("_Save"), GTK_RESPONSE_ACCEPT, win,
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
TR_ARG_TUPLE(_("_Cancel"), GTK_RESPONSE_CANCEL),
TR_ARG_TUPLE(_("_Save"), GTK_RESPONSE_ACCEPT),
NULL); NULL);
g_signal_connect(d, "response", G_CALLBACK(on_edit_trackers_response), data); g_signal_connect(d, "response", G_CALLBACK(on_edit_trackers_response), data);
@ -2575,8 +2642,10 @@ static void on_edit_trackers(GtkButton* button, gpointer data)
hig_workarea_add_section_title(t, &row, _("Tracker Announce URLs")); hig_workarea_add_section_title(t, &row, _("Tracker Announce URLs"));
l = gtk_label_new(NULL); l = gtk_label_new(NULL);
gtk_label_set_markup(GTK_LABEL(l), _("To add a backup URL, add it on the line after the primary URL.\n" gtk_label_set_markup(
"To add another primary URL, add it after a blank line.")); GTK_LABEL(l),
_("To add a backup URL, add it on the line after the primary URL.\n"
"To add another primary URL, add it after a blank line."));
gtk_label_set_justify(GTK_LABEL(l), GTK_JUSTIFY_LEFT); gtk_label_set_justify(GTK_LABEL(l), GTK_JUSTIFY_LEFT);
g_object_set(l, "halign", GTK_ALIGN_START, "valign", GTK_ALIGN_CENTER, NULL); g_object_set(l, "halign", GTK_ALIGN_START, "valign", GTK_ALIGN_CENTER, NULL);
hig_workarea_add_wide_control(t, &row, l); hig_workarea_add_wide_control(t, &row, l);
@ -2678,9 +2747,12 @@ static void on_tracker_list_add_button_clicked(GtkButton const* button, gpointer
g_string_truncate(gstr, 0); g_string_truncate(gstr, 0);
g_string_append_printf(gstr, _("%s - Add Tracker"), tr_torrentName(tor)); g_string_append_printf(gstr, _("%s - Add Tracker"), tr_torrentName(tor));
w = gtk_dialog_new_with_buttons(gstr->str, GTK_WINDOW(di->dialog), GTK_DIALOG_DESTROY_WITH_PARENT, w = gtk_dialog_new_with_buttons(
_("_Cancel"), GTK_RESPONSE_CANCEL, gstr->str,
_("_Add"), GTK_RESPONSE_ACCEPT, GTK_WINDOW(di->dialog),
GTK_DIALOG_DESTROY_WITH_PARENT,
TR_ARG_TUPLE(_("_Cancel"), GTK_RESPONSE_CANCEL),
TR_ARG_TUPLE(_("_Add"), GTK_RESPONSE_ACCEPT),
NULL); NULL);
g_signal_connect(w, "response", G_CALLBACK(on_add_tracker_response), gdi); g_signal_connect(w, "response", G_CALLBACK(on_add_tracker_response), gdi);
@ -2716,9 +2788,11 @@ static void on_tracker_list_remove_button_clicked(GtkButton const* button, gpoin
tr_variant* args; tr_variant* args;
tr_variant* trackers; tr_variant* trackers;
gtk_tree_model_get(model, &iter, gtk_tree_model_get(
TRACKER_COL_TRACKER_ID, &tracker_id, model,
TRACKER_COL_TORRENT_ID, &torrent_id, &iter,
TR_ARG_TUPLE(TRACKER_COL_TRACKER_ID, &tracker_id),
TR_ARG_TUPLE(TRACKER_COL_TORRENT_ID, &torrent_id),
-1); -1);
tr_variantInitDict(&top, 2); tr_variantInitDict(&top, 2);
@ -2751,7 +2825,8 @@ static GtkWidget* tracker_page_new(struct DetailsImpl* di)
vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, GUI_PAD); vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, GUI_PAD);
gtk_container_set_border_width(GTK_CONTAINER(vbox), GUI_PAD_BIG); gtk_container_set_border_width(GTK_CONTAINER(vbox), GUI_PAD_BIG);
di->tracker_store = gtk_list_store_new(TRACKER_N_COLS, di->tracker_store = gtk_list_store_new(
TRACKER_N_COLS,
G_TYPE_INT, G_TYPE_INT,
G_TYPE_STRING, G_TYPE_STRING,
G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
@ -2760,7 +2835,10 @@ static GtkWidget* tracker_page_new(struct DetailsImpl* di)
G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
G_TYPE_STRING); G_TYPE_STRING);
di->tracker_hash = g_hash_table_new_full(g_str_hash, g_str_equal, (GDestroyNotify)g_free, di->tracker_hash = g_hash_table_new_full(
g_str_hash,
g_str_equal,
(GDestroyNotify)g_free,
(GDestroyNotify)gtk_tree_row_reference_free); (GDestroyNotify)gtk_tree_row_reference_free);
di->trackers_filtered = gtk_tree_model_filter_new(GTK_TREE_MODEL(di->tracker_store), NULL); di->trackers_filtered = gtk_tree_model_filter_new(GTK_TREE_MODEL(di->tracker_store), NULL);
@ -2913,14 +2991,13 @@ GtkWidget* gtr_torrent_details_dialog_new(GtkWindow* parent, TrCore* core)
/* create the dialog */ /* create the dialog */
di->core = core; di->core = core;
di->gstr = g_string_new(NULL); di->gstr = g_string_new(NULL);
d = gtk_dialog_new_with_buttons(NULL, parent, 0, d = gtk_dialog_new_with_buttons(NULL, parent, 0, TR_ARG_TUPLE(_("_Close"), GTK_RESPONSE_CLOSE), NULL);
_("_Close"), GTK_RESPONSE_CLOSE,
NULL);
di->dialog = d; di->dialog = d;
gtk_window_set_role(GTK_WINDOW(d), "tr-info"); gtk_window_set_role(GTK_WINDOW(d), "tr-info");
/* return saved window size */ /* return saved window size */
gtk_window_resize(GTK_WINDOW(d), gtk_window_resize(
GTK_WINDOW(d),
(gint)gtr_pref_int_get(TR_KEY_details_window_width), (gint)gtr_pref_int_get(TR_KEY_details_window_width),
(gint)gtr_pref_int_get(TR_KEY_details_window_height)); (gint)gtr_pref_int_get(TR_KEY_details_window_height));
g_signal_connect(d, "size-allocate", G_CALLBACK(on_details_window_size_allocated), NULL); g_signal_connect(d, "size-allocate", G_CALLBACK(on_details_window_size_allocated), NULL);

View File

@ -101,34 +101,45 @@ void gtr_confirm_remove(GtkWindow* parent, TrCore* core, GSList* torrent_ids, gb
} }
else else
{ {
g_string_printf(primary_text, ngettext("Delete this torrent's downloaded files?", g_string_printf(
"Delete these %d torrents' downloaded files?", count), count); primary_text,
ngettext("Delete this torrent's downloaded files?", "Delete these %d torrents' downloaded files?", count),
count);
} }
secondary_text = g_string_new(NULL); secondary_text = g_string_new(NULL);
if (incomplete == 0 && connected == 0) if (incomplete == 0 && connected == 0)
{ {
g_string_assign(secondary_text, g_string_assign(
ngettext("Once removed, continuing the transfer will require the torrent file or magnet link.", secondary_text,
"Once removed, continuing the transfers will require the torrent files or magnet links.", count)); ngettext(
"Once removed, continuing the transfer will require the torrent file or magnet link.",
"Once removed, continuing the transfers will require the torrent files or magnet links.",
count));
} }
else if (count == incomplete) else if (count == incomplete)
{ {
g_string_assign(secondary_text, ngettext("This torrent has not finished downloading.", g_string_assign(
"These torrents have not finished downloading.", count)); secondary_text,
ngettext("This torrent has not finished downloading.", "These torrents have not finished downloading.", count));
} }
else if (count == connected) else if (count == connected)
{ {
g_string_assign(secondary_text, ngettext("This torrent is connected to peers.", g_string_assign(
"These torrents are connected to peers.", count)); secondary_text,
ngettext("This torrent is connected to peers.", "These torrents are connected to peers.", count));
} }
else else
{ {
if (connected != 0) if (connected != 0)
{ {
g_string_append(secondary_text, ngettext("One of these torrents is connected to peers.", g_string_append(
"Some of these torrents are connected to peers.", connected)); secondary_text,
ngettext(
"One of these torrents is connected to peers.",
"Some of these torrents are connected to peers.",
connected));
} }
if (connected != 0 && incomplete != 0) if (connected != 0 && incomplete != 0)
@ -138,22 +149,32 @@ void gtr_confirm_remove(GtkWindow* parent, TrCore* core, GSList* torrent_ids, gb
if (incomplete != 0) if (incomplete != 0)
{ {
g_string_assign(secondary_text, ngettext("One of these torrents has not finished downloading.", g_string_assign(
"Some of these torrents have not finished downloading.", incomplete)); secondary_text,
ngettext(
"One of these torrents has not finished downloading.",
"Some of these torrents have not finished downloading.",
incomplete));
} }
} }
d = gtk_message_dialog_new_with_markup(parent, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, d = gtk_message_dialog_new_with_markup(
"<big><b>%s</b></big>", primary_text->str); parent,
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_QUESTION,
GTK_BUTTONS_NONE,
"<big><b>%s</b></big>",
primary_text->str);
if (secondary_text->len != 0) if (secondary_text->len != 0)
{ {
gtk_message_dialog_format_secondary_markup(GTK_MESSAGE_DIALOG(d), "%s", secondary_text->str); gtk_message_dialog_format_secondary_markup(GTK_MESSAGE_DIALOG(d), "%s", secondary_text->str);
} }
gtk_dialog_add_buttons(GTK_DIALOG(d), gtk_dialog_add_buttons(
_("_Cancel"), GTK_RESPONSE_CANCEL, GTK_DIALOG(d),
delete_files ? _("_Delete") : _("_Remove"), GTK_RESPONSE_ACCEPT, TR_ARG_TUPLE(_("_Cancel"), GTK_RESPONSE_CANCEL),
TR_ARG_TUPLE(delete_files ? _("_Delete") : _("_Remove"), GTK_RESPONSE_ACCEPT),
NULL); NULL);
gtk_dialog_set_default_response(GTK_DIALOG(d), GTK_RESPONSE_CANCEL); gtk_dialog_set_default_response(GTK_DIALOG(d), GTK_RESPONSE_CANCEL);
g_signal_connect(d, "response", G_CALLBACK(on_remove_dialog_response), dd); g_signal_connect(d, "response", G_CALLBACK(on_remove_dialog_response), dd);

View File

@ -118,8 +118,14 @@ static gboolean favicon_web_done_idle_cb(gpointer vfav)
return G_SOURCE_REMOVE; return G_SOURCE_REMOVE;
} }
static void favicon_web_done_cb(tr_session* session, bool did_connect, bool did_timeout, long code, void const* data, static void favicon_web_done_cb(
size_t len, void* vfav) tr_session* session,
bool did_connect,
bool did_timeout,
long code,
void const* data,
size_t len,
void* vfav)
{ {
TR_UNUSED(session); TR_UNUSED(session);
TR_UNUSED(did_connect); TR_UNUSED(did_connect);

View File

@ -56,8 +56,7 @@ typedef struct
GtkTreeStore* store; /* same object as model, but recast */ GtkTreeStore* store; /* same object as model, but recast */
int torrentId; int torrentId;
guint timeout_tag; guint timeout_tag;
} } FileData;
FileData;
static void clearData(FileData* data) static void clearData(FileData* data)
{ {
@ -105,13 +104,15 @@ static gboolean refreshFilesForeach(GtkTreeModel* model, GtkTreePath* path, GtkT
int old_enabled; int old_enabled;
gboolean const is_file = !gtk_tree_model_iter_has_child(model, iter); gboolean const is_file = !gtk_tree_model_iter_has_child(model, iter);
gtk_tree_model_get(model, iter, gtk_tree_model_get(
FC_ENABLED, &old_enabled, model,
FC_PRIORITY, &old_priority, iter,
FC_INDEX, &index, TR_ARG_TUPLE(FC_ENABLED, &old_enabled),
FC_HAVE, &old_have, TR_ARG_TUPLE(FC_PRIORITY, &old_priority),
FC_SIZE, &size, TR_ARG_TUPLE(FC_INDEX, &index),
FC_PROG, &old_prog, TR_ARG_TUPLE(FC_HAVE, &old_have),
TR_ARG_TUPLE(FC_SIZE, &size),
TR_ARG_TUPLE(FC_PROG, &old_prog),
-1); -1);
if (is_file) if (is_file)
@ -131,19 +132,23 @@ static gboolean refreshFilesForeach(GtkTreeModel* model, GtkTreePath* path, GtkT
* sorting until we finish walking the tree. */ * sorting until we finish walking the tree. */
if (!refresh_data->resort_needed && if (!refresh_data->resort_needed &&
(((refresh_data->sort_column_id == FC_PRIORITY) && (priority != old_priority)) || (((refresh_data->sort_column_id == FC_PRIORITY) && (priority != old_priority)) ||
((refresh_data->sort_column_id == FC_ENABLED) && (enabled != old_enabled)))) ((refresh_data->sort_column_id == FC_ENABLED) && (enabled != old_enabled))))
{ {
refresh_data->resort_needed = TRUE; refresh_data->resort_needed = TRUE;
gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(data->model), gtk_tree_sortable_set_sort_column_id(
GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID, GTK_SORT_ASCENDING); GTK_TREE_SORTABLE(data->model),
GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID,
GTK_SORT_ASCENDING);
} }
gtk_tree_store_set(data->store, iter, gtk_tree_store_set(
FC_PRIORITY, priority, data->store,
FC_ENABLED, enabled, iter,
FC_HAVE, have, TR_ARG_TUPLE(FC_PRIORITY, priority),
FC_PROG, prog, TR_ARG_TUPLE(FC_ENABLED, enabled),
TR_ARG_TUPLE(FC_HAVE, have),
TR_ARG_TUPLE(FC_PROG, prog),
-1); -1);
} }
} }
@ -168,11 +173,13 @@ static gboolean refreshFilesForeach(GtkTreeModel* model, GtkTreePath* path, GtkT
int64_t child_have; int64_t child_have;
int64_t child_size; int64_t child_size;
gtk_tree_model_get(model, &child, gtk_tree_model_get(
FC_SIZE, &child_size, model,
FC_HAVE, &child_have, &child,
FC_PRIORITY, &child_priority, TR_ARG_TUPLE(FC_SIZE, &child_size),
FC_ENABLED, &child_enabled, TR_ARG_TUPLE(FC_HAVE, &child_have),
TR_ARG_TUPLE(FC_PRIORITY, &child_priority),
TR_ARG_TUPLE(FC_ENABLED, &child_enabled),
-1); -1);
if ((child_enabled != FALSE) && (child_enabled != NOT_SET)) if ((child_enabled != FALSE) && (child_enabled != NOT_SET))
@ -198,8 +205,7 @@ static gboolean refreshFilesForeach(GtkTreeModel* model, GtkTreePath* path, GtkT
{ {
priority = MIXED; priority = MIXED;
} }
} } while (gtk_tree_model_iter_next(model, &child));
while (gtk_tree_model_iter_next(model, &child));
} }
prog = sub_size != 0 ? (int)(100.0 * have / sub_size) : 1; prog = sub_size != 0 ? (int)(100.0 * have / sub_size) : 1;
@ -208,13 +214,15 @@ static gboolean refreshFilesForeach(GtkTreeModel* model, GtkTreePath* path, GtkT
{ {
char size_str[64]; char size_str[64];
tr_strlsize(size_str, sub_size, sizeof(size_str)); tr_strlsize(size_str, sub_size, sizeof(size_str));
gtk_tree_store_set(data->store, iter, gtk_tree_store_set(
FC_SIZE, sub_size, data->store,
FC_SIZE_STR, size_str, iter,
FC_HAVE, have, TR_ARG_TUPLE(FC_SIZE, sub_size),
FC_PRIORITY, priority, TR_ARG_TUPLE(FC_SIZE_STR, size_str),
FC_ENABLED, enabled, TR_ARG_TUPLE(FC_HAVE, have),
FC_PROG, prog, TR_ARG_TUPLE(FC_PRIORITY, priority),
TR_ARG_TUPLE(FC_ENABLED, enabled),
TR_ARG_TUPLE(FC_PROG, prog),
-1); -1);
} }
} }
@ -222,7 +230,10 @@ static gboolean refreshFilesForeach(GtkTreeModel* model, GtkTreePath* path, GtkT
return FALSE; /* keep walking */ return FALSE; /* keep walking */
} }
static void gtr_tree_model_foreach_postorder_subtree(GtkTreeModel* model, GtkTreeIter* parent, GtkTreeModelForeachFunc func, static void gtr_tree_model_foreach_postorder_subtree(
GtkTreeModel* model,
GtkTreeIter* parent,
GtkTreeModelForeachFunc func,
gpointer data) gpointer data)
{ {
GtkTreeIter child; GtkTreeIter child;
@ -232,8 +243,7 @@ static void gtr_tree_model_foreach_postorder_subtree(GtkTreeModel* model, GtkTre
do do
{ {
gtr_tree_model_foreach_postorder_subtree(model, &child, func, data); gtr_tree_model_foreach_postorder_subtree(model, &child, func, data);
} } while (gtk_tree_model_iter_next(model, &child));
while (gtk_tree_model_iter_next(model, &child));
} }
if (parent != NULL) if (parent != NULL)
@ -251,8 +261,7 @@ static void gtr_tree_model_foreach_postorder(GtkTreeModel* model, GtkTreeModelFo
do do
{ {
gtr_tree_model_foreach_postorder_subtree(model, &iter, func, data); gtr_tree_model_foreach_postorder_subtree(model, &iter, func, data);
} } while (gtk_tree_model_iter_next(model, &iter));
while (gtk_tree_model_iter_next(model, &iter));
} }
} }
@ -457,15 +466,19 @@ static void buildTree(GNode* node, gpointer gdata)
tr_strlsize(size_str, child_data->length, sizeof(size_str)); tr_strlsize(size_str, child_data->length, sizeof(size_str));
gtk_tree_store_insert_with_values(build->store, &child_iter, build->iter, INT_MAX, gtk_tree_store_insert_with_values(
FC_INDEX, child_data->index, build->store,
FC_LABEL, child_data->name, &child_iter,
FC_LABEL_ESC, name_esc, build->iter,
FC_SIZE, child_data->length, INT_MAX,
FC_SIZE_STR, size_str, TR_ARG_TUPLE(FC_INDEX, child_data->index),
FC_ICON, icon, TR_ARG_TUPLE(FC_LABEL, child_data->name),
FC_PRIORITY, priority, TR_ARG_TUPLE(FC_LABEL_ESC, name_esc),
FC_ENABLED, enabled, TR_ARG_TUPLE(FC_SIZE, child_data->length),
TR_ARG_TUPLE(FC_SIZE_STR, size_str),
TR_ARG_TUPLE(FC_ICON, icon),
TR_ARG_TUPLE(FC_PRIORITY, priority),
TR_ARG_TUPLE(FC_ENABLED, enabled),
-1); -1);
if (!isLeaf) if (!isLeaf)
@ -509,7 +522,8 @@ void gtr_file_list_set_torrent(GtkWidget* w, int torrentId)
clearData(data); clearData(data);
/* instantiate the model */ /* instantiate the model */
GtkTreeStore* const store = gtk_tree_store_new(N_FILE_COLS, GtkTreeStore* const store = gtk_tree_store_new(
N_FILE_COLS,
GDK_TYPE_PIXBUF, /* icon */ GDK_TYPE_PIXBUF, /* icon */
G_TYPE_STRING, /* label */ G_TYPE_STRING, /* label */
G_TYPE_STRING, /* label esc */ G_TYPE_STRING, /* label esc */
@ -526,9 +540,7 @@ void gtr_file_list_set_torrent(GtkWidget* w, int torrentId)
data->torrentId = torrentId; data->torrentId = torrentId;
/* populate the model */ /* populate the model */
tr_torrent* const tor = torrentId > 0 ? tr_torrent* const tor = torrentId > 0 ? gtr_core_find_torrent(data->core, torrentId) : NULL;
gtr_core_find_torrent(data->core, torrentId) :
NULL;
if (tor != NULL) if (tor != NULL)
{ {
// build a GNode tree of the files // build a GNode tree of the files
@ -601,7 +613,11 @@ void gtr_file_list_set_torrent(GtkWidget* w, int torrentId)
**** ****
***/ ***/
static void renderDownload(GtkTreeViewColumn* column, GtkCellRenderer* renderer, GtkTreeModel* model, GtkTreeIter* iter, static void renderDownload(
GtkTreeViewColumn* column,
GtkCellRenderer* renderer,
GtkTreeModel* model,
GtkTreeIter* iter,
gpointer data) gpointer data)
{ {
TR_UNUSED(column); TR_UNUSED(column);
@ -612,7 +628,11 @@ static void renderDownload(GtkTreeViewColumn* column, GtkCellRenderer* renderer,
g_object_set(renderer, "inconsistent", enabled == MIXED, "active", enabled == TRUE, NULL); g_object_set(renderer, "inconsistent", enabled == MIXED, "active", enabled == TRUE, NULL);
} }
static void renderPriority(GtkTreeViewColumn* column, GtkCellRenderer* renderer, GtkTreeModel* model, GtkTreeIter* iter, static void renderPriority(
GtkTreeViewColumn* column,
GtkCellRenderer* renderer,
GtkTreeModel* model,
GtkTreeIter* iter,
gpointer data) gpointer data)
{ {
TR_UNUSED(column); TR_UNUSED(column);
@ -657,8 +677,7 @@ static char* buildFilename(tr_torrent const* tor, GtkTreeModel* model, GtkTreePa
{ {
child = parent; child = parent;
gtk_tree_model_get(model, &child, FC_LABEL, &tokens[n--], -1); gtk_tree_model_get(model, &child, FC_LABEL, &tokens[n--], -1);
} } while (gtk_tree_model_iter_parent(model, &parent, &child));
while (gtk_tree_model_iter_parent(model, &parent, &child));
char* const ret = g_build_filenamev(tokens); char* const ret = g_build_filenamev(tokens);
g_strfreev(tokens); g_strfreev(tokens);
@ -693,8 +712,7 @@ static gboolean onRowActivated(GtkTreeView* view, GtkTreePath* path, GtkTreeView
char* tmp = g_path_get_dirname(filename); char* tmp = g_path_get_dirname(filename);
g_free(filename); g_free(filename);
filename = tmp; filename = tmp;
} } while (!tr_str_is_empty(filename) && !g_file_test(filename, G_FILE_TEST_EXISTS));
while (!tr_str_is_empty(filename) && !g_file_test(filename, G_FILE_TEST_EXISTS));
} }
if ((handled = !tr_str_is_empty(filename))) if ((handled = !tr_str_is_empty(filename)))
@ -772,7 +790,10 @@ static gboolean onViewPathToggled(GtkTreeView* view, GtkTreeViewColumn* col, Gtk
/** /**
* @note 'col' and 'path' are assumed not to be NULL. * @note 'col' and 'path' are assumed not to be NULL.
*/ */
static gboolean getAndSelectEventPath(GtkTreeView* treeview, GdkEventButton const* event, GtkTreeViewColumn** col, static gboolean getAndSelectEventPath(
GtkTreeView* treeview,
GdkEventButton const* event,
GtkTreeViewColumn** col,
GtkTreePath** path) GtkTreePath** path)
{ {
GtkTreeSelection* sel; GtkTreeSelection* sel;
@ -847,8 +868,13 @@ static int on_rename_done_idle(struct rename_data* data)
} }
else else
{ {
GtkWidget* w = gtk_message_dialog_new(GTK_WINDOW(gtk_widget_get_toplevel(data->file_data->top)), GTK_DIALOG_MODAL, GtkWidget* w = gtk_message_dialog_new(
GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, _("Unable to rename file as \"%s\": %s"), data->newname, GTK_WINDOW(gtk_widget_get_toplevel(data->file_data->top)),
GTK_DIALOG_MODAL,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
_("Unable to rename file as \"%s\": %s"),
data->newname,
tr_strerror(data->error)); tr_strerror(data->error));
gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(w), "%s", _("Please correct the errors and try again.")); gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(w), "%s", _("Please correct the errors and try again."));
gtk_dialog_run(GTK_DIALOG(w)); gtk_dialog_run(GTK_DIALOG(w));
@ -862,14 +888,21 @@ static int on_rename_done_idle(struct rename_data* data)
return G_SOURCE_REMOVE; return G_SOURCE_REMOVE;
} }
static void on_rename_done(tr_torrent const* tor G_GNUC_UNUSED, char const* oldpath G_GNUC_UNUSED, static void on_rename_done(
char const* newname G_GNUC_UNUSED, int error, struct rename_data* rename_data) tr_torrent const* tor G_GNUC_UNUSED,
char const* oldpath G_GNUC_UNUSED,
char const* newname G_GNUC_UNUSED,
int error,
struct rename_data* rename_data)
{ {
rename_data->error = error; rename_data->error = error;
gdk_threads_add_idle((GSourceFunc)on_rename_done_idle, rename_data); gdk_threads_add_idle((GSourceFunc)on_rename_done_idle, rename_data);
} }
static void cell_edited_callback(GtkCellRendererText const* cell G_GNUC_UNUSED, gchar const* path_string, gchar const* newname, static void cell_edited_callback(
GtkCellRendererText const* cell G_GNUC_UNUSED,
gchar const* path_string,
gchar const* newname,
FileData* data) FileData* data)
{ {
tr_torrent* const tor = gtr_core_find_torrent(data->core, data->torrentId); tr_torrent* const tor = gtr_core_find_torrent(data->core, data->torrentId);
@ -975,8 +1008,14 @@ GtkWidget* gtr_file_list_new(TrCore* core, int torrentId)
/* add "size" column */ /* add "size" column */
title = _("Size"); title = _("Size");
rend = gtk_cell_renderer_text_new(); rend = gtk_cell_renderer_text_new();
g_object_set(rend, "alignment", PANGO_ALIGN_RIGHT, "font-desc", pango_font_description, "xpad", GUI_PAD, "xalign", 1.0F, g_object_set(
"yalign", 0.5F, NULL); rend,
TR_ARG_TUPLE("alignment", PANGO_ALIGN_RIGHT),
TR_ARG_TUPLE("font-desc", pango_font_description),
TR_ARG_TUPLE("xpad", GUI_PAD),
TR_ARG_TUPLE("xalign", 1.0F),
TR_ARG_TUPLE("yalign", 0.5F),
NULL);
col = gtk_tree_view_column_new_with_attributes(title, rend, NULL); col = gtk_tree_view_column_new_with_attributes(title, rend, NULL);
gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_GROW_ONLY); gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_GROW_ONLY);
gtk_tree_view_column_set_sort_column_id(col, FC_SIZE); gtk_tree_view_column_set_sort_column_id(col, FC_SIZE);

View File

@ -173,8 +173,7 @@ static gboolean tracker_filter_model_update(gpointer gstore)
g_free(keys); g_free(keys);
++num_torrents; ++num_torrents;
} } while (gtk_tree_model_iter_next(tmodel, &iter));
while (gtk_tree_model_iter_next(tmodel, &iter));
} }
qsort(hosts->pdata, hosts->len, sizeof(char*), pstrcmp); qsort(hosts->pdata, hosts->len, sizeof(char*), pstrcmp);
@ -242,11 +241,15 @@ static gboolean tracker_filter_model_update(gpointer gstore)
char const* host = hosts->pdata[i]; char const* host = hosts->pdata[i];
char* name = get_name_from_host(host); char* name = get_name_from_host(host);
int const count = *(int*)g_hash_table_lookup(hosts_hash, host); int const count = *(int*)g_hash_table_lookup(hosts_hash, host);
gtk_tree_store_insert_with_values(store, &add, NULL, store_pos, gtk_tree_store_insert_with_values(
TRACKER_FILTER_COL_HOST, host, store,
TRACKER_FILTER_COL_NAME, name, &add,
TRACKER_FILTER_COL_COUNT, count, NULL,
TRACKER_FILTER_COL_TYPE, TRACKER_FILTER_TYPE_HOST, store_pos,
TR_ARG_TUPLE(TRACKER_FILTER_COL_HOST, host),
TR_ARG_TUPLE(TRACKER_FILTER_COL_NAME, name),
TR_ARG_TUPLE(TRACKER_FILTER_COL_COUNT, count),
TR_ARG_TUPLE(TRACKER_FILTER_COL_TYPE, TRACKER_FILTER_TYPE_HOST),
-1); -1);
path = gtk_tree_model_get_path(model, &add); path = gtk_tree_model_get_path(model, &add);
reference = gtk_tree_row_reference_new(model, path); reference = gtk_tree_row_reference_new(model, path);
@ -275,19 +278,28 @@ static gboolean tracker_filter_model_update(gpointer gstore)
static GtkTreeModel* tracker_filter_model_new(GtkTreeModel* tmodel) static GtkTreeModel* tracker_filter_model_new(GtkTreeModel* tmodel)
{ {
GtkTreeStore* store = gtk_tree_store_new(TRACKER_FILTER_N_COLS, GtkTreeStore* store = gtk_tree_store_new(
TRACKER_FILTER_N_COLS,
G_TYPE_STRING, G_TYPE_STRING,
G_TYPE_INT, G_TYPE_INT,
G_TYPE_INT, G_TYPE_INT,
G_TYPE_STRING, G_TYPE_STRING,
GDK_TYPE_PIXBUF); GDK_TYPE_PIXBUF);
gtk_tree_store_insert_with_values(store, NULL, NULL, -1, gtk_tree_store_insert_with_values(
TRACKER_FILTER_COL_NAME, _("All"), store,
TRACKER_FILTER_COL_TYPE, TRACKER_FILTER_TYPE_ALL, NULL,
NULL,
-1,
TR_ARG_TUPLE(TRACKER_FILTER_COL_NAME, _("All")),
TR_ARG_TUPLE(TRACKER_FILTER_COL_TYPE, TRACKER_FILTER_TYPE_ALL),
-1); -1);
gtk_tree_store_insert_with_values(store, NULL, NULL, -1, gtk_tree_store_insert_with_values(
TRACKER_FILTER_COL_TYPE, TRACKER_FILTER_TYPE_SEPARATOR, store,
NULL,
NULL,
-1,
TR_ARG_TUPLE(TRACKER_FILTER_COL_TYPE, TRACKER_FILTER_TYPE_SEPARATOR),
-1); -1);
g_object_set_qdata(G_OBJECT(store), TORRENT_MODEL_KEY, tmodel); g_object_set_qdata(G_OBJECT(store), TORRENT_MODEL_KEY, tmodel);
@ -334,8 +346,12 @@ static void torrent_model_row_deleted_cb(GtkTreeModel* tmodel, GtkTreePath* path
tracker_model_update_idle(tracker_model); tracker_model_update_idle(tracker_model);
} }
static void render_pixbuf_func(GtkCellLayout* cell_layout, GtkCellRenderer* cell_renderer, GtkTreeModel* tree_model, static void render_pixbuf_func(
GtkTreeIter* iter, gpointer data) GtkCellLayout* cell_layout,
GtkCellRenderer* cell_renderer,
GtkTreeModel* tree_model,
GtkTreeIter* iter,
gpointer data)
{ {
TR_UNUSED(cell_layout); TR_UNUSED(cell_layout);
TR_UNUSED(data); TR_UNUSED(data);
@ -348,8 +364,12 @@ static void render_pixbuf_func(GtkCellLayout* cell_layout, GtkCellRenderer* cell
g_object_set(cell_renderer, "width", width, NULL); g_object_set(cell_renderer, "width", width, NULL);
} }
static void render_number_func(GtkCellLayout* cell_layout, GtkCellRenderer* cell_renderer, GtkTreeModel* tree_model, static void render_number_func(
GtkTreeIter* iter, gpointer data) GtkCellLayout* cell_layout,
GtkCellRenderer* cell_renderer,
GtkTreeModel* tree_model,
GtkTreeIter* iter,
gpointer data)
{ {
TR_UNUSED(cell_layout); TR_UNUSED(cell_layout);
TR_UNUSED(data); TR_UNUSED(data);
@ -375,7 +395,12 @@ static GtkCellRenderer* number_renderer_new(void)
{ {
GtkCellRenderer* r = gtk_cell_renderer_text_new(); GtkCellRenderer* r = gtk_cell_renderer_text_new();
g_object_set(G_OBJECT(r), "alignment", PANGO_ALIGN_RIGHT, "weight", PANGO_WEIGHT_ULTRALIGHT, "xalign", 1.0, "xpad", GUI_PAD, g_object_set(
G_OBJECT(r),
TR_ARG_TUPLE("alignment", PANGO_ALIGN_RIGHT),
TR_ARG_TUPLE("weight", PANGO_WEIGHT_ULTRALIGHT),
TR_ARG_TUPLE("xalign", 1.0),
TR_ARG_TUPLE("xpad", GUI_PAD),
NULL); NULL);
return r; return r;
@ -560,13 +585,11 @@ static gboolean activity_filter_model_update(gpointer gstore)
{ {
++hits; ++hits;
} }
} } while (gtk_tree_model_iter_next(tmodel, &torrent_iter));
while (gtk_tree_model_iter_next(tmodel, &torrent_iter));
} }
status_model_update_count(store, &iter, hits); status_model_update_count(store, &iter, hits);
} } while (gtk_tree_model_iter_next(model, &iter));
while (gtk_tree_model_iter_next(model, &iter));
} }
return G_SOURCE_REMOVE; return G_SOURCE_REMOVE;
@ -580,9 +603,7 @@ static GtkTreeModel* activity_filter_model_new(GtkTreeModel* tmodel)
char const* context; char const* context;
char const* name; char const* name;
char const* icon_name; char const* icon_name;
} } types[] = {
types[] =
{
{ ACTIVITY_FILTER_ALL, NULL, N_("All"), NULL }, { ACTIVITY_FILTER_ALL, NULL, N_("All"), NULL },
{ ACTIVITY_FILTER_SEPARATOR, NULL, NULL, NULL }, { ACTIVITY_FILTER_SEPARATOR, NULL, NULL, NULL },
{ ACTIVITY_FILTER_ACTIVE, NULL, N_("Active"), "system-run" }, { ACTIVITY_FILTER_ACTIVE, NULL, N_("Active"), "system-run" },
@ -591,22 +612,21 @@ static GtkTreeModel* activity_filter_model_new(GtkTreeModel* tmodel)
{ ACTIVITY_FILTER_PAUSED, NULL, N_("Paused"), "media-playback-pause" }, { ACTIVITY_FILTER_PAUSED, NULL, N_("Paused"), "media-playback-pause" },
{ ACTIVITY_FILTER_FINISHED, NULL, N_("Finished"), "media-playback-stop" }, { ACTIVITY_FILTER_FINISHED, NULL, N_("Finished"), "media-playback-stop" },
{ ACTIVITY_FILTER_VERIFYING, "Verb", NC_("Verb", "Verifying"), "view-refresh" }, { ACTIVITY_FILTER_VERIFYING, "Verb", NC_("Verb", "Verifying"), "view-refresh" },
{ ACTIVITY_FILTER_ERROR, NULL, N_("Error"), "dialog-error" } { ACTIVITY_FILTER_ERROR, NULL, N_("Error"), "dialog-error" },
}; };
GtkListStore* store = gtk_list_store_new(ACTIVITY_FILTER_N_COLS, GtkListStore* store = gtk_list_store_new(ACTIVITY_FILTER_N_COLS, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT, G_TYPE_STRING);
G_TYPE_STRING,
G_TYPE_INT,
G_TYPE_INT,
G_TYPE_STRING);
for (size_t i = 0; i < G_N_ELEMENTS(types); ++i) for (size_t i = 0; i < G_N_ELEMENTS(types); ++i)
{ {
char const* name = types[i].context != NULL ? g_dpgettext2(NULL, types[i].context, types[i].name) : _(types[i].name); char const* name = types[i].context != NULL ? g_dpgettext2(NULL, types[i].context, types[i].name) : _(types[i].name);
gtk_list_store_insert_with_values(store, NULL, -1, gtk_list_store_insert_with_values(
ACTIVITY_FILTER_COL_NAME, name, store,
ACTIVITY_FILTER_COL_TYPE, types[i].type, NULL,
ACTIVITY_FILTER_COL_ICON_NAME, types[i].icon_name, -1,
TR_ARG_TUPLE(ACTIVITY_FILTER_COL_NAME, name),
TR_ARG_TUPLE(ACTIVITY_FILTER_COL_TYPE, types[i].type),
TR_ARG_TUPLE(ACTIVITY_FILTER_COL_ICON_NAME, types[i].icon_name),
-1); -1);
} }
@ -615,8 +635,12 @@ static GtkTreeModel* activity_filter_model_new(GtkTreeModel* tmodel)
return GTK_TREE_MODEL(store); return GTK_TREE_MODEL(store);
} }
static void render_activity_pixbuf_func(GtkCellLayout* cell_layout, GtkCellRenderer* cell_renderer, GtkTreeModel* tree_model, static void render_activity_pixbuf_func(
GtkTreeIter* iter, gpointer data) GtkCellLayout* cell_layout,
GtkCellRenderer* cell_renderer,
GtkTreeModel* tree_model,
GtkTreeIter* iter,
gpointer data)
{ {
TR_UNUSED(cell_layout); TR_UNUSED(cell_layout);
TR_UNUSED(data); TR_UNUSED(data);
@ -645,7 +669,10 @@ static void activity_model_update_idle(gpointer activity_model)
} }
} }
static void activity_torrent_model_row_changed(GtkTreeModel const* tmodel, GtkTreePath const* path, GtkTreeIter const* iter, static void activity_torrent_model_row_changed(
GtkTreeModel const* tmodel,
GtkTreePath const* path,
GtkTreeIter const* iter,
gpointer activity_model) gpointer activity_model)
{ {
TR_UNUSED(tmodel); TR_UNUSED(tmodel);
@ -686,14 +713,12 @@ static GtkWidget* activity_combo_box_new(GtkTreeModel* tmodel)
r = gtk_cell_renderer_pixbuf_new(); r = gtk_cell_renderer_pixbuf_new();
gtk_cell_layout_pack_start(c_cell_layout, r, FALSE); gtk_cell_layout_pack_start(c_cell_layout, r, FALSE);
gtk_cell_layout_set_attributes(c_cell_layout, r, gtk_cell_layout_set_attributes(c_cell_layout, r, TR_ARG_TUPLE("icon-name", ACTIVITY_FILTER_COL_ICON_NAME), NULL);
"icon-name", ACTIVITY_FILTER_COL_ICON_NAME,
NULL);
gtk_cell_layout_set_cell_data_func(c_cell_layout, r, render_activity_pixbuf_func, NULL, NULL); gtk_cell_layout_set_cell_data_func(c_cell_layout, r, render_activity_pixbuf_func, NULL, NULL);
r = gtk_cell_renderer_text_new(); r = gtk_cell_renderer_text_new();
gtk_cell_layout_pack_start(c_cell_layout, r, TRUE); gtk_cell_layout_pack_start(c_cell_layout, r, TRUE);
gtk_cell_layout_set_attributes(c_cell_layout, r, "text", ACTIVITY_FILTER_COL_NAME, NULL); gtk_cell_layout_set_attributes(c_cell_layout, r, TR_ARG_TUPLE("text", ACTIVITY_FILTER_COL_NAME), NULL);
r = number_renderer_new(); r = number_renderer_new();
gtk_cell_layout_pack_end(c_cell_layout, r, TRUE); gtk_cell_layout_pack_end(c_cell_layout, r, TRUE);
@ -823,9 +848,11 @@ static void selection_changed_cb(GtkComboBox* combo, gpointer vdata)
if (gtk_combo_box_get_active_iter(combo, &iter)) if (gtk_combo_box_get_active_iter(combo, &iter))
{ {
gtk_tree_model_get(model, &iter, gtk_tree_model_get(
TRACKER_FILTER_COL_TYPE, &type, model,
TRACKER_FILTER_COL_HOST, &host, &iter,
TR_ARG_TUPLE(TRACKER_FILTER_COL_TYPE, &type),
TR_ARG_TUPLE(TRACKER_FILTER_COL_HOST, &host),
-1); -1);
} }
else else
@ -914,7 +941,10 @@ static void update_count_label_idle(struct filter_data* data)
} }
} }
static void on_filter_model_row_inserted(GtkTreeModel const* tree_model, GtkTreePath const* path, GtkTreeIter const* iter, static void on_filter_model_row_inserted(
GtkTreeModel const* tree_model,
GtkTreePath const* path,
GtkTreeIter const* iter,
gpointer data) gpointer data)
{ {
TR_UNUSED(tree_model); TR_UNUSED(tree_model);

View File

@ -7,6 +7,9 @@
*/ */
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include <libtransmission/tr-macros.h>
#include "hig.h" #include "hig.h"
GtkWidget* hig_workarea_create(void) GtkWidget* hig_workarea_create(void)
@ -86,10 +89,11 @@ void hig_workarea_add_label_w(GtkWidget* t, guint row, GtkWidget* w)
if (GTK_IS_LABEL(w)) if (GTK_IS_LABEL(w))
{ {
g_object_set(w, g_object_set(
"halign", GTK_ALIGN_START, w,
"valign", GTK_ALIGN_CENTER, TR_ARG_TUPLE("halign", GTK_ALIGN_START),
"use-markup", TRUE, TR_ARG_TUPLE("valign", GTK_ALIGN_CENTER),
TR_ARG_TUPLE("use-markup", TRUE),
NULL); NULL);
} }
@ -100,10 +104,7 @@ static void hig_workarea_add_tall_control(GtkWidget* t, guint row, GtkWidget* co
{ {
if (GTK_IS_LABEL(control)) if (GTK_IS_LABEL(control))
{ {
g_object_set(control, g_object_set(control, TR_ARG_TUPLE("halign", GTK_ALIGN_START), TR_ARG_TUPLE("valign", GTK_ALIGN_CENTER), NULL);
"halign", GTK_ALIGN_START,
"valign", GTK_ALIGN_CENTER,
NULL);
} }
g_object_set(control, "expand", TRUE, NULL); g_object_set(control, "expand", TRUE, NULL);
@ -114,10 +115,7 @@ static void hig_workarea_add_control(GtkWidget* t, guint row, GtkWidget* control
{ {
if (GTK_IS_LABEL(control)) if (GTK_IS_LABEL(control))
{ {
g_object_set(control, g_object_set(control, TR_ARG_TUPLE("halign", GTK_ALIGN_START), TR_ARG_TUPLE("valign", GTK_ALIGN_CENTER), NULL);
"halign", GTK_ALIGN_START,
"valign", GTK_ALIGN_CENTER,
NULL);
} }
gtk_widget_set_hexpand(control, TRUE); gtk_widget_set_hexpand(control, TRUE);
@ -145,7 +143,11 @@ GtkWidget* hig_workarea_add_row(GtkWidget* t, guint* row, char const* mnemonic_s
return l; return l;
} }
GtkWidget* hig_workarea_add_tall_row(GtkWidget* table, guint* row, char const* mnemonic_string, GtkWidget* control, GtkWidget* hig_workarea_add_tall_row(
GtkWidget* table,
guint* row,
char const* mnemonic_string,
GtkWidget* control,
GtkWidget* mnemonic) GtkWidget* mnemonic)
{ {
GtkWidget* l = gtk_label_new_with_mnemonic(mnemonic_string); GtkWidget* l = gtk_label_new_with_mnemonic(mnemonic_string);

View File

@ -31,13 +31,25 @@ GtkWidget* hig_workarea_add_wide_checkbutton(GtkWidget* table, guint* row, char
void hig_workarea_add_label_w(GtkWidget* table, guint row, GtkWidget* label_widget); void hig_workarea_add_label_w(GtkWidget* table, guint row, GtkWidget* label_widget);
GtkWidget* hig_workarea_add_tall_row(GtkWidget* table, guint* row, char const* mnemonic_string, GtkWidget* control, GtkWidget* hig_workarea_add_tall_row(
GtkWidget* table,
guint* row,
char const* mnemonic_string,
GtkWidget* control,
GtkWidget* mnemonic_or_null_for_control); GtkWidget* mnemonic_or_null_for_control);
GtkWidget* hig_workarea_add_row(GtkWidget* table, guint* row, char const* mnemonic_string, GtkWidget* control, GtkWidget* hig_workarea_add_row(
GtkWidget* table,
guint* row,
char const* mnemonic_string,
GtkWidget* control,
GtkWidget* mnemonic_or_null_for_control); GtkWidget* mnemonic_or_null_for_control);
void hig_workarea_add_row_w(GtkWidget* table, guint* row, GtkWidget* label, GtkWidget* control, void hig_workarea_add_row_w(
GtkWidget* table,
guint* row,
GtkWidget* label,
GtkWidget* control,
GtkWidget* mnemonic_or_null_for_control); GtkWidget* mnemonic_or_null_for_control);
enum enum

View File

@ -34,8 +34,7 @@ typedef struct
GtkIconTheme* icon_theme; GtkIconTheme* icon_theme;
int icon_size; int icon_size;
GHashTable* cache; GHashTable* cache;
} } IconCache;
IconCache;
static IconCache* icon_cache[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; static IconCache* icon_cache[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
@ -66,8 +65,7 @@ static IconCache* icon_cache_new(GtkWidget* for_widget, int icon_size)
icons->icon_size = get_size_in_pixels(icon_size); icons->icon_size = get_size_in_pixels(icon_size);
icons->cache = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_object_unref); icons->cache = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_object_unref);
g_hash_table_insert(icons->cache, (void*)VOID_PIXBUF_KEY, create_void_pixbuf(icons->icon_size, g_hash_table_insert(icons->cache, (void*)VOID_PIXBUF_KEY, create_void_pixbuf(icons->icon_size, icons->icon_size));
icons->icon_size));
return icons; return icons;
} }

View File

@ -455,8 +455,11 @@ static gboolean on_rpc_changed_idle(gpointer gdata)
return G_SOURCE_REMOVE; return G_SOURCE_REMOVE;
} }
static tr_rpc_callback_status on_rpc_changed(tr_session* session G_GNUC_UNUSED, tr_rpc_callback_type type, static tr_rpc_callback_status on_rpc_changed(
struct tr_torrent* tor, void* gdata) tr_session* session G_GNUC_UNUSED,
tr_rpc_callback_type type,
struct tr_torrent* tor,
void* gdata)
{ {
struct cbdata* cbdata = gdata; struct cbdata* cbdata = gdata;
struct on_rpc_changed_struct* data; struct on_rpc_changed_struct* data;
@ -547,8 +550,7 @@ static void on_startup(GApplication* application, gpointer user_data)
tr_sessionSetRPCCallback(session, on_rpc_changed, cbdata); tr_sessionSetRPCCallback(session, on_rpc_changed, cbdata);
/* check & see if it's time to update the blocklist */ /* check & see if it's time to update the blocklist */
if (gtr_pref_flag_get(TR_KEY_blocklist_enabled) && if (gtr_pref_flag_get(TR_KEY_blocklist_enabled) && gtr_pref_flag_get(TR_KEY_blocklist_updates_enabled))
gtr_pref_flag_get(TR_KEY_blocklist_updates_enabled))
{ {
int64_t const last_time = gtr_pref_int_get(TR_KEY_blocklist_date); int64_t const last_time = gtr_pref_int_get(TR_KEY_blocklist_date);
int const SECONDS_IN_A_WEEK = 7 * 24 * 60 * 60; int const SECONDS_IN_A_WEEK = 7 * 24 * 60 * 60;
@ -623,8 +625,7 @@ int main(int argc, char** argv)
GError* error = NULL; GError* error = NULL;
struct cbdata cbdata; struct cbdata cbdata;
GOptionEntry option_entries[] = GOptionEntry option_entries[] = {
{
{ "config-dir", 'g', 0, G_OPTION_ARG_FILENAME, &cbdata.config_dir, _("Where to look for configuration files"), NULL }, { "config-dir", 'g', 0, G_OPTION_ARG_FILENAME, &cbdata.config_dir, _("Where to look for configuration files"), NULL },
{ "paused", 'p', 0, G_OPTION_ARG_NONE, &cbdata.start_paused, _("Start with all torrents paused"), NULL }, { "paused", 'p', 0, G_OPTION_ARG_NONE, &cbdata.start_paused, _("Start with all torrents paused"), NULL },
{ "minimized", 'm', 0, G_OPTION_ARG_NONE, &cbdata.is_iconified, _("Start minimized in notification area"), NULL }, { "minimized", 'm', 0, G_OPTION_ARG_NONE, &cbdata.is_iconified, _("Start minimized in notification area"), NULL },
@ -687,7 +688,9 @@ int main(int argc, char** argv)
/* init the application for the specified config dir */ /* init the application for the specified config dir */
stat(cbdata.config_dir, &sb); stat(cbdata.config_dir, &sb);
application_id = g_strdup_printf("com.transmissionbt.transmission_%lu_%lu", (unsigned long)sb.st_dev, application_id = g_strdup_printf(
"com.transmissionbt.transmission_%lu_%lu",
(unsigned long)sb.st_dev,
(unsigned long)sb.st_ino); (unsigned long)sb.st_ino);
app = gtk_application_new(application_id, G_APPLICATION_HANDLES_OPEN); app = gtk_application_new(application_id, G_APPLICATION_HANDLES_OPEN);
g_signal_connect(app, "open", G_CALLBACK(on_open), &cbdata); g_signal_connect(app, "open", G_CALLBACK(on_open), &cbdata);
@ -756,9 +759,14 @@ static void app_setup(GtkWindow* wind, struct cbdata* cbdata)
if (!gtr_pref_flag_get(TR_KEY_user_has_given_informed_consent)) if (!gtr_pref_flag_get(TR_KEY_user_has_given_informed_consent))
{ {
GtkWidget* w = gtk_message_dialog_new(GTK_WINDOW(wind), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_OTHER, GtkWidget* w = gtk_message_dialog_new(
GTK_BUTTONS_NONE, "%s", _("Transmission is a file sharing program. When you run a torrent, its data will be " GTK_WINDOW(wind),
"made available to others by means of upload. Any content you share is your sole responsibility.")); GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_OTHER,
GTK_BUTTONS_NONE,
"%s",
_("Transmission is a file sharing program. When you run a torrent, its data will be "
"made available to others by means of upload. Any content you share is your sole responsibility."));
gtk_dialog_add_button(GTK_DIALOG(w), _("_Cancel"), GTK_RESPONSE_REJECT); gtk_dialog_add_button(GTK_DIALOG(w), _("_Cancel"), GTK_RESPONSE_REJECT);
gtk_dialog_add_button(GTK_DIALOG(w), _("I _Agree"), GTK_RESPONSE_ACCEPT); gtk_dialog_add_button(GTK_DIALOG(w), _("I _Agree"), GTK_RESPONSE_ACCEPT);
gtk_dialog_set_default_response(GTK_DIALOG(w), GTK_RESPONSE_ACCEPT); gtk_dialog_set_default_response(GTK_DIALOG(w), GTK_RESPONSE_ACCEPT);
@ -779,10 +787,11 @@ static void app_setup(GtkWindow* wind, struct cbdata* cbdata)
static void placeWindowFromPrefs(GtkWindow* window) static void placeWindowFromPrefs(GtkWindow* window)
{ {
gtk_window_resize(window, (int)gtr_pref_int_get(TR_KEY_main_window_width), gtk_window_resize(
window,
(int)gtr_pref_int_get(TR_KEY_main_window_width),
(int)gtr_pref_int_get(TR_KEY_main_window_height)); (int)gtr_pref_int_get(TR_KEY_main_window_height));
gtk_window_move(window, (int)gtr_pref_int_get(TR_KEY_main_window_x), gtk_window_move(window, (int)gtr_pref_int_get(TR_KEY_main_window_x), (int)gtr_pref_int_get(TR_KEY_main_window_y));
(int)gtr_pref_int_get(TR_KEY_main_window_y));
} }
static void presentMainWindow(struct cbdata* cbdata) static void presentMainWindow(struct cbdata* cbdata)
@ -860,8 +869,15 @@ static void rowChangedCB(GtkTreeModel const* model, GtkTreePath* path, GtkTreeIt
} }
} }
static void on_drag_data_received(GtkWidget const* widget, GdkDragContext* drag_context, gint x, gint y, static void on_drag_data_received(
GtkSelectionData const* selection_data, guint info, guint time_, gpointer gdata) GtkWidget const* widget,
GdkDragContext* drag_context,
gint x,
gint y,
GtkSelectionData const* selection_data,
guint info,
guint time_,
gpointer gdata)
{ {
TR_UNUSED(widget); TR_UNUSED(widget);
TR_UNUSED(x); TR_UNUSED(x);
@ -1000,8 +1016,11 @@ static void on_app_exit(gpointer vdata)
c = GTK_WIDGET(cbdata->wind); c = GTK_WIDGET(cbdata->wind);
gtk_container_remove(GTK_CONTAINER(c), gtk_bin_get_child(GTK_BIN(c))); gtk_container_remove(GTK_CONTAINER(c), gtk_bin_get_child(GTK_BIN(c)));
p = p = g_object_new(
g_object_new(GTK_TYPE_GRID, "column-spacing", GUI_PAD_BIG, "halign", GTK_ALIGN_CENTER, "valign", GTK_ALIGN_CENTER, GTK_TYPE_GRID,
TR_ARG_TUPLE("column-spacing", GUI_PAD_BIG),
TR_ARG_TUPLE("halign", GTK_ALIGN_CENTER),
TR_ARG_TUPLE("valign", GTK_ALIGN_CENTER),
NULL); NULL);
gtk_container_add(GTK_CONTAINER(c), p); gtk_container_add(GTK_CONTAINER(c), p);
@ -1066,14 +1085,21 @@ static void flush_torrent_errors(struct cbdata* cbdata)
{ {
if (cbdata->error_list != NULL) if (cbdata->error_list != NULL)
{ {
show_torrent_errors(cbdata->wind, ngettext("Couldn't add corrupt torrent", "Couldn't add corrupt torrents", show_torrent_errors(
g_slist_length(cbdata->error_list)), &cbdata->error_list); cbdata->wind,
ngettext("Couldn't add corrupt torrent", "Couldn't add corrupt torrents", g_slist_length(cbdata->error_list)),
&cbdata->error_list);
} }
if (cbdata->duplicates_list != NULL) if (cbdata->duplicates_list != NULL)
{ {
show_torrent_errors(cbdata->wind, ngettext("Couldn't add duplicate torrent", "Couldn't add duplicate torrents", show_torrent_errors(
g_slist_length(cbdata->duplicates_list)), &cbdata->duplicates_list); cbdata->wind,
ngettext(
"Couldn't add duplicate torrent",
"Couldn't add duplicate torrents",
g_slist_length(cbdata->duplicates_list)),
&cbdata->duplicates_list);
} }
} }
@ -1388,30 +1414,30 @@ static gboolean update_model_loop(gpointer gdata)
static void show_about_dialog(GtkWindow* parent) static void show_about_dialog(GtkWindow* parent)
{ {
char const* uri = "https://transmissionbt.com/"; char const* uri = "https://transmissionbt.com/";
char const* authors[] = char const* authors[] = {
{
"Charles Kerr (Backend; GTK+)", "Charles Kerr (Backend; GTK+)",
"Mitchell Livingston (Backend; OS X)", "Mitchell Livingston (Backend; OS X)",
"Mike Gelfand", "Mike Gelfand",
NULL NULL,
}; };
gtk_show_about_dialog(parent, gtk_show_about_dialog(
"authors", authors, parent,
"comments", _("A fast and easy BitTorrent client"), TR_ARG_TUPLE("authors", authors),
"copyright", _("Copyright (c) The Transmission Project"), TR_ARG_TUPLE("comments", _("A fast and easy BitTorrent client")),
"logo-icon-name", MY_CONFIG_NAME, TR_ARG_TUPLE("copyright", _("Copyright (c) The Transmission Project")),
"name", g_get_application_name(), TR_ARG_TUPLE("logo-icon-name", MY_CONFIG_NAME),
TR_ARG_TUPLE("name", g_get_application_name()),
/* Translators: translate "translator-credits" as your name /* Translators: translate "translator-credits" as your name
to have it appear in the credits in the "About" to have it appear in the credits in the "About"
dialog */ dialog */
"translator-credits", _("translator-credits"), TR_ARG_TUPLE("translator-credits", _("translator-credits")),
"version", LONG_VERSION_STRING, TR_ARG_TUPLE("version", LONG_VERSION_STRING),
"website", uri, TR_ARG_TUPLE("website", uri),
"website-label", uri, TR_ARG_TUPLE("website-label", uri),
#ifdef SHOW_LICENSE #ifdef SHOW_LICENSE
"license", LICENSE, TR_ARG_TUPLE("license", LICENSE),
"wrap-license", TRUE, TR_ARG_TUPLE("wrap-license", TRUE),
#endif #endif
NULL); NULL);
} }
@ -1605,7 +1631,8 @@ void gtr_actions_handler(char const* action_name, gpointer user_data)
gtk_widget_show(w); gtk_widget_show(w);
} }
} }
else if (g_strcmp0(action_name, "torrent-start") == 0 || g_strcmp0(action_name, "torrent-start-now") == 0 || else if (
g_strcmp0(action_name, "torrent-start") == 0 || g_strcmp0(action_name, "torrent-start-now") == 0 ||
g_strcmp0(action_name, "torrent-stop") == 0 || g_strcmp0(action_name, "torrent-reannounce") == 0 || g_strcmp0(action_name, "torrent-stop") == 0 || g_strcmp0(action_name, "torrent-reannounce") == 0 ||
g_strcmp0(action_name, "torrent-verify") == 0 || g_strcmp0(action_name, "queue-move-top") == 0 || g_strcmp0(action_name, "torrent-verify") == 0 || g_strcmp0(action_name, "queue-move-top") == 0 ||
g_strcmp0(action_name, "queue-move-up") == 0 || g_strcmp0(action_name, "queue-move-down") == 0 || g_strcmp0(action_name, "queue-move-up") == 0 || g_strcmp0(action_name, "queue-move-down") == 0 ||

View File

@ -41,8 +41,7 @@ typedef struct
GtkTextBuffer* announce_text_buffer; GtkTextBuffer* announce_text_buffer;
TrCore* core; TrCore* core;
tr_metainfo_builder* builder; tr_metainfo_builder* builder;
} } MakeMetaUI;
MakeMetaUI;
static void freeMetaUI(gpointer p) static void freeMetaUI(gpointer p)
{ {
@ -163,7 +162,7 @@ static void onProgressDialogResponse(GtkDialog* d, int response, gpointer data)
case GTK_RESPONSE_ACCEPT: case GTK_RESPONSE_ACCEPT:
addTorrent(ui); addTorrent(ui);
/* fall-through */ /* fall-through */
case GTK_RESPONSE_CLOSE: case GTK_RESPONSE_CLOSE:
gtk_widget_destroy(ui->builder->result ? GTK_WIDGET(d) : ui->dialog); gtk_widget_destroy(ui->builder->result ? GTK_WIDGET(d) : ui->dialog);
@ -182,10 +181,13 @@ static void makeProgressDialog(GtkWidget* parent, MakeMetaUI* ui)
GtkWidget* v; GtkWidget* v;
GtkWidget* fr; GtkWidget* fr;
d = gtk_dialog_new_with_buttons(_("New Torrent"), GTK_WINDOW(parent), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, d = gtk_dialog_new_with_buttons(
_("_Cancel"), GTK_RESPONSE_CANCEL, _("New Torrent"),
_("_Close"), GTK_RESPONSE_CLOSE, GTK_WINDOW(parent),
_("_Add"), GTK_RESPONSE_ACCEPT, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
TR_ARG_TUPLE(_("_Cancel"), GTK_RESPONSE_CANCEL),
TR_ARG_TUPLE(_("_Close"), GTK_RESPONSE_CLOSE),
TR_ARG_TUPLE(_("_Add"), GTK_RESPONSE_ACCEPT),
NULL); NULL);
ui->progress_dialog = d; ui->progress_dialog = d;
g_signal_connect(d, "response", G_CALLBACK(onProgressDialogResponse), ui); g_signal_connect(d, "response", G_CALLBACK(onProgressDialogResponse), ui);
@ -312,13 +314,19 @@ static void updatePiecesLabel(MakeMetaUI* ui)
{ {
char buf[128]; char buf[128];
tr_strlsize(buf, builder->totalSize, sizeof(buf)); tr_strlsize(buf, builder->totalSize, sizeof(buf));
g_string_append_printf(gstr, ngettext("%1$s; %2$'d File", "%1$s; %2$'d Files", builder->fileCount), buf, g_string_append_printf(
gstr,
ngettext("%1$s; %2$'d File", "%1$s; %2$'d Files", builder->fileCount),
buf,
builder->fileCount); builder->fileCount);
g_string_append(gstr, "; "); g_string_append(gstr, "; ");
tr_formatter_mem_B(buf, builder->pieceSize, sizeof(buf)); tr_formatter_mem_B(buf, builder->pieceSize, sizeof(buf));
g_string_append_printf(gstr, ngettext("%1$'d Piece @ %2$s", "%1$'d Pieces @ %2$s", builder->pieceCount), g_string_append_printf(
builder->pieceCount, buf); gstr,
ngettext("%1$'d Piece @ %2$s", "%1$'d Pieces @ %2$s", builder->pieceCount),
builder->pieceCount,
buf);
} }
g_string_append(gstr, "</i>"); g_string_append(gstr, "</i>");
@ -386,8 +394,15 @@ static char const* getDefaultSavePath(void)
return g_get_user_special_dir(G_USER_DIRECTORY_DESKTOP); return g_get_user_special_dir(G_USER_DIRECTORY_DESKTOP);
} }
static void on_drag_data_received(GtkWidget const* widget, GdkDragContext* drag_context, gint x, gint y, static void on_drag_data_received(
GtkSelectionData const* selection_data, guint info, guint time_, gpointer user_data) GtkWidget const* widget,
GdkDragContext* drag_context,
gint x,
gint y,
GtkSelectionData const* selection_data,
guint info,
guint time_,
gpointer user_data)
{ {
TR_UNUSED(widget); TR_UNUSED(widget);
TR_UNUSED(x); TR_UNUSED(x);
@ -441,9 +456,12 @@ GtkWidget* gtr_torrent_creation_dialog_new(GtkWindow* parent, TrCore* core)
ui->core = core; ui->core = core;
d = gtk_dialog_new_with_buttons(_("New Torrent"), parent, GTK_DIALOG_DESTROY_WITH_PARENT, d = gtk_dialog_new_with_buttons(
_("_Close"), GTK_RESPONSE_CLOSE, _("New Torrent"),
_("_New"), GTK_RESPONSE_ACCEPT, parent,
GTK_DIALOG_DESTROY_WITH_PARENT,
TR_ARG_TUPLE(_("_Close"), GTK_RESPONSE_CLOSE),
TR_ARG_TUPLE(_("_New"), GTK_RESPONSE_ACCEPT),
NULL); NULL);
ui->dialog = d; ui->dialog = d;
g_signal_connect(d, "response", G_CALLBACK(onResponse), ui); g_signal_connect(d, "response", G_CALLBACK(onResponse), ui);
@ -470,7 +488,7 @@ GtkWidget* gtr_torrent_creation_dialog_new(GtkWindow* parent, TrCore* core)
gtk_widget_set_sensitive(GTK_WIDGET(w), FALSE); gtk_widget_set_sensitive(GTK_WIDGET(w), FALSE);
hig_workarea_add_row_w(t, &row, l, w, NULL); hig_workarea_add_row_w(t, &row, l, w, NULL);
slist = gtk_radio_button_get_group(GTK_RADIO_BUTTON(l)), slist = gtk_radio_button_get_group(GTK_RADIO_BUTTON(l));
l = gtk_radio_button_new_with_mnemonic(slist, _("Source _File:")); l = gtk_radio_button_new_with_mnemonic(slist, _("Source _File:"));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(l), TRUE); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(l), TRUE);
w = gtk_file_chooser_button_new(NULL, GTK_FILE_CHOOSER_ACTION_OPEN); w = gtk_file_chooser_button_new(NULL, GTK_FILE_CHOOSER_ACTION_OPEN);
@ -502,8 +520,10 @@ GtkWidget* gtr_torrent_creation_dialog_new(GtkWindow* parent, TrCore* core)
gtk_container_add(GTK_CONTAINER(fr), sw); gtk_container_add(GTK_CONTAINER(fr), sw);
gtk_box_pack_start(GTK_BOX(v), fr, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(v), fr, TRUE, TRUE, 0);
l = gtk_label_new(NULL); l = gtk_label_new(NULL);
gtk_label_set_markup(GTK_LABEL(l), _("To add a backup URL, add it on the line after the primary URL.\n" gtk_label_set_markup(
"To add another primary URL, add it after a blank line.")); GTK_LABEL(l),
_("To add a backup URL, add it on the line after the primary URL.\n"
"To add another primary URL, add it after a blank line."));
gtk_label_set_justify(GTK_LABEL(l), GTK_JUSTIFY_LEFT); gtk_label_set_justify(GTK_LABEL(l), GTK_JUSTIFY_LEFT);
g_object_set(l, "halign", GTK_ALIGN_START, "valign", GTK_ALIGN_CENTER, NULL); g_object_set(l, "halign", GTK_ALIGN_START, "valign", GTK_ALIGN_CENTER, NULL);
gtk_box_pack_start(GTK_BOX(v), l, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(v), l, FALSE, FALSE, 0);

View File

@ -135,8 +135,8 @@ static void doSave(GtkWindow* parent, struct MsgData* data, char const* filename
if (fp == NULL) if (fp == NULL)
{ {
GtkWidget* w = gtk_message_dialog_new(parent, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, _("Couldn't save \"%s\""), GtkWidget*
filename); w = gtk_message_dialog_new(parent, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, _("Couldn't save \"%s\""), filename);
gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(w), "%s", g_strerror(errno)); gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(w), "%s", g_strerror(errno));
g_signal_connect_swapped(w, "response", G_CALLBACK(gtk_widget_destroy), w); g_signal_connect_swapped(w, "response", G_CALLBACK(gtk_widget_destroy), w);
gtk_widget_show(w); gtk_widget_show(w);
@ -171,11 +171,15 @@ static void doSave(GtkWindow* parent, struct MsgData* data, char const* filename
break; break;
} }
fprintf(fp, "%s\t%s\t%s\t%s\n", date, levelStr, node->name != NULL ? node->name : "", fprintf(
fp,
"%s\t%s\t%s\t%s\n",
date,
levelStr,
node->name != NULL ? node->name : "",
node->message != NULL ? node->message : ""); node->message != NULL ? node->message : "");
g_free(date); g_free(date);
} } while (gtk_tree_model_iter_next(model, &iter));
while (gtk_tree_model_iter_next(model, &iter));
} }
fclose(fp); fclose(fp);
@ -197,9 +201,12 @@ static void onSaveDialogResponse(GtkWidget* d, int response, gpointer data)
static void onSaveRequest(GtkWidget* w, gpointer data) static void onSaveRequest(GtkWidget* w, gpointer data)
{ {
GtkWindow* window = GTK_WINDOW(gtk_widget_get_toplevel(w)); GtkWindow* window = GTK_WINDOW(gtk_widget_get_toplevel(w));
GtkWidget* d = gtk_file_chooser_dialog_new(_("Save Log"), window, GTK_FILE_CHOOSER_ACTION_SAVE, GtkWidget* d = gtk_file_chooser_dialog_new(
_("_Cancel"), GTK_RESPONSE_CANCEL, _("Save Log"),
_("_Save"), GTK_RESPONSE_ACCEPT, window,
GTK_FILE_CHOOSER_ACTION_SAVE,
TR_ARG_TUPLE(_("_Cancel"), GTK_RESPONSE_CANCEL),
TR_ARG_TUPLE(_("_Save"), GTK_RESPONSE_ACCEPT),
NULL); NULL);
g_signal_connect(d, "response", G_CALLBACK(onSaveDialogResponse), data); g_signal_connect(d, "response", G_CALLBACK(onSaveDialogResponse), data);
@ -243,7 +250,11 @@ static char const* getForegroundColor(int msgLevel)
} }
} }
static void renderText(GtkTreeViewColumn* column, GtkCellRenderer* renderer, GtkTreeModel* tree_model, GtkTreeIter* iter, static void renderText(
GtkTreeViewColumn* column,
GtkCellRenderer* renderer,
GtkTreeModel* tree_model,
GtkTreeIter* iter,
gpointer gcol) gpointer gcol)
{ {
TR_UNUSED(column); TR_UNUSED(column);
@ -256,7 +267,11 @@ static void renderText(GtkTreeViewColumn* column, GtkCellRenderer* renderer, Gtk
g_object_set(renderer, "text", str, "foreground", getForegroundColor(node->level), "ellipsize", PANGO_ELLIPSIZE_END, NULL); g_object_set(renderer, "text", str, "foreground", getForegroundColor(node->level), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
} }
static void renderTime(GtkTreeViewColumn* column, GtkCellRenderer* renderer, GtkTreeModel* tree_model, GtkTreeIter* iter, static void renderTime(
GtkTreeViewColumn* column,
GtkCellRenderer* renderer,
GtkTreeModel* tree_model,
GtkTreeIter* iter,
gpointer data) gpointer data)
{ {
TR_UNUSED(column); TR_UNUSED(column);
@ -363,11 +378,14 @@ static tr_log_message* addMessages(GtkListStore* store, struct tr_log_message* h
{ {
char const* name = i->name != NULL ? i->name : default_name; char const* name = i->name != NULL ? i->name : default_name;
gtk_list_store_insert_with_values(store, NULL, 0, gtk_list_store_insert_with_values(
COL_TR_MSG, i, store,
COL_NAME, name, NULL,
COL_MESSAGE, i->message, 0,
COL_SEQUENCE, ++sequence, TR_ARG_TUPLE(COL_TR_MSG, i),
TR_ARG_TUPLE(COL_NAME, name),
TR_ARG_TUPLE(COL_MESSAGE, i->message),
TR_ARG_TUPLE(COL_SEQUENCE, ++sequence),
-1); -1);
/* if it's an error message, dump it to the terminal too */ /* if it's an error message, dump it to the terminal too */
@ -428,9 +446,9 @@ static gboolean onRefresh(gpointer gdata)
static GtkWidget* debug_level_combo_new(void) static GtkWidget* debug_level_combo_new(void)
{ {
GtkWidget* w = gtr_combo_box_new_enum( GtkWidget* w = gtr_combo_box_new_enum(
_("Error"), TR_LOG_ERROR, TR_ARG_TUPLE(_("Error"), TR_LOG_ERROR),
_("Information"), TR_LOG_INFO, TR_ARG_TUPLE(_("Information"), TR_LOG_INFO),
_("Debug"), TR_LOG_DEBUG, TR_ARG_TUPLE(_("Debug"), TR_LOG_DEBUG),
NULL); NULL);
gtr_combo_box_set_active_enum(GTK_COMBO_BOX(w), gtr_pref_int_get(TR_KEY_message_level)); gtr_combo_box_set_active_enum(GTK_COMBO_BOX(w), gtr_pref_int_get(TR_KEY_message_level));
return w; return w;
@ -469,21 +487,23 @@ GtkWidget* gtr_message_log_window_new(GtkWindow* parent, TrCore* core)
gtk_style_context_add_class(gtk_widget_get_style_context(toolbar), GTK_STYLE_CLASS_PRIMARY_TOOLBAR); gtk_style_context_add_class(gtk_widget_get_style_context(toolbar), GTK_STYLE_CLASS_PRIMARY_TOOLBAR);
item = gtk_tool_button_new(NULL, NULL); item = gtk_tool_button_new(NULL, NULL);
g_object_set(item, g_object_set(
"icon-name", "document-save-as", item,
"is-important", TRUE, TR_ARG_TUPLE("icon-name", "document-save-as"),
"label", _("Save _As"), TR_ARG_TUPLE("is-important", TRUE),
"use-underline", TRUE, TR_ARG_TUPLE("label", _("Save _As")),
TR_ARG_TUPLE("use-underline", TRUE),
NULL); NULL);
g_signal_connect(item, "clicked", G_CALLBACK(onSaveRequest), data); g_signal_connect(item, "clicked", G_CALLBACK(onSaveRequest), data);
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1); gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
item = gtk_tool_button_new(NULL, NULL); item = gtk_tool_button_new(NULL, NULL);
g_object_set(item, g_object_set(
"icon-name", "edit-clear", item,
"is-important", TRUE, TR_ARG_TUPLE("icon-name", "edit-clear"),
"label", _("Clear"), TR_ARG_TUPLE("is-important", TRUE),
"use-underline", TRUE, TR_ARG_TUPLE("label", _("Clear")),
TR_ARG_TUPLE("use-underline", TRUE),
NULL); NULL);
g_signal_connect(item, "clicked", G_CALLBACK(onClearRequest), data); g_signal_connect(item, "clicked", G_CALLBACK(onClearRequest), data);
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1); gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
@ -492,11 +512,12 @@ GtkWidget* gtr_message_log_window_new(GtkWindow* parent, TrCore* core)
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1); gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
item = gtk_toggle_tool_button_new(); item = gtk_toggle_tool_button_new();
g_object_set(G_OBJECT(item), g_object_set(
"icon-name", "media-playback-pause", G_OBJECT(item),
"is-important", TRUE, TR_ARG_TUPLE("icon-name", "media-playback-pause"),
"label", _("P_ause"), TR_ARG_TUPLE("is-important", TRUE),
"use-underline", TRUE, TR_ARG_TUPLE("label", _("P_ause")),
TR_ARG_TUPLE("use-underline", TRUE),
NULL); NULL);
g_signal_connect(item, "toggled", G_CALLBACK(onPauseToggled), data); g_signal_connect(item, "toggled", G_CALLBACK(onPauseToggled), data);
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1); gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
@ -522,7 +543,8 @@ GtkWidget* gtr_message_log_window_new(GtkWindow* parent, TrCore* core)
*** messages *** messages
**/ **/
data->store = gtk_list_store_new(N_COLUMNS, data->store = gtk_list_store_new(
N_COLUMNS,
G_TYPE_UINT, /* sequence */ G_TYPE_UINT, /* sequence */
G_TYPE_POINTER, /* category */ G_TYPE_POINTER, /* category */
G_TYPE_POINTER, /* message */ G_TYPE_POINTER, /* message */

View File

@ -26,8 +26,7 @@ typedef struct TrNotification
{ {
TrCore* core; TrCore* core;
int torrent_id; int torrent_id;
} } TrNotification;
TrNotification;
static void tr_notification_free(gpointer data) static void tr_notification_free(gpointer data)
{ {
@ -75,7 +74,11 @@ static void get_capabilities_callback(GObject* source, GAsyncResult* res, gpoint
g_variant_unref(result); g_variant_unref(result);
} }
static void g_signal_callback(GDBusProxy const* dbus_proxy, char const* sender_name, char const* signal_name, GVariant* params, static void g_signal_callback(
GDBusProxy const* dbus_proxy,
char const* sender_name,
char const* signal_name,
GVariant* params,
gconstpointer user_data) gconstpointer user_data)
{ {
TR_UNUSED(dbus_proxy); TR_UNUSED(dbus_proxy);
@ -139,15 +142,30 @@ static void dbus_proxy_ready_callback(GObject* source, GAsyncResult* res, gpoint
} }
g_signal_connect(proxy, "g-signal", G_CALLBACK(g_signal_callback), NULL); g_signal_connect(proxy, "g-signal", G_CALLBACK(g_signal_callback), NULL);
g_dbus_proxy_call(proxy, "GetCapabilities", g_variant_new("()"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, g_dbus_proxy_call(
get_capabilities_callback, NULL); proxy,
"GetCapabilities",
g_variant_new("()"),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
get_capabilities_callback,
NULL);
} }
void gtr_notify_init(void) void gtr_notify_init(void)
{ {
active_notifications = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, tr_notification_free); active_notifications = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, tr_notification_free);
g_dbus_proxy_new_for_bus(G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL, NOTIFICATIONS_DBUS_NAME, g_dbus_proxy_new_for_bus(
NOTIFICATIONS_DBUS_CORE_OBJECT, NOTIFICATIONS_DBUS_CORE_INTERFACE, NULL, dbus_proxy_ready_callback, NULL); G_BUS_TYPE_SESSION,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
NULL,
NOTIFICATIONS_DBUS_NAME,
NOTIFICATIONS_DBUS_CORE_OBJECT,
NOTIFICATIONS_DBUS_CORE_INTERFACE,
NULL,
dbus_proxy_ready_callback,
NULL);
} }
static void notify_callback(GObject* source, GAsyncResult* res, gpointer user_data) static void notify_callback(GObject* source, GAsyncResult* res, gpointer user_data)
@ -180,7 +198,8 @@ void gtr_notify_torrent_completed(TrCore* core, int torrent_id)
if (gtr_pref_flag_get(TR_KEY_torrent_complete_sound_enabled)) if (gtr_pref_flag_get(TR_KEY_torrent_complete_sound_enabled))
{ {
char** argv = gtr_pref_strv_get(TR_KEY_torrent_complete_sound_command); char** argv = gtr_pref_strv_get(TR_KEY_torrent_complete_sound_command);
g_spawn_async(NULL /*cwd*/, g_spawn_async(
NULL /*cwd*/,
argv, argv,
NULL /*envp*/, NULL /*envp*/,
G_SPAWN_SEARCH_PATH, G_SPAWN_SEARCH_PATH,
@ -227,9 +246,24 @@ void gtr_notify_torrent_completed(TrCore* core, int torrent_id)
g_variant_builder_init(&hints_builder, G_VARIANT_TYPE("a{sv}")); g_variant_builder_init(&hints_builder, G_VARIANT_TYPE("a{sv}"));
g_variant_builder_add(&hints_builder, "{sv}", "category", g_variant_new_string("transfer.complete")); g_variant_builder_add(&hints_builder, "{sv}", "category", g_variant_new_string("transfer.complete"));
g_dbus_proxy_call(proxy, "Notify", g_variant_new("(susssasa{sv}i)", "Transmission", 0, "transmission", g_dbus_proxy_call(
_("Torrent Complete"), tr_torrentName(tor), &actions_builder, &hints_builder, -1), G_DBUS_CALL_FLAGS_NONE, -1, NULL, proxy,
notify_callback, n); "Notify",
g_variant_new(
"(susssasa{sv}i)",
"Transmission",
0,
"transmission",
_("Torrent Complete"),
tr_torrentName(tor),
&actions_builder,
&hints_builder,
-1),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
notify_callback,
n);
} }
void gtr_notify_torrent_added(char const* name) void gtr_notify_torrent_added(char const* name)
@ -244,6 +278,13 @@ void gtr_notify_torrent_added(char const* name)
} }
n = g_new0(TrNotification, 1); n = g_new0(TrNotification, 1);
g_dbus_proxy_call(proxy, "Notify", g_variant_new("(susssasa{sv}i)", "Transmission", 0, "transmission", _("Torrent Added"), g_dbus_proxy_call(
name, NULL, NULL, -1), G_DBUS_CALL_FLAGS_NONE, -1, NULL, notify_callback, n); proxy,
"Notify",
g_variant_new("(susssasa{sv}i)", "Transmission", 0, "transmission", _("Torrent Added"), name, NULL, NULL, -1),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
notify_callback,
n);
} }

View File

@ -281,9 +281,12 @@ GtkWidget* gtr_torrent_options_dialog_new(GtkWindow* parent, TrCore* core, tr_ct
GSList* list; GSList* list;
/* make the dialog */ /* make the dialog */
d = gtk_dialog_new_with_buttons(_("Torrent Options"), parent, GTK_DIALOG_DESTROY_WITH_PARENT, d = gtk_dialog_new_with_buttons(
_("_Cancel"), GTK_RESPONSE_CANCEL, _("Torrent Options"),
_("_Open"), GTK_RESPONSE_ACCEPT, parent,
GTK_DIALOG_DESTROY_WITH_PARENT,
TR_ARG_TUPLE(_("_Cancel"), GTK_RESPONSE_CANCEL),
TR_ARG_TUPLE(_("_Open"), GTK_RESPONSE_ACCEPT),
NULL); NULL);
gtk_dialog_set_default_response(GTK_DIALOG(d), GTK_RESPONSE_ACCEPT); gtk_dialog_set_default_response(GTK_DIALOG(d), GTK_RESPONSE_ACCEPT);
@ -454,9 +457,12 @@ GtkWidget* gtr_torrent_open_from_file_dialog_new(GtkWindow* parent, TrCore* core
GtkWidget* c; GtkWidget* c;
char const* folder; char const* folder;
w = gtk_file_chooser_dialog_new(_("Open a Torrent"), parent, GTK_FILE_CHOOSER_ACTION_OPEN, w = gtk_file_chooser_dialog_new(
_("_Cancel"), GTK_RESPONSE_CANCEL, _("Open a Torrent"),
_("_Open"), GTK_RESPONSE_ACCEPT, parent,
GTK_FILE_CHOOSER_ACTION_OPEN,
TR_ARG_TUPLE(_("_Cancel"), GTK_RESPONSE_CANCEL),
TR_ARG_TUPLE(_("_Open"), GTK_RESPONSE_ACCEPT),
NULL); NULL);
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(w), TRUE); gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(w), TRUE);
addTorrentFilters(GTK_FILE_CHOOSER(w)); addTorrentFilters(GTK_FILE_CHOOSER(w));
@ -519,9 +525,12 @@ GtkWidget* gtr_torrent_open_from_url_dialog_new(GtkWindow* parent, TrCore* core)
GtkWidget* t; GtkWidget* t;
GtkWidget* w; GtkWidget* w;
w = gtk_dialog_new_with_buttons(_("Open URL"), parent, GTK_DIALOG_DESTROY_WITH_PARENT, w = gtk_dialog_new_with_buttons(
_("_Cancel"), GTK_RESPONSE_CANCEL, _("Open URL"),
_("_Open"), GTK_RESPONSE_ACCEPT, parent,
GTK_DIALOG_DESTROY_WITH_PARENT,
TR_ARG_TUPLE(_("_Cancel"), GTK_RESPONSE_CANCEL),
TR_ARG_TUPLE(_("_Open"), GTK_RESPONSE_ACCEPT),
NULL); NULL);
g_signal_connect(w, "response", G_CALLBACK(onOpenURLResponse), core); g_signal_connect(w, "response", G_CALLBACK(onOpenURLResponse), core);

View File

@ -72,8 +72,13 @@ static gboolean onTimer(gpointer gdata)
if (done == TR_LOC_ERROR) if (done == TR_LOC_ERROR)
{ {
int const flags = GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT; int const flags = GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT;
GtkWidget* w = gtk_message_dialog_new(GTK_WINDOW(data->message_dialog), flags, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, GtkWidget* w = gtk_message_dialog_new(
"%s", _("Couldn't move torrent")); GTK_WINDOW(data->message_dialog),
flags,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
"%s",
_("Couldn't move torrent"));
gtk_dialog_run(GTK_DIALOG(w)); gtk_dialog_run(GTK_DIALOG(w));
gtk_widget_destroy(GTK_WIDGET(data->message_dialog)); gtk_widget_destroy(GTK_WIDGET(data->message_dialog));
} }
@ -108,8 +113,12 @@ static void onResponse(GtkDialog* dialog, int response, gconstpointer user_data)
data->do_move = gtk_toggle_button_get_active(move_tb); data->do_move = gtk_toggle_button_get_active(move_tb);
/* pop up a dialog saying that the work is in progress */ /* pop up a dialog saying that the work is in progress */
w = gtk_message_dialog_new(GTK_WINDOW(dialog), GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, w = gtk_message_dialog_new(
GTK_BUTTONS_CLOSE, NULL); GTK_WINDOW(dialog),
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
GTK_MESSAGE_INFO,
GTK_BUTTONS_CLOSE,
NULL);
gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(w), _("This may take a moment…")); gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(w), _("This may take a moment…"));
gtk_dialog_set_response_sensitive(GTK_DIALOG(w), GTK_RESPONSE_CLOSE, FALSE); gtk_dialog_set_response_sensitive(GTK_DIALOG(w), GTK_RESPONSE_CLOSE, FALSE);
gtk_widget_show(w); gtk_widget_show(w);
@ -138,9 +147,12 @@ GtkWidget* gtr_relocate_dialog_new(GtkWindow* parent, TrCore* core, GSList* torr
GtkWidget* t; GtkWidget* t;
struct relocate_dialog_data* data; struct relocate_dialog_data* data;
d = gtk_dialog_new_with_buttons(_("Set Torrent Location"), parent, GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL, d = gtk_dialog_new_with_buttons(
_("_Cancel"), GTK_RESPONSE_CANCEL, _("Set Torrent Location"),
_("_Apply"), GTK_RESPONSE_APPLY, parent,
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
TR_ARG_TUPLE(_("_Cancel"), GTK_RESPONSE_CANCEL),
TR_ARG_TUPLE(_("_Apply"), GTK_RESPONSE_APPLY),
NULL); NULL);
gtk_dialog_set_default_response(GTK_DIALOG(d), GTK_RESPONSE_CANCEL); gtk_dialog_set_default_response(GTK_DIALOG(d), GTK_RESPONSE_CANCEL);
g_signal_connect(d, "response", G_CALLBACK(onResponse), NULL); g_signal_connect(d, "response", G_CALLBACK(onResponse), NULL);

View File

@ -90,13 +90,15 @@ static void dialogResponse(GtkDialog* dialog, gint response, gpointer gdata)
if (response == TR_RESPONSE_RESET) if (response == TR_RESPONSE_RESET)
{ {
char const* primary = _("Reset your statistics?"); char const* primary = _("Reset your statistics?");
char const* secondary = _("These statistics are for your information only. " char const* secondary = _(
"These statistics are for your information only. "
"Resetting them doesn't affect the statistics logged by your BitTorrent trackers."); "Resetting them doesn't affect the statistics logged by your BitTorrent trackers.");
int const flags = GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL; int const flags = GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL;
GtkWidget* w = gtk_message_dialog_new(GTK_WINDOW(dialog), flags, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, "%s", primary); GtkWidget* w = gtk_message_dialog_new(GTK_WINDOW(dialog), flags, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, "%s", primary);
gtk_dialog_add_buttons(GTK_DIALOG(w), gtk_dialog_add_buttons(
_("_Cancel"), GTK_RESPONSE_CANCEL, GTK_DIALOG(w),
_("_Reset"), TR_RESPONSE_RESET, TR_ARG_TUPLE(_("_Cancel"), GTK_RESPONSE_CANCEL),
TR_ARG_TUPLE(_("_Reset"), TR_RESPONSE_RESET),
NULL); NULL);
gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(w), "%s", secondary); gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(w), "%s", secondary);
@ -124,9 +126,12 @@ GtkWidget* gtr_stats_dialog_new(GtkWindow* parent, TrCore* core)
guint row = 0; guint row = 0;
struct stat_ui* ui = g_new0(struct stat_ui, 1); struct stat_ui* ui = g_new0(struct stat_ui, 1);
d = gtk_dialog_new_with_buttons(_("Statistics"), parent, GTK_DIALOG_DESTROY_WITH_PARENT, d = gtk_dialog_new_with_buttons(
_("_Reset"), TR_RESPONSE_RESET, _("Statistics"),
_("_Close"), GTK_RESPONSE_CLOSE, parent,
GTK_DIALOG_DESTROY_WITH_PARENT,
TR_ARG_TUPLE(_("_Reset"), TR_RESPONSE_RESET),
TR_ARG_TUPLE(_("_Close"), GTK_RESPONSE_CLOSE),
NULL); NULL);
gtk_dialog_set_default_response(GTK_DIALOG(d), GTK_RESPONSE_CLOSE); gtk_dialog_set_default_response(GTK_DIALOG(d), GTK_RESPONSE_CLOSE);
t = hig_workarea_create(); t = hig_workarea_create();

View File

@ -52,7 +52,8 @@ static void getProgressString(GString* gstr, tr_torrent const* tor, tr_info cons
if (!isDone) /* downloading */ if (!isDone) /* downloading */
{ {
g_string_append_printf(gstr, g_string_append_printf(
gstr,
/* %1$s is how much we've got, /* %1$s is how much we've got,
%2$s is how much we'll have when done, %2$s is how much we'll have when done,
%3$s%% is a percentage of the two */ %3$s%% is a percentage of the two */
@ -65,7 +66,8 @@ static void getProgressString(GString* gstr, tr_torrent const* tor, tr_info cons
{ {
if (hasSeedRatio) if (hasSeedRatio)
{ {
g_string_append_printf(gstr, g_string_append_printf(
gstr,
/* %1$s is how much we've got, /* %1$s is how much we've got,
%2$s is the torrent's total size, %2$s is the torrent's total size,
%3$s%% is a percentage of the two, %3$s%% is a percentage of the two,
@ -82,7 +84,8 @@ static void getProgressString(GString* gstr, tr_torrent const* tor, tr_info cons
} }
else else
{ {
g_string_append_printf(gstr, g_string_append_printf(
gstr,
/* %1$s is how much we've got, /* %1$s is how much we've got,
%2$s is the torrent's total size, %2$s is the torrent's total size,
%3$s%% is a percentage of the two, %3$s%% is a percentage of the two,
@ -100,7 +103,8 @@ static void getProgressString(GString* gstr, tr_torrent const* tor, tr_info cons
{ {
if (hasSeedRatio) if (hasSeedRatio)
{ {
g_string_append_printf(gstr, g_string_append_printf(
gstr,
/* %1$s is the torrent's total size, /* %1$s is the torrent's total size,
%2$s is how much we've uploaded, %2$s is how much we've uploaded,
%3$s is our upload-to-download ratio, %3$s is our upload-to-download ratio,
@ -113,7 +117,8 @@ static void getProgressString(GString* gstr, tr_torrent const* tor, tr_info cons
} }
else /* seeding w/o a ratio */ else /* seeding w/o a ratio */
{ {
g_string_append_printf(gstr, g_string_append_printf(
gstr,
/* %1$s is the torrent's total size, /* %1$s is the torrent's total size,
%2$s is how much we've uploaded, %2$s is how much we've uploaded,
%3$s is our upload-to-download ratio */ %3$s is our upload-to-download ratio */
@ -144,8 +149,13 @@ static void getProgressString(GString* gstr, tr_torrent const* tor, tr_info cons
} }
} }
static char* getShortTransferString(tr_torrent const* tor, tr_stat const* st, double uploadSpeed_KBps, static char* getShortTransferString(
double downloadSpeed_KBps, char* buf, size_t buflen) tr_torrent const* tor,
tr_stat const* st,
double uploadSpeed_KBps,
double downloadSpeed_KBps,
char* buf,
size_t buflen)
{ {
bool const haveMeta = tr_torrentHasMetadata(tor); bool const haveMeta = tr_torrentHasMetadata(tor);
bool const haveUp = haveMeta && st->peersGettingFromUs > 0; bool const haveUp = haveMeta && st->peersGettingFromUs > 0;
@ -159,7 +169,13 @@ static char* getShortTransferString(tr_torrent const* tor, tr_stat const* st, do
tr_formatter_speed_KBps(upStr, uploadSpeed_KBps, sizeof(upStr)); tr_formatter_speed_KBps(upStr, uploadSpeed_KBps, sizeof(upStr));
/* down speed, down symbol, up speed, up symbol */ /* down speed, down symbol, up speed, up symbol */
g_snprintf(buf, buflen, _("%1$s %2$s %3$s %4$s"), dnStr, gtr_get_unicode_string(GTR_UNICODE_DOWN), upStr, g_snprintf(
buf,
buflen,
_("%1$s %2$s %3$s %4$s"),
dnStr,
gtr_get_unicode_string(GTR_UNICODE_DOWN),
upStr,
gtr_get_unicode_string(GTR_UNICODE_UP)); gtr_get_unicode_string(GTR_UNICODE_UP));
} }
else if (haveUp) else if (haveUp)
@ -182,7 +198,11 @@ static char* getShortTransferString(tr_torrent const* tor, tr_stat const* st, do
return buf; return buf;
} }
static void getShortStatusString(GString* gstr, tr_torrent const* tor, tr_stat const* st, double uploadSpeed_KBps, static void getShortStatusString(
GString* gstr,
tr_torrent const* tor,
tr_stat const* st,
double uploadSpeed_KBps,
double downloadSpeed_KBps) double downloadSpeed_KBps)
{ {
switch (st->activity) switch (st->activity)
@ -204,8 +224,7 @@ static void getShortStatusString(GString* gstr, tr_torrent const* tor, tr_stat c
break; break;
case TR_STATUS_CHECK: case TR_STATUS_CHECK:
g_string_append_printf(gstr, _("Verifying local data (%.1f%% tested)"), g_string_append_printf(gstr, _("Verifying local data (%.1f%% tested)"), tr_truncd(st->recheckProgress * 100.0, 1));
tr_truncd(st->recheckProgress * 100.0, 1));
break; break;
case TR_STATUS_DOWNLOAD: case TR_STATUS_DOWNLOAD:
@ -226,17 +245,20 @@ static void getShortStatusString(GString* gstr, tr_torrent const* tor, tr_stat c
} }
} }
static void getStatusString(GString* gstr, tr_torrent const* tor, tr_stat const* st, double const uploadSpeed_KBps, static void getStatusString(
GString* gstr,
tr_torrent const* tor,
tr_stat const* st,
double const uploadSpeed_KBps,
double const downloadSpeed_KBps) double const downloadSpeed_KBps)
{ {
if (st->error != 0) if (st->error != 0)
{ {
char const* fmt[] = char const* fmt[] = {
{
NULL, NULL,
N_("Tracker gave a warning: \"%s\""), N_("Tracker gave a warning: \"%s\""),
N_("Tracker gave an error: \"%s\""), N_("Tracker gave an error: \"%s\""),
N_("Error: %s") N_("Error: %s"),
}; };
g_string_append_printf(gstr, _(fmt[st->error]), st->errorString); g_string_append_printf(gstr, _(fmt[st->error]), st->errorString);
@ -260,35 +282,57 @@ static void getStatusString(GString* gstr, tr_torrent const* tor, tr_stat const*
if (!tr_torrentHasMetadata(tor)) if (!tr_torrentHasMetadata(tor))
{ {
/* Downloading metadata from 2 peer (s)(50% done) */ /* Downloading metadata from 2 peer (s)(50% done) */
g_string_append_printf(gstr, _("Downloading metadata from %1$'d %2$s (%3$d%% done)"), st->peersConnected, g_string_append_printf(
ngettext("peer", "peers", st->peersConnected), (int)(100.0 * st->metadataPercentComplete)); gstr,
_("Downloading metadata from %1$'d %2$s (%3$d%% done)"),
st->peersConnected,
ngettext("peer", "peers", st->peersConnected),
(int)(100.0 * st->metadataPercentComplete));
} }
else if (st->peersSendingToUs != 0 && st->webseedsSendingToUs != 0) else if (st->peersSendingToUs != 0 && st->webseedsSendingToUs != 0)
{ {
/* Downloading from 2 of 3 peer (s) and 2 webseed (s) */ /* Downloading from 2 of 3 peer (s) and 2 webseed (s) */
g_string_append_printf(gstr, _("Downloading from %1$'d of %2$'d %3$s and %4$'d %5$s"), st->peersSendingToUs, g_string_append_printf(
st->peersConnected, ngettext("peer", "peers", st->peersConnected), st->webseedsSendingToUs, gstr,
_("Downloading from %1$'d of %2$'d %3$s and %4$'d %5$s"),
st->peersSendingToUs,
st->peersConnected,
ngettext("peer", "peers", st->peersConnected),
st->webseedsSendingToUs,
ngettext("web seed", "web seeds", st->webseedsSendingToUs)); ngettext("web seed", "web seeds", st->webseedsSendingToUs));
} }
else if (st->webseedsSendingToUs != 0) else if (st->webseedsSendingToUs != 0)
{ {
/* Downloading from 3 web seed (s) */ /* Downloading from 3 web seed (s) */
g_string_append_printf(gstr, _("Downloading from %1$'d %2$s"), st->webseedsSendingToUs, g_string_append_printf(
gstr,
_("Downloading from %1$'d %2$s"),
st->webseedsSendingToUs,
ngettext("web seed", "web seeds", st->webseedsSendingToUs)); ngettext("web seed", "web seeds", st->webseedsSendingToUs));
} }
else else
{ {
/* Downloading from 2 of 3 peer (s) */ /* Downloading from 2 of 3 peer (s) */
g_string_append_printf(gstr, _("Downloading from %1$'d of %2$'d %3$s"), st->peersSendingToUs, g_string_append_printf(
st->peersConnected, ngettext("peer", "peers", st->peersConnected)); gstr,
_("Downloading from %1$'d of %2$'d %3$s"),
st->peersSendingToUs,
st->peersConnected,
ngettext("peer", "peers", st->peersConnected));
} }
break; break;
} }
case TR_STATUS_SEED: case TR_STATUS_SEED:
g_string_append_printf(gstr, ngettext("Seeding to %1$'d of %2$'d connected peer", g_string_append_printf(
"Seeding to %1$'d of %2$'d connected peers", st->peersConnected), st->peersGettingFromUs, st->peersConnected); gstr,
ngettext(
"Seeding to %1$'d of %2$'d connected peer",
"Seeding to %1$'d of %2$'d connected peers",
st->peersConnected),
st->peersGettingFromUs,
st->peersConnected);
break; break;
} }
} }
@ -330,8 +374,7 @@ typedef struct TorrentCellRendererPrivate
double download_speed_KBps; double download_speed_KBps;
gboolean compact; gboolean compact;
} } TorrentCellRendererPrivate;
TorrentCellRendererPrivate;
/*** /***
**** ****
@ -366,7 +409,10 @@ static GdkPixbuf* get_icon(tr_torrent const* tor, GtkIconSize icon_size, GtkWidg
**** ****
***/ ***/
static void gtr_cell_renderer_get_preferred_size(GtkCellRenderer* renderer, GtkWidget* widget, GtkRequisition* minimum_size, static void gtr_cell_renderer_get_preferred_size(
GtkCellRenderer* renderer,
GtkWidget* widget,
GtkRequisition* minimum_size,
GtkRequisition* natural_size) GtkRequisition* natural_size)
{ {
gtk_cell_renderer_get_preferred_size(renderer, widget, minimum_size, natural_size); gtk_cell_renderer_get_preferred_size(renderer, widget, minimum_size, natural_size);
@ -450,7 +496,12 @@ static void get_size_full(TorrentCellRenderer* cell, GtkWidget* widget, gint* wi
/* get the idealized cell dimensions */ /* get the idealized cell dimensions */
g_object_set(p->icon_renderer, "pixbuf", icon, NULL); g_object_set(p->icon_renderer, "pixbuf", icon, NULL);
gtr_cell_renderer_get_preferred_size(p->icon_renderer, widget, NULL, &icon_size); gtr_cell_renderer_get_preferred_size(p->icon_renderer, widget, NULL, &icon_size);
g_object_set(p->text_renderer, "text", name, "weight", PANGO_WEIGHT_BOLD, "scale", 1.0, "ellipsize", PANGO_ELLIPSIZE_NONE, g_object_set(
p->text_renderer,
TR_ARG_TUPLE("text", name),
TR_ARG_TUPLE("weight", PANGO_WEIGHT_BOLD),
TR_ARG_TUPLE("scale", 1.0),
TR_ARG_TUPLE("ellipsize", PANGO_ELLIPSIZE_NONE),
NULL); NULL);
gtr_cell_renderer_get_preferred_size(p->text_renderer, widget, NULL, &name_size); gtr_cell_renderer_get_preferred_size(p->text_renderer, widget, NULL, &name_size);
g_object_set(p->text_renderer, "text", gstr_prog->str, "weight", PANGO_WEIGHT_NORMAL, "scale", SMALL_SCALE, NULL); g_object_set(p->text_renderer, "text", gstr_prog->str, "weight", PANGO_WEIGHT_NORMAL, "scale", SMALL_SCALE, NULL);
@ -477,8 +528,14 @@ static void get_size_full(TorrentCellRenderer* cell, GtkWidget* widget, gint* wi
g_object_unref(icon); g_object_unref(icon);
} }
static void torrent_cell_renderer_get_size(GtkCellRenderer* cell, GtkWidget* widget, GdkRectangle const* cell_area, static void torrent_cell_renderer_get_size(
gint* x_offset, gint* y_offset, gint* width, gint* height) GtkCellRenderer* cell,
GtkWidget* widget,
GdkRectangle const* cell_area,
gint* x_offset,
gint* y_offset,
gint* width,
gint* height)
{ {
TorrentCellRenderer const* const self = TORRENT_CELL_RENDERER(cell); TorrentCellRenderer const* const self = TORRENT_CELL_RENDERER(cell);
@ -563,14 +620,23 @@ static double get_percent_done(tr_torrent const* tor, tr_stat const* st, bool* s
typedef cairo_t GtrDrawable; typedef cairo_t GtrDrawable;
static void gtr_cell_renderer_render(GtkCellRenderer* renderer, GtrDrawable* drawable, GtkWidget* widget, static void gtr_cell_renderer_render(
GdkRectangle const* area, GtkCellRendererState flags) GtkCellRenderer* renderer,
GtrDrawable* drawable,
GtkWidget* widget,
GdkRectangle const* area,
GtkCellRendererState flags)
{ {
gtk_cell_renderer_render(renderer, drawable, widget, area, area, flags); gtk_cell_renderer_render(renderer, drawable, widget, area, area, flags);
} }
static void render_compact(TorrentCellRenderer* cell, GtrDrawable* window, GtkWidget* widget, static void render_compact(
GdkRectangle const* background_area, GdkRectangle const* cell_area, GtkCellRendererState flags) TorrentCellRenderer* cell,
GtrDrawable* window,
GtkWidget* widget,
GdkRectangle const* background_area,
GdkRectangle const* cell_area,
GtkCellRendererState flags)
{ {
TR_UNUSED(cell_area); TR_UNUSED(cell_area);
@ -636,8 +702,13 @@ static void render_compact(TorrentCellRenderer* cell, GtrDrawable* window, GtkWi
gtr_cell_renderer_render(p->icon_renderer, window, widget, &icon_area, flags); gtr_cell_renderer_render(p->icon_renderer, window, widget, &icon_area, flags);
g_object_set(p->progress_renderer, "value", (int)(percentDone * 100.0), "text", NULL, "sensitive", sensitive, NULL); g_object_set(p->progress_renderer, "value", (int)(percentDone * 100.0), "text", NULL, "sensitive", sensitive, NULL);
gtr_cell_renderer_render(p->progress_renderer, window, widget, &prog_area, flags); gtr_cell_renderer_render(p->progress_renderer, window, widget, &prog_area, flags);
g_object_set(p->text_renderer, "text", gstr_stat->str, "scale", SMALL_SCALE, "ellipsize", PANGO_ELLIPSIZE_END, g_object_set(
FOREGROUND_COLOR_KEY, &text_color, NULL); p->text_renderer,
TR_ARG_TUPLE("text", gstr_stat->str),
TR_ARG_TUPLE("scale", SMALL_SCALE),
TR_ARG_TUPLE("ellipsize", PANGO_ELLIPSIZE_END),
TR_ARG_TUPLE(FOREGROUND_COLOR_KEY, &text_color),
NULL);
gtr_cell_renderer_render(p->text_renderer, window, widget, &stat_area, flags); gtr_cell_renderer_render(p->text_renderer, window, widget, &stat_area, flags);
g_object_set(p->text_renderer, "text", name, "scale", 1.0, FOREGROUND_COLOR_KEY, &text_color, NULL); g_object_set(p->text_renderer, "text", name, "scale", 1.0, FOREGROUND_COLOR_KEY, &text_color, NULL);
gtr_cell_renderer_render(p->text_renderer, window, widget, &name_area, flags); gtr_cell_renderer_render(p->text_renderer, window, widget, &name_area, flags);
@ -646,8 +717,13 @@ static void render_compact(TorrentCellRenderer* cell, GtrDrawable* window, GtkWi
g_object_unref(icon); g_object_unref(icon);
} }
static void render_full(TorrentCellRenderer* cell, GtrDrawable* window, GtkWidget* widget, GdkRectangle const* background_area, static void render_full(
GdkRectangle const* cell_area, GtkCellRendererState flags) TorrentCellRenderer* cell,
GtrDrawable* window,
GtkWidget* widget,
GdkRectangle const* background_area,
GdkRectangle const* cell_area,
GtkCellRendererState flags)
{ {
TR_UNUSED(cell_area); TR_UNUSED(cell_area);
@ -690,7 +766,12 @@ static void render_full(TorrentCellRenderer* cell, GtrDrawable* window, GtkWidge
gtr_cell_renderer_get_preferred_size(p->icon_renderer, widget, NULL, &size); gtr_cell_renderer_get_preferred_size(p->icon_renderer, widget, NULL, &size);
icon_area.width = size.width; icon_area.width = size.width;
icon_area.height = size.height; icon_area.height = size.height;
g_object_set(p->text_renderer, "text", name, "weight", PANGO_WEIGHT_BOLD, "ellipsize", PANGO_ELLIPSIZE_NONE, "scale", 1.0, g_object_set(
p->text_renderer,
TR_ARG_TUPLE("text", name),
TR_ARG_TUPLE("weight", PANGO_WEIGHT_BOLD),
TR_ARG_TUPLE("ellipsize", PANGO_ELLIPSIZE_NONE),
TR_ARG_TUPLE("scale", 1.0),
NULL); NULL);
gtr_cell_renderer_get_preferred_size(p->text_renderer, widget, NULL, &size); gtr_cell_renderer_get_preferred_size(p->text_renderer, widget, NULL, &size);
name_area.width = size.width; name_area.width = size.width;
@ -745,8 +826,14 @@ static void render_full(TorrentCellRenderer* cell, GtrDrawable* window, GtkWidge
g_object_set(p->icon_renderer, "pixbuf", icon, "sensitive", sensitive, NULL); g_object_set(p->icon_renderer, "pixbuf", icon, "sensitive", sensitive, NULL);
gtr_cell_renderer_render(p->icon_renderer, window, widget, &icon_area, flags); gtr_cell_renderer_render(p->icon_renderer, window, widget, &icon_area, flags);
g_object_set(p->text_renderer, "text", name, "scale", 1.0, FOREGROUND_COLOR_KEY, &text_color, "ellipsize", g_object_set(
PANGO_ELLIPSIZE_END, "weight", PANGO_WEIGHT_BOLD, NULL); p->text_renderer,
TR_ARG_TUPLE("text", name),
TR_ARG_TUPLE("scale", 1.0),
TR_ARG_TUPLE(FOREGROUND_COLOR_KEY, &text_color),
TR_ARG_TUPLE("ellipsize", PANGO_ELLIPSIZE_END),
TR_ARG_TUPLE("weight", PANGO_WEIGHT_BOLD),
NULL);
gtr_cell_renderer_render(p->text_renderer, window, widget, &name_area, flags); gtr_cell_renderer_render(p->text_renderer, window, widget, &name_area, flags);
g_object_set(p->text_renderer, "text", gstr_prog->str, "scale", SMALL_SCALE, "weight", PANGO_WEIGHT_NORMAL, NULL); g_object_set(p->text_renderer, "text", gstr_prog->str, "scale", SMALL_SCALE, "weight", PANGO_WEIGHT_NORMAL, NULL);
gtr_cell_renderer_render(p->text_renderer, window, widget, &prog_area, flags); gtr_cell_renderer_render(p->text_renderer, window, widget, &prog_area, flags);
@ -759,8 +846,12 @@ static void render_full(TorrentCellRenderer* cell, GtrDrawable* window, GtkWidge
g_object_unref(icon); g_object_unref(icon);
} }
static void torrent_cell_renderer_render(GtkCellRenderer* cell, GtrDrawable* window, GtkWidget* widget, static void torrent_cell_renderer_render(
GdkRectangle const* background_area, GdkRectangle const* cell_area, GtkCellRenderer* cell,
GtrDrawable* window,
GtkWidget* widget,
GdkRectangle const* background_area,
GdkRectangle const* cell_area,
GtkCellRendererState flags) GtkCellRendererState flags)
{ {
TorrentCellRenderer* self = TORRENT_CELL_RENDERER(cell); TorrentCellRenderer* self = TORRENT_CELL_RENDERER(cell);
@ -885,19 +976,29 @@ static void torrent_cell_renderer_class_init(TorrentCellRendererClass* klass)
gobject_class->get_property = torrent_cell_renderer_get_property; gobject_class->get_property = torrent_cell_renderer_get_property;
gobject_class->dispose = torrent_cell_renderer_dispose; gobject_class->dispose = torrent_cell_renderer_dispose;
g_object_class_install_property(gobject_class, P_TORRENT, g_object_class_install_property(
gobject_class,
P_TORRENT,
g_param_spec_pointer("torrent", NULL, "tr_torrent*", G_PARAM_READWRITE)); g_param_spec_pointer("torrent", NULL, "tr_torrent*", G_PARAM_READWRITE));
g_object_class_install_property(gobject_class, P_UPLOAD_SPEED, g_object_class_install_property(
gobject_class,
P_UPLOAD_SPEED,
g_param_spec_double("piece-upload-speed", NULL, "tr_stat.pieceUploadSpeed_KBps", 0, INT_MAX, 0, G_PARAM_READWRITE)); g_param_spec_double("piece-upload-speed", NULL, "tr_stat.pieceUploadSpeed_KBps", 0, INT_MAX, 0, G_PARAM_READWRITE));
g_object_class_install_property(gobject_class, P_DOWNLOAD_SPEED, g_object_class_install_property(
gobject_class,
P_DOWNLOAD_SPEED,
g_param_spec_double("piece-download-speed", NULL, "tr_stat.pieceDownloadSpeed_KBps", 0, INT_MAX, 0, G_PARAM_READWRITE)); g_param_spec_double("piece-download-speed", NULL, "tr_stat.pieceDownloadSpeed_KBps", 0, INT_MAX, 0, G_PARAM_READWRITE));
g_object_class_install_property(gobject_class, P_BAR_HEIGHT, g_object_class_install_property(
gobject_class,
P_BAR_HEIGHT,
g_param_spec_int("bar-height", NULL, "Bar Height", 1, INT_MAX, DEFAULT_BAR_HEIGHT, G_PARAM_READWRITE)); g_param_spec_int("bar-height", NULL, "Bar Height", 1, INT_MAX, DEFAULT_BAR_HEIGHT, G_PARAM_READWRITE));
g_object_class_install_property(gobject_class, P_COMPACT, g_object_class_install_property(
gobject_class,
P_COMPACT,
g_param_spec_boolean("compact", NULL, "Compact Mode", FALSE, G_PARAM_READWRITE)); g_param_spec_boolean("compact", NULL, "Compact Mode", FALSE, G_PARAM_READWRITE));
} }

View File

@ -79,8 +79,7 @@ typedef struct TrCorePrivate
GtkTreeModel* sorted_model; GtkTreeModel* sorted_model;
tr_session* session; tr_session* session;
GStringChunk* string_chunk; GStringChunk* string_chunk;
} } TrCorePrivate;
TrCorePrivate;
static int core_is_disposed(TrCore const* core) static int core_is_disposed(TrCore const* core)
{ {
@ -121,23 +120,78 @@ static void tr_core_class_init(TrCoreClass* core_class)
gobject_class->dispose = core_dispose; gobject_class->dispose = core_dispose;
gobject_class->finalize = core_finalize; gobject_class->finalize = core_finalize;
signals[ADD_ERROR_SIGNAL] = g_signal_new("add-error", core_type, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(TrCoreClass, add_error), signals[ADD_ERROR_SIGNAL] = g_signal_new(
NULL, NULL, g_cclosure_marshal_VOID__UINT_POINTER, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_POINTER); "add-error",
core_type,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(TrCoreClass, add_error),
NULL,
NULL,
g_cclosure_marshal_VOID__UINT_POINTER,
G_TYPE_NONE,
2,
G_TYPE_UINT,
G_TYPE_POINTER);
signals[ADD_PROMPT_SIGNAL] = g_signal_new("add-prompt", core_type, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(TrCoreClass, signals[ADD_PROMPT_SIGNAL] = g_signal_new(
add_prompt), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); "add-prompt",
core_type,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(TrCoreClass, add_prompt),
NULL,
NULL,
g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE,
1,
G_TYPE_POINTER);
signals[BUSY_SIGNAL] = g_signal_new("busy", core_type, G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(TrCoreClass, busy), NULL, NULL, signals[BUSY_SIGNAL] = g_signal_new(
g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); "busy",
core_type,
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET(TrCoreClass, busy),
NULL,
NULL,
g_cclosure_marshal_VOID__BOOLEAN,
G_TYPE_NONE,
1,
G_TYPE_BOOLEAN);
signals[BLOCKLIST_SIGNAL] = g_signal_new("blocklist-updated", core_type, G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(TrCoreClass, signals[BLOCKLIST_SIGNAL] = g_signal_new(
blocklist_updated), NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); "blocklist-updated",
core_type,
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET(TrCoreClass, blocklist_updated),
NULL,
NULL,
g_cclosure_marshal_VOID__INT,
G_TYPE_NONE,
1,
G_TYPE_INT);
signals[PORT_SIGNAL] = g_signal_new("port-tested", core_type, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(TrCoreClass, port_tested), signals[PORT_SIGNAL] = g_signal_new(
NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); "port-tested",
core_type,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(TrCoreClass, port_tested),
NULL,
NULL,
g_cclosure_marshal_VOID__BOOLEAN,
G_TYPE_NONE,
1,
G_TYPE_BOOLEAN);
signals[PREFS_SIGNAL] = g_signal_new("prefs-changed", core_type, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(TrCoreClass, signals[PREFS_SIGNAL] = g_signal_new(
prefs_changed), NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); "prefs-changed",
core_type,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(TrCoreClass, prefs_changed),
NULL,
NULL,
g_cclosure_marshal_VOID__INT,
G_TYPE_NONE,
1,
G_TYPE_INT);
} }
static void tr_core_init(TrCore* core) static void tr_core_init(TrCore* core)
@ -147,8 +201,7 @@ static void tr_core_init(TrCore* core)
/* column types for the model used to store torrent information */ /* column types for the model used to store torrent information */
/* keep this in sync with the enum near the bottom of tr_core.h */ /* keep this in sync with the enum near the bottom of tr_core.h */
GType types[] = GType types[] = {
{
G_TYPE_POINTER, /* collated name */ G_TYPE_POINTER, /* collated name */
G_TYPE_POINTER, /* tr_torrent* */ G_TYPE_POINTER, /* tr_torrent* */
G_TYPE_INT, /* torrent id */ G_TYPE_INT, /* torrent id */
@ -801,8 +854,12 @@ static void core_watchdir_monitor_file(TrCore* core, GFile* file)
} }
/* GFileMonitor noticed a file was created */ /* GFileMonitor noticed a file was created */
static void on_file_changed_in_watchdir(GFileMonitor const* monitor, GFile* file, GFile const* other_type, static void on_file_changed_in_watchdir(
GFileMonitorEvent event_type, gpointer core) GFileMonitor const* monitor,
GFile* file,
GFile const* other_type,
GFileMonitorEvent event_type,
gpointer core)
{ {
TR_UNUSED(monitor); TR_UNUSED(monitor);
TR_UNUSED(other_type); TR_UNUSED(other_type);
@ -1009,8 +1066,7 @@ static gboolean find_row_from_torrent_id(GtkTreeModel* model, int id, GtkTreeIte
int row_id; int row_id;
gtk_tree_model_get(model, &iter, MC_TORRENT_ID, &row_id, -1); gtk_tree_model_get(model, &iter, MC_TORRENT_ID, &row_id, -1);
match = id == row_id; match = id == row_id;
} } while (!match && gtk_tree_model_iter_next(model, &iter));
while (!match && gtk_tree_model_iter_next(model, &iter));
} }
if (match) if (match)
@ -1095,21 +1151,24 @@ void gtr_core_add_torrent(TrCore* core, tr_torrent* tor, gboolean do_notify)
unsigned int const trackers_hash = build_torrent_trackers_hash(tor); unsigned int const trackers_hash = build_torrent_trackers_hash(tor);
GtkListStore* store = GTK_LIST_STORE(core_raw_model(core)); GtkListStore* store = GTK_LIST_STORE(core_raw_model(core));
gtk_list_store_insert_with_values(store, &unused, 0, gtk_list_store_insert_with_values(
MC_NAME_COLLATED, collated, store,
MC_TORRENT, tor, &unused,
MC_TORRENT_ID, tr_torrentId(tor), 0,
MC_SPEED_UP, st->pieceUploadSpeed_KBps, TR_ARG_TUPLE(MC_NAME_COLLATED, collated),
MC_SPEED_DOWN, st->pieceDownloadSpeed_KBps, TR_ARG_TUPLE(MC_TORRENT, tor),
MC_ACTIVE_PEERS_UP, st->peersGettingFromUs, TR_ARG_TUPLE(MC_TORRENT_ID, tr_torrentId(tor)),
MC_ACTIVE_PEERS_DOWN, st->peersSendingToUs + st->webseedsSendingToUs, TR_ARG_TUPLE(MC_SPEED_UP, st->pieceUploadSpeed_KBps),
MC_RECHECK_PROGRESS, st->recheckProgress, TR_ARG_TUPLE(MC_SPEED_DOWN, st->pieceDownloadSpeed_KBps),
MC_ACTIVE, is_torrent_active(st), TR_ARG_TUPLE(MC_ACTIVE_PEERS_UP, st->peersGettingFromUs),
MC_ACTIVITY, st->activity, TR_ARG_TUPLE(MC_ACTIVE_PEERS_DOWN, st->peersSendingToUs + st->webseedsSendingToUs),
MC_FINISHED, st->finished, TR_ARG_TUPLE(MC_RECHECK_PROGRESS, st->recheckProgress),
MC_PRIORITY, tr_torrentGetPriority(tor), TR_ARG_TUPLE(MC_ACTIVE, is_torrent_active(st)),
MC_QUEUE_POSITION, st->queuePosition, TR_ARG_TUPLE(MC_ACTIVITY, st->activity),
MC_TRACKERS, trackers_hash, TR_ARG_TUPLE(MC_FINISHED, st->finished),
TR_ARG_TUPLE(MC_PRIORITY, tr_torrentGetPriority(tor)),
TR_ARG_TUPLE(MC_QUEUE_POSITION, st->queuePosition),
TR_ARG_TUPLE(MC_TRACKERS, trackers_hash),
-1); -1);
if (do_notify) if (do_notify)
@ -1324,8 +1383,8 @@ static bool add_file(TrCore* core, GFile* file, gboolean do_start, gboolean do_p
handled = true; handled = true;
core_add_ctor(core, ctor, do_prompt, do_notify); core_add_ctor(core, ctor, do_prompt, do_notify);
} }
else if (g_file_has_uri_scheme(file, "http") || g_file_has_uri_scheme(file, "https") || else if (
g_file_has_uri_scheme(file, "ftp")) g_file_has_uri_scheme(file, "http") || g_file_has_uri_scheme(file, "https") || g_file_has_uri_scheme(file, "ftp"))
{ {
struct add_from_url_data* data; struct add_from_url_data* data;
@ -1501,21 +1560,23 @@ static void update_foreach(GtkTreeModel* model, GtkTreeIter* iter)
tr_torrent* tor; tr_torrent* tor;
/* get the old states */ /* get the old states */
gtk_tree_model_get(model, iter, gtk_tree_model_get(
MC_TORRENT, &tor, model,
MC_ACTIVE, &oldActive, iter,
MC_ACTIVE_PEER_COUNT, &oldActivePeerCount, TR_ARG_TUPLE(MC_TORRENT, &tor),
MC_ACTIVE_PEERS_UP, &oldUploadPeerCount, TR_ARG_TUPLE(MC_ACTIVE, &oldActive),
MC_ACTIVE_PEERS_DOWN, &oldDownloadPeerCount, TR_ARG_TUPLE(MC_ACTIVE_PEER_COUNT, &oldActivePeerCount),
MC_ERROR, &oldError, TR_ARG_TUPLE(MC_ACTIVE_PEERS_UP, &oldUploadPeerCount),
MC_ACTIVITY, &oldActivity, TR_ARG_TUPLE(MC_ACTIVE_PEERS_DOWN, &oldDownloadPeerCount),
MC_FINISHED, &oldFinished, TR_ARG_TUPLE(MC_ERROR, &oldError),
MC_PRIORITY, &oldPriority, TR_ARG_TUPLE(MC_ACTIVITY, &oldActivity),
MC_QUEUE_POSITION, &oldQueuePosition, TR_ARG_TUPLE(MC_FINISHED, &oldFinished),
MC_TRACKERS, &oldTrackers, TR_ARG_TUPLE(MC_PRIORITY, &oldPriority),
MC_SPEED_UP, &oldUpSpeed, TR_ARG_TUPLE(MC_QUEUE_POSITION, &oldQueuePosition),
MC_RECHECK_PROGRESS, &oldRecheckProgress, TR_ARG_TUPLE(MC_TRACKERS, &oldTrackers),
MC_SPEED_DOWN, &oldDownSpeed, TR_ARG_TUPLE(MC_SPEED_UP, &oldUpSpeed),
TR_ARG_TUPLE(MC_RECHECK_PROGRESS, &oldRecheckProgress),
TR_ARG_TUPLE(MC_SPEED_DOWN, &oldDownSpeed),
-1); -1);
/* get the new states */ /* get the new states */
@ -1543,20 +1604,22 @@ static void update_foreach(GtkTreeModel* model, GtkTreeIter* iter)
gtr_compare_double(newDownSpeed, oldDownSpeed, 2) != 0 || gtr_compare_double(newDownSpeed, oldDownSpeed, 2) != 0 ||
gtr_compare_double(newRecheckProgress, oldRecheckProgress, 2) != 0) gtr_compare_double(newRecheckProgress, oldRecheckProgress, 2) != 0)
{ {
gtk_list_store_set(GTK_LIST_STORE(model), iter, gtk_list_store_set(
MC_ACTIVE, newActive, GTK_LIST_STORE(model),
MC_ACTIVE_PEER_COUNT, newActivePeerCount, iter,
MC_ACTIVE_PEERS_UP, newUploadPeerCount, TR_ARG_TUPLE(MC_ACTIVE, newActive),
MC_ACTIVE_PEERS_DOWN, newDownloadPeerCount, TR_ARG_TUPLE(MC_ACTIVE_PEER_COUNT, newActivePeerCount),
MC_ERROR, newError, TR_ARG_TUPLE(MC_ACTIVE_PEERS_UP, newUploadPeerCount),
MC_ACTIVITY, newActivity, TR_ARG_TUPLE(MC_ACTIVE_PEERS_DOWN, newDownloadPeerCount),
MC_FINISHED, newFinished, TR_ARG_TUPLE(MC_ERROR, newError),
MC_PRIORITY, newPriority, TR_ARG_TUPLE(MC_ACTIVITY, newActivity),
MC_QUEUE_POSITION, newQueuePosition, TR_ARG_TUPLE(MC_FINISHED, newFinished),
MC_TRACKERS, newTrackers, TR_ARG_TUPLE(MC_PRIORITY, newPriority),
MC_SPEED_UP, newUpSpeed, TR_ARG_TUPLE(MC_QUEUE_POSITION, newQueuePosition),
MC_SPEED_DOWN, newDownSpeed, TR_ARG_TUPLE(MC_TRACKERS, newTrackers),
MC_RECHECK_PROGRESS, newRecheckProgress, TR_ARG_TUPLE(MC_SPEED_UP, newUpSpeed),
TR_ARG_TUPLE(MC_SPEED_DOWN, newDownSpeed),
TR_ARG_TUPLE(MC_RECHECK_PROGRESS, newRecheckProgress),
-1); -1);
} }
} }
@ -1574,8 +1637,7 @@ void gtr_core_update(TrCore* core)
do do
{ {
update_foreach(model, &iter); update_foreach(model, &iter);
} } while (gtk_tree_model_iter_next(model, &iter));
while (gtk_tree_model_iter_next(model, &iter));
} }
/* update hibernation */ /* update hibernation */
@ -1603,9 +1665,18 @@ static gboolean gtr_inhibit_hibernation(guint* cookie)
connection = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &err); connection = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &err);
response = g_dbus_connection_call_sync(connection, SESSION_MANAGER_SERVICE_NAME, SESSION_MANAGER_OBJECT_PATH, response = g_dbus_connection_call_sync(
SESSION_MANAGER_INTERFACE, "Inhibit", g_variant_new("(susu)", application, toplevel_xid, reason, flags), NULL, connection,
G_DBUS_CALL_FLAGS_NONE, 1000, NULL, &err); SESSION_MANAGER_SERVICE_NAME,
SESSION_MANAGER_OBJECT_PATH,
SESSION_MANAGER_INTERFACE,
"Inhibit",
g_variant_new("(susu)", application, toplevel_xid, reason, flags),
NULL,
G_DBUS_CALL_FLAGS_NONE,
1000,
NULL,
&err);
if (response != NULL) if (response != NULL)
{ {
@ -1647,8 +1718,17 @@ static void gtr_uninhibit_hibernation(guint inhibit_cookie)
connection = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &err); connection = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &err);
response = g_dbus_connection_call_sync(connection, SESSION_MANAGER_SERVICE_NAME, SESSION_MANAGER_OBJECT_PATH, response = g_dbus_connection_call_sync(
SESSION_MANAGER_INTERFACE, "Uninhibit", g_variant_new("(u)", inhibit_cookie), NULL, G_DBUS_CALL_FLAGS_NONE, 1000, NULL, connection,
SESSION_MANAGER_SERVICE_NAME,
SESSION_MANAGER_OBJECT_PATH,
SESSION_MANAGER_INTERFACE,
"Uninhibit",
g_variant_new("(u)", inhibit_cookie),
NULL,
G_DBUS_CALL_FLAGS_NONE,
1000,
NULL,
&err); &err);
/* logging */ /* logging */
@ -1759,7 +1839,7 @@ void gtr_core_set_pref_double(TrCore* self, tr_quark const key, double newval)
static int nextTag = 1; static int nextTag = 1;
typedef void (* server_response_func)(TrCore* core, tr_variant* response, gpointer user_data); typedef void (*server_response_func)(TrCore* core, tr_variant* response, gpointer user_data);
struct pending_request_data struct pending_request_data
{ {
@ -1809,7 +1889,11 @@ static void core_read_rpc_response(tr_session* session, tr_variant* response, vo
gdk_threads_add_idle(core_read_rpc_response_idle, response_copy); gdk_threads_add_idle(core_read_rpc_response_idle, response_copy);
} }
static void core_send_rpc_request(TrCore* core, tr_variant const* request, int tag, server_response_func response_func, static void core_send_rpc_request(
TrCore* core,
tr_variant const* request,
int tag,
server_response_func response_func,
void* response_func_user_data) void* response_func_user_data)
{ {
tr_session* session = gtr_core_session(core); tr_session* session = gtr_core_session(core);
@ -1838,7 +1922,7 @@ static void core_send_rpc_request(TrCore* core, tr_variant const* request, int t
{ {
struct evbuffer* buf = tr_variantToBuf(request, TR_VARIANT_FMT_JSON_LEAN); struct evbuffer* buf = tr_variantToBuf(request, TR_VARIANT_FMT_JSON_LEAN);
size_t const buf_len = evbuffer_get_length(buf); size_t const buf_len = evbuffer_get_length(buf);
g_message("request: [%*.*s]", (int)buf_len, (int)buf_len, evbuffer_pullup(buf, -1)); g_message("request: [%*.*s]", TR_ARG_TUPLE((int)buf_len, (int)buf_len, evbuffer_pullup(buf, -1)));
evbuffer_free(buf); evbuffer_free(buf);
} }
#endif #endif
@ -1956,8 +2040,7 @@ size_t gtr_core_get_active_torrent_count(TrCore* core)
{ {
++activeCount; ++activeCount;
} }
} } while (gtk_tree_model_iter_next(model, &iter));
while (gtk_tree_model_iter_next(model, &iter));
} }
return activeCount; return activeCount;

View File

@ -40,8 +40,7 @@ typedef struct _TrCore
/*< private >*/ /*< private >*/
struct TrCorePrivate* priv; struct TrCorePrivate* priv;
} } TrCore;
TrCore;
enum tr_core_err enum tr_core_err
{ {
@ -54,15 +53,14 @@ typedef struct _TrCoreClass
{ {
GObjectClass parent_class; GObjectClass parent_class;
void (* add_error)(TrCore*, enum tr_core_err, char const* name); void (*add_error)(TrCore*, enum tr_core_err, char const* name);
void (* add_prompt)(TrCore*, gpointer ctor); void (*add_prompt)(TrCore*, gpointer ctor);
void (* blocklist_updated)(TrCore*, int ruleCount); void (*blocklist_updated)(TrCore*, int ruleCount);
void (* busy)(TrCore*, gboolean is_busy); void (*busy)(TrCore*, gboolean is_busy);
void (* prefs_changed)(TrCore*, tr_quark const key); void (*prefs_changed)(TrCore*, tr_quark const key);
void (* port_tested)(TrCore*, gboolean is_open); void (*port_tested)(TrCore*, gboolean is_open);
void (* quit)(TrCore*); void (*quit)(TrCore*);
} } TrCoreClass;
TrCoreClass;
GType tr_core_get_type(void) G_GNUC_CONST; GType tr_core_get_type(void) G_GNUC_CONST;

View File

@ -463,8 +463,13 @@ static void onBlocklistUpdate(GtkButton* w, gpointer gdata)
{ {
GtkWidget* d; GtkWidget* d;
struct blocklist_data* data = gdata; struct blocklist_data* data = gdata;
d = gtk_message_dialog_new(GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(w))), GTK_DIALOG_DESTROY_WITH_PARENT, d = gtk_message_dialog_new(
GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, "%s", _("Update Blocklist")); GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(w))),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_CLOSE,
"%s",
_("Update Blocklist"));
gtk_widget_set_sensitive(data->updateBlocklistButton, FALSE); gtk_widget_set_sensitive(data->updateBlocklistButton, FALSE);
gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(d), "%s", _("Getting new blocklist…")); gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(d), "%s", _("Getting new blocklist…"));
data->updateBlocklistDialog = d; data->updateBlocklistDialog = d;
@ -491,8 +496,11 @@ static void onIntComboChanged(GtkComboBox* combo_box, gpointer core)
static GtkWidget* new_encryption_combo(GObject* core, tr_quark const key) static GtkWidget* new_encryption_combo(GObject* core, tr_quark const key)
{ {
GtkWidget* w = gtr_combo_box_new_enum(_("Allow encryption"), TR_CLEAR_PREFERRED, _("Prefer encryption"), GtkWidget* w = gtr_combo_box_new_enum(
TR_ENCRYPTION_PREFERRED, _("Require encryption"), TR_ENCRYPTION_REQUIRED, NULL); TR_ARG_TUPLE(_("Allow encryption"), TR_CLEAR_PREFERRED),
TR_ARG_TUPLE(_("Prefer encryption"), TR_ENCRYPTION_PREFERRED),
TR_ARG_TUPLE(_("Require encryption"), TR_ENCRYPTION_REQUIRED),
NULL);
gtr_combo_box_set_active_enum(GTK_COMBO_BOX(w), gtr_pref_int_get(key)); gtr_combo_box_set_active_enum(GTK_COMBO_BOX(w), gtr_pref_int_get(key));
g_object_set_data(G_OBJECT(w), PREF_KEY, GINT_TO_POINTER(key)); g_object_set_data(G_OBJECT(w), PREF_KEY, GINT_TO_POINTER(key));
g_signal_connect(w, "changed", G_CALLBACK(onIntComboChanged), core); g_signal_connect(w, "changed", G_CALLBACK(onIntComboChanged), core);
@ -572,9 +580,7 @@ enum
static GtkTreeModel* whitelist_tree_model_new(char const* whitelist) static GtkTreeModel* whitelist_tree_model_new(char const* whitelist)
{ {
char** rules; char** rules;
GtkListStore* store = gtk_list_store_new(N_COLS, GtkListStore* store = gtk_list_store_new(N_COLS, G_TYPE_STRING, G_TYPE_STRING);
G_TYPE_STRING,
G_TYPE_STRING);
rules = g_strsplit(whitelist, ",", 0); rules = g_strsplit(whitelist, ",", 0);
@ -625,8 +631,7 @@ static void refreshWhitelist(struct remote_page* page)
g_string_append(gstr, address); g_string_append(gstr, address);
g_string_append(gstr, ","); g_string_append(gstr, ",");
g_free(address); g_free(address);
} } while (gtk_tree_model_iter_next(model, &iter));
while (gtk_tree_model_iter_next(model, &iter));
} }
g_string_truncate(gstr, gstr->len - 1); /* remove the trailing comma */ g_string_truncate(gstr, gstr->len - 1); /* remove the trailing comma */
@ -832,8 +837,7 @@ static GtkWidget* remotePage(GObject* core)
v = page->view = GTK_TREE_VIEW(w); v = page->view = GTK_TREE_VIEW(w);
gtk_widget_set_tooltip_text(w, _("IP addresses may use wildcards, such as 192.168.*.*")); gtk_widget_set_tooltip_text(w, _("IP addresses may use wildcards, such as 192.168.*.*"));
sel = gtk_tree_view_get_selection(v); sel = gtk_tree_view_get_selection(v);
g_signal_connect(sel, "changed", g_signal_connect(sel, "changed", G_CALLBACK(onWhitelistSelectionChanged), page);
G_CALLBACK(onWhitelistSelectionChanged), page);
g_object_unref(G_OBJECT(m)); g_object_unref(G_OBJECT(m));
gtk_tree_view_set_headers_visible(v, TRUE); gtk_tree_view_set_headers_visible(v, TRUE);
w = gtk_frame_new(NULL); w = gtk_frame_new(NULL);
@ -851,7 +855,12 @@ static GtkWidget* remotePage(GObject* core)
s = _("Addresses:"); s = _("Addresses:");
w = hig_workarea_add_row(t, &row, s, w, NULL); w = hig_workarea_add_row(t, &row, s, w, NULL);
g_object_set(w, "halign", GTK_ALIGN_START, "valign", GTK_ALIGN_START, "margin-top", GUI_PAD, "margin-bottom", GUI_PAD, g_object_set(
w,
TR_ARG_TUPLE("halign", GTK_ALIGN_START),
TR_ARG_TUPLE("valign", GTK_ALIGN_START),
TR_ARG_TUPLE("margin-top", GUI_PAD),
TR_ARG_TUPLE("margin-bottom", GUI_PAD),
NULL); NULL);
page->whitelist_widgets = g_slist_prepend(page->whitelist_widgets, w); page->whitelist_widgets = g_slist_prepend(page->whitelist_widgets, w);
@ -951,16 +960,16 @@ static GtkWidget* new_time_combo(GObject* core, tr_quark const key)
static GtkWidget* new_week_combo(GObject* core, tr_quark const key) static GtkWidget* new_week_combo(GObject* core, tr_quark const key)
{ {
GtkWidget* w = gtr_combo_box_new_enum( GtkWidget* w = gtr_combo_box_new_enum(
_("Every Day"), TR_SCHED_ALL, TR_ARG_TUPLE(_("Every Day"), TR_SCHED_ALL),
_("Weekdays"), TR_SCHED_WEEKDAY, TR_ARG_TUPLE(_("Weekdays"), TR_SCHED_WEEKDAY),
_("Weekends"), TR_SCHED_WEEKEND, TR_ARG_TUPLE(_("Weekends"), TR_SCHED_WEEKEND),
_("Sunday"), TR_SCHED_SUN, TR_ARG_TUPLE(_("Sunday"), TR_SCHED_SUN),
_("Monday"), TR_SCHED_MON, TR_ARG_TUPLE(_("Monday"), TR_SCHED_MON),
_("Tuesday"), TR_SCHED_TUES, TR_ARG_TUPLE(_("Tuesday"), TR_SCHED_TUES),
_("Wednesday"), TR_SCHED_WED, TR_ARG_TUPLE(_("Wednesday"), TR_SCHED_WED),
_("Thursday"), TR_SCHED_THURS, TR_ARG_TUPLE(_("Thursday"), TR_SCHED_THURS),
_("Friday"), TR_SCHED_FRI, TR_ARG_TUPLE(_("Friday"), TR_SCHED_FRI),
_("Saturday"), TR_SCHED_SAT, TR_ARG_TUPLE(_("Saturday"), TR_SCHED_SAT),
NULL); NULL);
gtr_combo_box_set_active_enum(GTK_COMBO_BOX(w), gtr_pref_int_get(key)); gtr_combo_box_set_active_enum(GTK_COMBO_BOX(w), gtr_pref_int_get(key));
g_object_set_data(G_OBJECT(w), PREF_KEY, GINT_TO_POINTER(key)); g_object_set_data(G_OBJECT(w), PREF_KEY, GINT_TO_POINTER(key));
@ -1266,9 +1275,12 @@ GtkWidget* gtr_prefs_dialog_new(GtkWindow* parent, GObject* core)
data->core = TR_CORE(core); data->core = TR_CORE(core);
data->core_prefs_tag = g_signal_connect(TR_CORE(core), "prefs-changed", G_CALLBACK(on_core_prefs_changed), data); data->core_prefs_tag = g_signal_connect(TR_CORE(core), "prefs-changed", G_CALLBACK(on_core_prefs_changed), data);
d = gtk_dialog_new_with_buttons(_("Transmission Preferences"), parent, GTK_DIALOG_DESTROY_WITH_PARENT, d = gtk_dialog_new_with_buttons(
_("_Help"), GTK_RESPONSE_HELP, _("Transmission Preferences"),
_("_Close"), GTK_RESPONSE_CLOSE, parent,
GTK_DIALOG_DESTROY_WITH_PARENT,
TR_ARG_TUPLE(_("_Help"), GTK_RESPONSE_HELP),
TR_ARG_TUPLE(_("_Close"), GTK_RESPONSE_CLOSE),
NULL); NULL);
g_object_weak_ref(G_OBJECT(d), on_prefs_dialog_destroyed, data); g_object_weak_ref(G_OBJECT(d), on_prefs_dialog_destroyed, data);
gtk_window_set_role(GTK_WINDOW(d), "transmission-preferences-dialog"); gtk_window_set_role(GTK_WINDOW(d), "transmission-preferences-dialog");

View File

@ -61,12 +61,11 @@ typedef struct
GtkTreeModel* filter_model; GtkTreeModel* filter_model;
TrCore* core; TrCore* core;
gulong pref_handler_id; gulong pref_handler_id;
} } PrivateData;
PrivateData;
static TR_DEFINE_QUARK(private_data, private_data) static TR_DEFINE_QUARK(private_data, private_data)
static PrivateData* get_private_data(GtkWindow * w) static PrivateData* get_private_data(GtkWindow* w)
{ {
return g_object_get_qdata(G_OBJECT(w), private_data_quark()); return g_object_get_qdata(G_OBJECT(w), private_data_quark());
} }
@ -98,7 +97,11 @@ static void view_row_activated(GtkTreeView* tree_view, GtkTreePath* path, GtkTre
gtr_action_activate("show-torrent-properties"); gtr_action_activate("show-torrent-properties");
} }
static gboolean tree_view_search_equal_func(GtkTreeModel* model, gint column, gchar const* key, GtkTreeIter* iter, static gboolean tree_view_search_equal_func(
GtkTreeModel* model,
gint column,
gchar const* key,
GtkTreeIter* iter,
gpointer search_data) gpointer search_data)
{ {
TR_UNUSED(column); TR_UNUSED(column);
@ -133,8 +136,12 @@ static GtkWidget* makeview(PrivateData* p)
p->selection = gtk_tree_view_get_selection(tree_view); p->selection = gtk_tree_view_get_selection(tree_view);
p->column = col = GTK_TREE_VIEW_COLUMN(g_object_new(GTK_TYPE_TREE_VIEW_COLUMN, "title", _("Torrent"), "resizable", TRUE, p->column = col = GTK_TREE_VIEW_COLUMN(g_object_new(
"sizing", GTK_TREE_VIEW_COLUMN_FIXED, NULL)); GTK_TYPE_TREE_VIEW_COLUMN,
TR_ARG_TUPLE("title", _("Torrent")),
TR_ARG_TUPLE("resizable", TRUE),
TR_ARG_TUPLE("sizing", GTK_TREE_VIEW_COLUMN_FIXED),
NULL));
p->renderer = r = torrent_cell_renderer_new(); p->renderer = r = torrent_cell_renderer_new();
gtk_tree_view_column_pack_start(col, r, FALSE); gtk_tree_view_column_pack_start(col, r, FALSE);
@ -234,13 +241,11 @@ static struct
{ {
char const* val; char const* val;
char const* i18n; char const* i18n;
} } stats_modes[] = {
stats_modes[] =
{
{ "total-ratio", N_("Total Ratio") }, { "total-ratio", N_("Total Ratio") },
{ "session-ratio", N_("Session Ratio") }, { "session-ratio", N_("Session Ratio") },
{ "total-transfer", N_("Total Transfer") }, { "total-transfer", N_("Total Transfer") },
{ "session-transfer", N_("Session Transfer") } { "session-transfer", N_("Session Transfer") },
}; };
static void status_menu_toggled_cb(GtkCheckMenuItem* menu_item, gpointer vprivate) static void status_menu_toggled_cb(GtkCheckMenuItem* menu_item, gpointer vprivate)
@ -264,9 +269,8 @@ static void syncAltSpeedButton(PrivateData* p)
char d[32]; char d[32];
tr_formatter_speed_KBps(d, gtr_pref_int_get(TR_KEY_alt_speed_down), sizeof(d)); tr_formatter_speed_KBps(d, gtr_pref_int_get(TR_KEY_alt_speed_down), sizeof(d));
char* const str = b ? char* const str = b ? g_strdup_printf(_("Click to disable Alternative Speed Limits\n (%1$s down, %2$s up)"), d, u) :
g_strdup_printf(_("Click to disable Alternative Speed Limits\n (%1$s down, %2$s up)"), d, u) : g_strdup_printf(_("Click to enable Alternative Speed Limits\n (%1$s down, %2$s up)"), d, u);
g_strdup_printf(_("Click to enable Alternative Speed Limits\n (%1$s down, %2$s up)"), d, u);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), b); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), b);
gtk_image_set_from_stock(GTK_IMAGE(p->alt_speed_image), stock, -1); gtk_image_set_from_stock(GTK_IMAGE(p->alt_speed_image), stock, -1);
@ -300,7 +304,12 @@ static void findMaxAnnounceTime(GtkTreeModel* model, GtkTreePath* path, GtkTreeI
*maxTime = MAX(*maxTime, torStat->manualAnnounceTime); *maxTime = MAX(*maxTime, torStat->manualAnnounceTime);
} }
static gboolean onAskTrackerQueryTooltip(GtkWidget* widget, gint x, gint y, gboolean keyboard_tip, GtkTooltip* tooltip, static gboolean onAskTrackerQueryTooltip(
GtkWidget* widget,
gint x,
gint y,
gboolean keyboard_tip,
GtkTooltip* tooltip,
gpointer gdata) gpointer gdata)
{ {
TR_UNUSED(widget); TR_UNUSED(widget);
@ -560,7 +569,11 @@ static void onOptionsClicked(GtkButton* button, gpointer vp)
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(b ? p->ratio_on_item : p->ratio_off_item), TRUE); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(b ? p->ratio_on_item : p->ratio_off_item), TRUE);
#if GTK_CHECK_VERSION(3, 22, 0) #if GTK_CHECK_VERSION(3, 22, 0)
gtk_menu_popup_at_widget(GTK_MENU(p->options_menu), GTK_WIDGET(button), GDK_GRAVITY_NORTH_WEST, GDK_GRAVITY_SOUTH_WEST, gtk_menu_popup_at_widget(
GTK_MENU(p->options_menu),
GTK_WIDGET(button),
GDK_GRAVITY_NORTH_WEST,
GDK_GRAVITY_SOUTH_WEST,
NULL); NULL);
#else #else
gtk_menu_popup(GTK_MENU(p->options_menu), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time()); gtk_menu_popup(GTK_MENU(p->options_menu), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time());
@ -615,7 +628,9 @@ GtkWidget* gtr_window_new(GtkApplication* app, GtkUIManager* ui_mgr, TrCore* cor
style = ".tr-workarea.frame {border-left-width: 0; border-right-width: 0; border-radius: 0;}"; style = ".tr-workarea.frame {border-left-width: 0; border-right-width: 0; border-radius: 0;}";
css_provider = gtk_css_provider_new(); css_provider = gtk_css_provider_new();
gtk_css_provider_load_from_data(css_provider, style, strlen(style), NULL); gtk_css_provider_load_from_data(css_provider, style, strlen(style), NULL);
gtk_style_context_add_provider_for_screen(gdk_screen_get_default(), GTK_STYLE_PROVIDER(css_provider), gtk_style_context_add_provider_for_screen(
gdk_screen_get_default(),
GTK_STYLE_PROVIDER(css_provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
/* window's main container */ /* window's main container */
@ -835,18 +850,19 @@ static void updateSpeeds(PrivateData* p)
int dc; int dc;
double us; double us;
double ds; double ds;
gtk_tree_model_get(model, &iter, gtk_tree_model_get(
MC_SPEED_UP, &us, model,
MC_SPEED_DOWN, &ds, &iter,
MC_ACTIVE_PEERS_UP, &uc, TR_ARG_TUPLE(MC_SPEED_UP, &us),
MC_ACTIVE_PEERS_DOWN, &dc, TR_ARG_TUPLE(MC_SPEED_DOWN, &ds),
TR_ARG_TUPLE(MC_ACTIVE_PEERS_UP, &uc),
TR_ARG_TUPLE(MC_ACTIVE_PEERS_DOWN, &dc),
-1); -1);
upSpeed += us; upSpeed += us;
upCount += uc; upCount += uc;
downSpeed += ds; downSpeed += ds;
downCount += dc; downCount += dc;
} } while (gtk_tree_model_iter_next(model, &iter));
while (gtk_tree_model_iter_next(model, &iter));
} }
tr_formatter_speed_KBps(speed_str, downSpeed, sizeof(speed_str)); tr_formatter_speed_KBps(speed_str, downSpeed, sizeof(speed_str));

View File

@ -202,8 +202,8 @@ void gtr_get_host_from_url(char* buf, size_t buflen, char const* url)
static gboolean gtr_is_supported_url(char const* str) static gboolean gtr_is_supported_url(char const* str)
{ {
return str != NULL && (g_str_has_prefix(str, "ftp://") || g_str_has_prefix(str, "http://") || return str != NULL &&
g_str_has_prefix(str, "https://")); (g_str_has_prefix(str, "ftp://") || g_str_has_prefix(str, "http://") || g_str_has_prefix(str, "https://"));
} }
gboolean gtr_is_magnet_link(char const* str) gboolean gtr_is_magnet_link(char const* str)
@ -256,7 +256,9 @@ void gtr_add_torrent_error_dialog(GtkWidget* child, int err, tr_torrent* duplica
} }
else if (err == TR_PARSE_DUPLICATE) else if (err == TR_PARSE_DUPLICATE)
{ {
secondary = g_strdup_printf(_("The torrent file \"%s\" is already in use by \"%s.\""), filename, secondary = g_strdup_printf(
_("The torrent file \"%s\" is already in use by \"%s.\""),
filename,
tr_torrentName(duplicate_torrent)); tr_torrentName(duplicate_torrent));
} }
else else
@ -264,7 +266,12 @@ void gtr_add_torrent_error_dialog(GtkWidget* child, int err, tr_torrent* duplica
secondary = g_strdup_printf(_("The torrent file \"%s\" encountered an unknown error."), filename); secondary = g_strdup_printf(_("The torrent file \"%s\" encountered an unknown error."), filename);
} }
w = gtk_message_dialog_new(win, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", w = gtk_message_dialog_new(
win,
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
"%s",
_("Error opening torrent")); _("Error opening torrent"));
gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(w), "%s", secondary); gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(w), "%s", secondary);
g_signal_connect_swapped(w, "response", G_CALLBACK(gtk_widget_destroy), w); g_signal_connect_swapped(w, "response", G_CALLBACK(gtk_widget_destroy), w);
@ -272,7 +279,7 @@ void gtr_add_torrent_error_dialog(GtkWidget* child, int err, tr_torrent* duplica
g_free(secondary); g_free(secondary);
} }
typedef void (* PopupFunc)(GtkWidget*, GdkEventButton*); typedef void (*PopupFunc)(GtkWidget*, GdkEventButton*);
/* pop up the context menu if a user right-clicks. /* pop up the context menu if a user right-clicks.
if the row they right-click on isn't selected, select it. */ if the row they right-click on isn't selected, select it. */
@ -373,8 +380,7 @@ char const* gtr_get_help_uri(void)
if (uri == NULL) if (uri == NULL)
{ {
uri = g_strdup_printf("https://transmissionbt.com/help/gtk/%d.%dx", uri = g_strdup_printf("https://transmissionbt.com/help/gtk/%d.%dx", MAJOR_VERSION, MINOR_VERSION / 10);
MAJOR_VERSION, MINOR_VERSION / 10);
} }
return uri; return uri;
@ -484,8 +490,7 @@ GtkWidget* gtr_combo_box_new_enum(char const* text_1, ...)
int const val = va_arg(vl, int); int const val = va_arg(vl, int);
gtk_list_store_insert_with_values(store, NULL, INT_MAX, 0, val, 1, text, -1); gtk_list_store_insert_with_values(store, NULL, INT_MAX, 0, val, 1, text, -1);
text = va_arg(vl, char const*); text = va_arg(vl, char const*);
} } while (text != NULL);
while (text != NULL);
va_end(vl); va_end(vl);
} }
@ -516,9 +521,9 @@ int gtr_combo_box_get_active_enum(GtkComboBox* combo_box)
GtkWidget* gtr_priority_combo_new(void) GtkWidget* gtr_priority_combo_new(void)
{ {
return gtr_combo_box_new_enum( return gtr_combo_box_new_enum(
_("High"), TR_PRI_HIGH, TR_ARG_TUPLE(_("High"), TR_PRI_HIGH),
_("Normal"), TR_PRI_NORMAL, TR_ARG_TUPLE(_("Normal"), TR_PRI_NORMAL),
_("Low"), TR_PRI_LOW, TR_ARG_TUPLE(_("Low"), TR_PRI_LOW),
NULL); NULL);
} }
@ -597,8 +602,11 @@ void gtr_unrecognized_url_dialog(GtkWidget* parent, char const* url)
if (gtr_is_magnet_link(url) && strstr(url, xt) == NULL) if (gtr_is_magnet_link(url) && strstr(url, xt) == NULL)
{ {
g_string_append_printf(gstr, "\n \n"); g_string_append_printf(gstr, "\n \n");
g_string_append_printf(gstr, _("This magnet link appears to be intended for something other than BitTorrent. " g_string_append_printf(
"BitTorrent magnet links have a section containing \"%s\"."), xt); gstr,
_("This magnet link appears to be intended for something other than BitTorrent. "
"BitTorrent magnet links have a section containing \"%s\"."),
xt);
} }
gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(w), "%s", gstr->str); gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(w), "%s", gstr->str);
@ -613,10 +621,9 @@ void gtr_unrecognized_url_dialog(GtkWidget* parent, char const* url)
void gtr_paste_clipboard_url_into_entry(GtkWidget* e) void gtr_paste_clipboard_url_into_entry(GtkWidget* e)
{ {
char* text[] = char* text[] = {
{
g_strstrip(gtk_clipboard_wait_for_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY))), g_strstrip(gtk_clipboard_wait_for_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY))),
g_strstrip(gtk_clipboard_wait_for_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD))) g_strstrip(gtk_clipboard_wait_for_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD))),
}; };
for (size_t i = 0; i < G_N_ELEMENTS(text); ++i) for (size_t i = 0; i < G_N_ELEMENTS(text); ++i)

View File

@ -13,6 +13,7 @@
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include <libtransmission/transmission.h> #include <libtransmission/transmission.h>
#include <libtransmission/tr-macros.h>
extern int const mem_K; extern int const mem_K;
extern char const* mem_K_str; extern char const* mem_K_str;
@ -39,15 +40,15 @@ extern char const* speed_T_str;
#else #else
#define TR_DEFINE_QUARK(QN, q_n) \ #define TR_DEFINE_QUARK(QN, q_n) \
GQuark q_n ## _quark(void) \ GQuark q_n##_quark(void) \
{ \ { \
static GQuark q; \ static GQuark q; \
\ \
if (G_UNLIKELY(q == 0)) \ if (G_UNLIKELY(q == 0)) \
{ \ { \
q = g_quark_from_static_string(#QN); \ q = g_quark_from_static_string(#QN); \
} \ } \
\ \
return q; \ return q; \
} }

View File

@ -46,8 +46,7 @@ typedef struct
/* how many hashes to use in the info_hash field */ /* how many hashes to use in the info_hash field */
int info_hash_count; int info_hash_count;
} } tr_scrape_request;
tr_scrape_request;
struct tr_scrape_response_row struct tr_scrape_response_row
{ {
@ -92,15 +91,20 @@ typedef struct
/* minimum interval (in seconds) allowed between scrapes. /* minimum interval (in seconds) allowed between scrapes.
* this is an unofficial extension that some trackers won't support. */ * this is an unofficial extension that some trackers won't support. */
int min_request_interval; int min_request_interval;
} } tr_scrape_response;
tr_scrape_response;
typedef void (* tr_scrape_response_func)(tr_scrape_response const* response, void* user_data); typedef void (*tr_scrape_response_func)(tr_scrape_response const* response, void* user_data);
void tr_tracker_http_scrape(tr_session* session, tr_scrape_request const* req, tr_scrape_response_func response_func, void tr_tracker_http_scrape(
tr_session* session,
tr_scrape_request const* req,
tr_scrape_response_func response_func,
void* user_data); void* user_data);
void tr_tracker_udp_scrape(tr_session* session, tr_scrape_request const* req, tr_scrape_response_func response_func, void tr_tracker_udp_scrape(
tr_session* session,
tr_scrape_request const* req,
tr_scrape_response_func response_func,
void* user_data); void* user_data);
/*** /***
@ -113,8 +117,7 @@ typedef enum
TR_ANNOUNCE_EVENT_COMPLETED, TR_ANNOUNCE_EVENT_COMPLETED,
TR_ANNOUNCE_EVENT_STARTED, TR_ANNOUNCE_EVENT_STARTED,
TR_ANNOUNCE_EVENT_STOPPED TR_ANNOUNCE_EVENT_STOPPED
} } tr_announce_event;
tr_announce_event;
char const* tr_announce_event_get_string(tr_announce_event); char const* tr_announce_event_get_string(tr_announce_event);
@ -160,8 +163,7 @@ typedef struct
/* the name to use when deep logging is enabled */ /* the name to use when deep logging is enabled */
char log_name[128]; char log_name[128];
} } tr_announce_request;
tr_announce_request;
struct tr_pex; struct tr_pex;
@ -214,15 +216,20 @@ typedef struct
/* key generated by and returned from an http tracker. /* key generated by and returned from an http tracker.
* if this is provided, subsequent http announces must include this. */ * if this is provided, subsequent http announces must include this. */
char* tracker_id_str; char* tracker_id_str;
} } tr_announce_response;
tr_announce_response;
typedef void (* tr_announce_response_func)(tr_announce_response const* response, void* userdata); typedef void (*tr_announce_response_func)(tr_announce_response const* response, void* userdata);
void tr_tracker_http_announce(tr_session* session, tr_announce_request const* req, tr_announce_response_func response_func, void tr_tracker_http_announce(
tr_session* session,
tr_announce_request const* req,
tr_announce_response_func response_func,
void* user_data); void* user_data);
void tr_tracker_udp_announce(tr_session* session, tr_announce_request const* req, tr_announce_response_func response_func, void tr_tracker_udp_announce(
tr_session* session,
tr_announce_request const* req,
tr_announce_response_func response_func,
void* user_data); void* user_data);
void tr_tracker_udp_start_shutdown(tr_session* session); void tr_tracker_udp_start_shutdown(tr_session* session);

View File

@ -36,9 +36,7 @@
static char const* get_event_string(tr_announce_request const* req) static char const* get_event_string(tr_announce_request const* req)
{ {
return req->partial_seed && (req->event != TR_ANNOUNCE_EVENT_STOPPED) ? return req->partial_seed && (req->event != TR_ANNOUNCE_EVENT_STOPPED) ? "paused" : tr_announce_event_get_string(req->event);
"paused" :
tr_announce_event_get_string(req->event);
} }
static char* announce_url_new(tr_session const* session, tr_announce_request const* req) static char* announce_url_new(tr_session const* session, tr_announce_request const* req)
@ -52,14 +50,15 @@ static char* announce_url_new(tr_session const* session, tr_announce_request con
evbuffer_expand(buf, 1024); evbuffer_expand(buf, 1024);
evbuffer_add_printf(buf, evbuffer_add_printf(
buf,
"%s" "%s"
"%c" "%c"
"info_hash=%s" "info_hash=%s"
"&peer_id=%*.*s" "&peer_id=%*.*s"
"&port=%d" "&port=%d"
"&uploaded=%" PRIu64 "&uploaded=%" PRIu64 //
"&downloaded=%" PRIu64 "&downloaded=%" PRIu64 //
"&left=%" PRIu64 "&left=%" PRIu64
"&numwant=%d" "&numwant=%d"
"&key=%x" "&key=%x"
@ -68,7 +67,7 @@ static char* announce_url_new(tr_session const* session, tr_announce_request con
req->url, req->url,
strchr(req->url, '?') != NULL ? '&' : '?', strchr(req->url, '?') != NULL ? '&' : '?',
escaped_info_hash, escaped_info_hash,
PEER_ID_LEN, PEER_ID_LEN, req->peer_id, TR_ARG_TUPLE(PEER_ID_LEN, PEER_ID_LEN, req->peer_id),
req->port, req->port,
req->up, req->up,
req->down, req->down,
@ -199,8 +198,14 @@ static void on_announce_done_eventthread(void* vdata)
tr_free(data); tr_free(data);
} }
static void on_announce_done(tr_session* session, bool did_connect, bool did_timeout, long response_code, void const* msg, static void on_announce_done(
size_t msglen, void* vdata) tr_session* session,
bool did_connect,
bool did_timeout,
long response_code,
void const* msg,
size_t msglen,
void* vdata)
{ {
tr_announce_response* response; tr_announce_response* response;
struct announce_data* data = vdata; struct announce_data* data = vdata;
@ -318,7 +323,10 @@ static void on_announce_done(tr_session* session, bool did_connect, bool did_tim
tr_runInEventThread(session, on_announce_done_eventthread, data); tr_runInEventThread(session, on_announce_done_eventthread, data);
} }
void tr_tracker_http_announce(tr_session* session, tr_announce_request const* request, tr_announce_response_func response_func, void tr_tracker_http_announce(
tr_session* session,
tr_announce_request const* request,
tr_announce_response_func response_func,
void* response_func_user_data) void* response_func_user_data)
{ {
struct announce_data* d; struct announce_data* d;
@ -367,8 +375,14 @@ static void on_scrape_done_eventthread(void* vdata)
tr_free(data); tr_free(data);
} }
static void on_scrape_done(tr_session* session, bool did_connect, bool did_timeout, long response_code, void const* msg, static void on_scrape_done(
size_t msglen, void* vdata) tr_session* session,
bool did_connect,
bool did_timeout,
long response_code,
void const* msg,
size_t msglen,
void* vdata)
{ {
tr_scrape_response* response; tr_scrape_response* response;
struct scrape_data* data = vdata; struct scrape_data* data = vdata;
@ -423,8 +437,8 @@ static void on_scrape_done(tr_session* session, bool did_connect, bool did_timeo
response->errmsg = tr_strndup(str, len); response->errmsg = tr_strndup(str, len);
} }
if (tr_variantDictFindDict(&top, TR_KEY_flags, if (tr_variantDictFindDict(&top, TR_KEY_flags, &flags) &&
&flags) && tr_variantDictFindInt(flags, TR_KEY_min_request_interval, &intVal)) tr_variantDictFindInt(flags, TR_KEY_min_request_interval, &intVal))
{ {
response->min_request_interval = intVal; response->min_request_interval = intVal;
} }
@ -495,7 +509,10 @@ static char* scrape_url_new(tr_scrape_request const* req)
return evbuffer_free_to_str(buf, NULL); return evbuffer_free_to_str(buf, NULL);
} }
void tr_tracker_http_scrape(tr_session* session, tr_scrape_request const* request, tr_scrape_response_func response_func, void tr_tracker_http_scrape(
tr_session* session,
tr_scrape_request const* request,
tr_scrape_response_func response_func,
void* response_func_user_data) void* response_func_user_data)
{ {
struct scrape_data* d; struct scrape_data* d;

View File

@ -117,8 +117,7 @@ typedef enum
TAU_ACTION_ANNOUNCE = 1, TAU_ACTION_ANNOUNCE = 1,
TAU_ACTION_SCRAPE = 2, TAU_ACTION_SCRAPE = 2,
TAU_ACTION_ERROR = 3 TAU_ACTION_ERROR = 3
} } tau_action_t;
tau_action_t;
static bool is_tau_response_message(tau_action_t action, size_t msglen) static bool is_tau_response_message(tau_action_t action, size_t msglen)
{ {
@ -170,7 +169,9 @@ struct tau_scrape_request
void* user_data; void* user_data;
}; };
static struct tau_scrape_request* tau_scrape_request_new(tr_scrape_request const* in, tr_scrape_response_func callback, static struct tau_scrape_request* tau_scrape_request_new(
tr_scrape_request const* in,
tr_scrape_response_func callback,
void* user_data) void* user_data)
{ {
struct evbuffer* buf; struct evbuffer* buf;
@ -305,8 +306,7 @@ typedef enum
TAU_ANNOUNCE_EVENT_COMPLETED = 1, TAU_ANNOUNCE_EVENT_COMPLETED = 1,
TAU_ANNOUNCE_EVENT_STARTED = 2, TAU_ANNOUNCE_EVENT_STARTED = 2,
TAU_ANNOUNCE_EVENT_STOPPED = 3 TAU_ANNOUNCE_EVENT_STOPPED = 3
} } tau_announce_event;
tau_announce_event;
static tau_announce_event get_tau_announce_event(tr_announce_event e) static tau_announce_event get_tau_announce_event(tr_announce_event e)
{ {
@ -326,7 +326,9 @@ static tau_announce_event get_tau_announce_event(tr_announce_event e)
} }
} }
static struct tau_announce_request* tau_announce_request_new(tr_announce_request const* in, tr_announce_response_func callback, static struct tau_announce_request* tau_announce_request_new(
tr_announce_request const* in,
tr_announce_response_func callback,
void* user_data) void* user_data)
{ {
struct evbuffer* buf; struct evbuffer* buf;
@ -384,7 +386,10 @@ static void tau_announce_request_finished(struct tau_announce_request const* req
} }
} }
static void tau_announce_request_fail(struct tau_announce_request* request, bool did_connect, bool did_timeout, static void tau_announce_request_fail(
struct tau_announce_request* request,
bool did_connect,
bool did_timeout,
char const* errmsg) char const* errmsg)
{ {
request->response.did_connect = did_connect; request->response.did_connect = did_connect;
@ -406,7 +411,11 @@ static void on_announce_response(struct tau_announce_request* request, tau_actio
resp->interval = evbuffer_read_ntoh_32(buf); resp->interval = evbuffer_read_ntoh_32(buf);
resp->leechers = evbuffer_read_ntoh_32(buf); resp->leechers = evbuffer_read_ntoh_32(buf);
resp->seeders = evbuffer_read_ntoh_32(buf); resp->seeders = evbuffer_read_ntoh_32(buf);
resp->pex = tr_peerMgrCompactToPex(evbuffer_pullup(buf, -1), evbuffer_get_length(buf), NULL, 0, resp->pex = tr_peerMgrCompactToPex(
evbuffer_pullup(buf, -1),
evbuffer_get_length(buf),
NULL,
0,
&request->response.pex_count); &request->response.pex_count);
tau_announce_request_finished(request); tau_announce_request_finished(request);
} }
@ -703,13 +712,23 @@ static void tau_tracker_upkeep_ex(struct tau_tracker* tracker, bool timeout_reqs
hints.ai_socktype = SOCK_DGRAM; hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP; hints.ai_protocol = IPPROTO_UDP;
dbgmsg(tracker->host, "Trying a new DNS lookup"); dbgmsg(tracker->host, "Trying a new DNS lookup");
tracker->dns_request = evdns_getaddrinfo(tracker->session->evdns_base, tracker->host, NULL, &hints, tau_tracker_on_dns, tracker->dns_request = evdns_getaddrinfo(
tracker->session->evdns_base,
tracker->host,
NULL,
&hints,
tau_tracker_on_dns,
tracker); tracker);
return; return;
} }
dbgmsg(tracker->key, "addr %p -- connected %d (%zu %zu) -- connecting_at %zu", (void*)tracker->addr, dbgmsg(
(int)(tracker->connection_expiration_time > now), (size_t)tracker->connection_expiration_time, (size_t)now, tracker->key,
"addr %p -- connected %d (%zu %zu) -- connecting_at %zu",
(void*)tracker->addr,
(int)(tracker->connection_expiration_time > now),
(size_t)tracker->connection_expiration_time,
(size_t)now,
(size_t)tracker->connecting_at); (size_t)tracker->connecting_at);
/* also need a valid connection ID... */ /* also need a valid connection ID... */
@ -980,7 +999,10 @@ bool tau_handle_message(tr_session* session, uint8_t const* msg, size_t msglen)
return false; return false;
} }
void tr_tracker_udp_announce(tr_session* session, tr_announce_request const* request, tr_announce_response_func response_func, void tr_tracker_udp_announce(
tr_session* session,
tr_announce_request const* request,
tr_announce_response_func response_func,
void* user_data) void* user_data)
{ {
struct tr_announcer_udp* tau = announcer_udp_get(session); struct tr_announcer_udp* tau = announcer_udp_get(session);
@ -990,7 +1012,10 @@ void tr_tracker_udp_announce(tr_session* session, tr_announce_request const* req
tau_tracker_upkeep_ex(tracker, false); tau_tracker_upkeep_ex(tracker, false);
} }
void tr_tracker_udp_scrape(tr_session* session, tr_scrape_request const* request, tr_scrape_response_func response_func, void tr_tracker_udp_scrape(
tr_session* session,
tr_scrape_request const* request,
tr_scrape_response_func response_func,
void* user_data) void* user_data)
{ {
struct tr_announcer_udp* tau = announcer_udp_get(session); struct tr_announcer_udp* tau = announcer_udp_get(session);

View File

@ -41,8 +41,7 @@ static void tier_build_log_name(struct tr_tier const* tier, char* buf, size_t bu
tier_build_log_name(tier, name, TR_N_ELEMENTS(name)); \ tier_build_log_name(tier, name, TR_N_ELEMENTS(name)); \
tr_logAddDeep(__FILE__, __LINE__, name, __VA_ARGS__); \ tr_logAddDeep(__FILE__, __LINE__, name, __VA_ARGS__); \
} \ } \
} \ } while (0)
while (0)
enum enum
{ {
@ -176,8 +175,7 @@ typedef struct tr_announcer
int slotsAvailable; int slotsAvailable;
int key; int key;
time_t tauUpkeepAt; time_t tauUpkeepAt;
} } tr_announcer;
tr_announcer;
static struct tr_scrape_info* tr_announcerGetScrapeInfo(struct tr_announcer* announcer, char const* url) static struct tr_scrape_info* tr_announcerGetScrapeInfo(struct tr_announcer* announcer, char const* url)
{ {
@ -262,8 +260,7 @@ typedef struct
int consecutiveFailures; int consecutiveFailures;
uint32_t id; uint32_t id;
} } tr_tracker;
tr_tracker;
/* format: host+':'+ port */ /* format: host+':'+ port */
static char* getKey(char const* url) static char* getKey(char const* url)
@ -353,8 +350,7 @@ typedef struct tr_tier
char lastAnnounceStr[128]; char lastAnnounceStr[128];
char lastScrapeStr[128]; char lastScrapeStr[128];
} } tr_tier;
tr_tier;
static time_t get_next_scrape_time(tr_session const* session, tr_tier const* tier, int interval) static time_t get_next_scrape_time(tr_session const* session, tr_tier const* tier, int interval)
{ {
@ -404,7 +400,11 @@ static void tierDestruct(tr_tier* tier)
static void tier_build_log_name(tr_tier const* tier, char* buf, size_t buflen) static void tier_build_log_name(tr_tier const* tier, char* buf, size_t buflen)
{ {
tr_snprintf(buf, buflen, "[%s---%s]", (tier != NULL && tier->tor != NULL) ? tr_torrentName(tier->tor) : "?", tr_snprintf(
buf,
buflen,
"[%s---%s]",
(tier != NULL && tier->tor != NULL) ? tr_torrentName(tier->tor) : "?",
(tier != NULL && tier->currentTracker != NULL) ? tier->currentTracker->key : "?"); (tier != NULL && tier->currentTracker != NULL) ? tier->currentTracker->key : "?");
} }
@ -444,8 +444,7 @@ typedef struct tr_torrent_tiers
tr_tracker_callback callback; tr_tracker_callback callback;
void* callbackData; void* callbackData;
} } tr_torrent_tiers;
tr_torrent_tiers;
static tr_torrent_tiers* tiersNew(void) static tr_torrent_tiers* tiersNew(void)
{ {
@ -505,14 +504,13 @@ static tr_tier* getTier(tr_announcer* announcer, uint8_t const* info_hash, int t
**** PUBLISH **** PUBLISH
***/ ***/
static tr_tracker_event const TRACKER_EVENT_INIT = static tr_tracker_event const TRACKER_EVENT_INIT = {
{
.messageType = TR_TRACKER_WARNING, .messageType = TR_TRACKER_WARNING,
.text = NULL, .text = NULL,
.tracker = NULL, .tracker = NULL,
.pex = NULL, .pex = NULL,
.pexCount = 0, .pexCount = 0,
.seedProbability = 0 .seedProbability = 0,
}; };
static void publishMessage(tr_tier* tier, char const* msg, int type) static void publishMessage(tr_tier* tier, char const* msg, int type)
@ -964,7 +962,10 @@ void tr_announcerAddBytes(tr_torrent* tor, int type, uint32_t byteCount)
**** ****
***/ ***/
static tr_announce_request* announce_request_new(tr_announcer const* announcer, tr_torrent* tor, tr_tier const* tier, static tr_announce_request* announce_request_new(
tr_announcer const* announcer,
tr_torrent* tor,
tr_tier const* tier,
tr_announce_event event) tr_announce_event event)
{ {
tr_announce_request* req = tr_new0(tr_announce_request, 1); tr_announce_request* req = tr_new0(tr_announce_request, 1);
@ -1098,7 +1099,8 @@ static void on_announce_done(tr_announce_response const* response, void* vdata)
{ {
tr_tracker* tracker; tr_tracker* tracker;
dbgmsg(tier, dbgmsg(
tier,
"Got announce response: " "Got announce response: "
"connected:%d " "connected:%d "
"timeout:%d " "timeout:%d "
@ -1229,8 +1231,11 @@ static void on_announce_done(tr_announce_response const* response, void* vdata)
then a separate scrape isn't needed */ then a separate scrape isn't needed */
if (scrape_fields >= 3 || (scrape_fields >= 1 && tracker->scrape_info == NULL)) if (scrape_fields >= 3 || (scrape_fields >= 1 && tracker->scrape_info == NULL))
{ {
tr_logAddTorDbg(tier->tor, "Announce response contained scrape info; " tr_logAddTorDbg(
"rescheduling next scrape to %d seconds from now.", tier->scrapeIntervalSec); tier->tor,
"Announce response contained scrape info; "
"rescheduling next scrape to %d seconds from now.",
tier->scrapeIntervalSec);
tier->scrapeAt = get_next_scrape_time(announcer->session, tier, tier->scrapeIntervalSec); tier->scrapeAt = get_next_scrape_time(announcer->session, tier, tier->scrapeIntervalSec);
tier->lastScrapeTime = now; tier->lastScrapeTime = now;
tier->lastScrapeSucceeded = true; tier->lastScrapeSucceeded = true;
@ -1273,7 +1278,10 @@ static void announce_request_free(tr_announce_request* req)
tr_free(req); tr_free(req);
} }
static void announce_request_delegate(tr_announcer* announcer, tr_announce_request* request, tr_announce_response_func callback, static void announce_request_delegate(
tr_announcer* announcer,
tr_announce_request* request,
tr_announce_response_func callback,
void* callback_data) void* callback_data)
{ {
tr_session* session = announcer->session; tr_session* session = announcer->session;
@ -1339,11 +1347,10 @@ static bool multiscrape_too_big(char const* errmsg)
{ {
/* Found a tracker that returns some bespoke string for this case? /* Found a tracker that returns some bespoke string for this case?
Add your patch here and open a PR */ Add your patch here and open a PR */
static char const* const too_long_errors[] = static char const* const too_long_errors[] = {
{
"Bad Request", "Bad Request",
"GET string too long", "GET string too long",
"Request-URI Too Long" "Request-URI Too Long",
}; };
if (errmsg == NULL) if (errmsg == NULL)
@ -1396,9 +1403,7 @@ static tr_tier* find_tier(tr_torrent* tor, char const* scrape)
{ {
tr_tracker const* const tracker = tt->tiers[i].currentTracker; tr_tracker const* const tracker = tt->tiers[i].currentTracker;
if (tracker != NULL && if (tracker != NULL && tracker->scrape_info != NULL && tr_strcmp0(scrape, tracker->scrape_info->url) == 0)
tracker->scrape_info != NULL &&
tr_strcmp0(scrape, tracker->scrape_info->url) == 0)
{ {
return &tt->tiers[i]; return &tt->tiers[i];
} }
@ -1424,7 +1429,8 @@ static void on_scrape_done(tr_scrape_response const* response, void* vsession)
if (tier != NULL) if (tier != NULL)
{ {
dbgmsg(tier, dbgmsg(
tier,
"scraped url:%s -- " "scraped url:%s -- "
"did_connect:%d " "did_connect:%d "
"did_timeout:%d " "did_timeout:%d "
@ -1537,7 +1543,10 @@ static void on_scrape_done(tr_scrape_response const* response, void* vsession)
} }
} }
static void scrape_request_delegate(tr_announcer* announcer, tr_scrape_request const* request, tr_scrape_response_func callback, static void scrape_request_delegate(
tr_announcer* announcer,
tr_scrape_request const* request,
tr_scrape_response_func callback,
void* callback_data) void* callback_data)
{ {
tr_session* session = announcer->session; tr_session* session = announcer->session;
@ -1647,7 +1656,10 @@ static int compareTiers(void const* va, void const* vb)
tr_tier const* b = *(tr_tier const* const*)vb; tr_tier const* b = *(tr_tier const* const*)vb;
/* primary key: larger stats come before smaller */ /* primary key: larger stats come before smaller */
ret = compareTransfer(a->byteCounts[TR_ANN_UP], a->byteCounts[TR_ANN_DOWN], b->byteCounts[TR_ANN_UP], ret = compareTransfer(
a->byteCounts[TR_ANN_UP],
a->byteCounts[TR_ANN_DOWN],
b->byteCounts[TR_ANN_UP],
b->byteCounts[TR_ANN_DOWN]); b->byteCounts[TR_ANN_DOWN]);
/* secondary key: announcements that have been waiting longer go first */ /* secondary key: announcements that have been waiting longer go first */

View File

@ -27,8 +27,7 @@ typedef enum
TR_TRACKER_ERROR, TR_TRACKER_ERROR,
TR_TRACKER_ERROR_CLEAR, TR_TRACKER_ERROR_CLEAR,
TR_TRACKER_PEERS TR_TRACKER_PEERS
} } TrackerEventType;
TrackerEventType;
struct tr_pex; struct tr_pex;
@ -48,10 +47,9 @@ typedef struct
/* [0...100] for probability a peer is a seed. calculated by the leecher/seeder ratio */ /* [0...100] for probability a peer is a seed. calculated by the leecher/seeder ratio */
int8_t seedProbability; int8_t seedProbability;
} } tr_tracker_event;
tr_tracker_event;
typedef void (* tr_tracker_callback)(tr_torrent* tor, tr_tracker_event const* event, void* client_data); typedef void (*tr_tracker_callback)(tr_torrent* tor, tr_tracker_event const* event, void* client_data);
/** /**
*** Session ctor/dtor *** Session ctor/dtor

View File

@ -149,7 +149,11 @@ void tr_bandwidthSetParent(tr_bandwidth* b, tr_bandwidth* parent)
**** ****
***/ ***/
static void allocateBandwidth(tr_bandwidth* b, tr_priority_t parent_priority, tr_direction dir, unsigned int period_msec, static void allocateBandwidth(
tr_bandwidth* b,
tr_priority_t parent_priority,
tr_direction dir,
unsigned int period_msec,
tr_ptrArray* peer_pool) tr_ptrArray* peer_pool)
{ {
TR_ASSERT(tr_isBandwidth(b)); TR_ASSERT(tr_isBandwidth(b));
@ -386,8 +390,14 @@ void tr_bandwidthUsed(tr_bandwidth* b, tr_direction dir, size_t byteCount, bool
if (dir == DEBUG_DIRECTION && band->isLimited) if (dir == DEBUG_DIRECTION && band->isLimited)
{ {
fprintf(stderr, "%p consumed %5zu bytes of %5s data... was %6zu, now %6zu left\n", b, byteCount, fprintf(
isPieceData ? "piece" : "raw", oldBytesLeft, band->bytesLeft); stderr,
"%p consumed %5zu bytes of %5s data... was %6zu, now %6zu left\n",
b,
byteCount,
isPieceData ? "piece" : "raw",
oldBytesLeft,
band->bytesLeft);
} }
#endif #endif

View File

@ -44,8 +44,7 @@ struct bratecontrol
{ {
uint64_t date; uint64_t date;
uint64_t size; uint64_t size;
} } transfers[HISTORY_SIZE];
transfers[HISTORY_SIZE];
uint64_t cache_time; uint64_t cache_time;
unsigned int cache_val; unsigned int cache_val;
}; };
@ -114,8 +113,7 @@ typedef struct tr_bandwidth
tr_session* session; tr_session* session;
tr_ptrArray children; /* struct tr_bandwidth */ tr_ptrArray children; /* struct tr_bandwidth */
struct tr_peerIo* peer; struct tr_peerIo* peer;
} } tr_bandwidth;
tr_bandwidth;
/** /**
*** ***

View File

@ -13,38 +13,36 @@
#include "tr-assert.h" #include "tr-assert.h"
#include "utils.h" /* tr_new0() */ #include "utils.h" /* tr_new0() */
tr_bitfield const TR_BITFIELD_INIT = tr_bitfield const TR_BITFIELD_INIT = {
{
.bits = NULL, .bits = NULL,
.alloc_count = 0, .alloc_count = 0,
.bit_count = 0, .bit_count = 0,
.true_count = 0, .true_count = 0,
.have_all_hint = false, .have_all_hint = false,
.have_none_hint = false .have_none_hint = false,
}; };
/**** /****
***** *****
****/ ****/
static int8_t const trueBitCount[256] = static int8_t const trueBitCount[256] = {
{ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, //
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, //
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, //
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, //
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, //
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, //
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, //
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, //
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, //
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, //
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, //
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, //
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, //
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, //
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, //
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, //
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
}; };
static size_t countArray(tr_bitfield const* b) static size_t countArray(tr_bitfield const* b)

View File

@ -31,8 +31,7 @@ typedef struct tr_bitfield
This occurs when a magnet link's peers send have all / have none */ This occurs when a magnet link's peers send have all / have none */
bool have_all_hint; bool have_all_hint;
bool have_none_hint; bool have_none_hint;
} } tr_bitfield;
tr_bitfield;
/*** /***
**** ****

View File

@ -235,12 +235,16 @@ static bool parseLine1(char const* line, struct tr_ipv4_range* range)
++walk; /* walk past the colon */ ++walk; /* walk past the colon */
if (sscanf(walk, "%d.%d.%d.%d-%d.%d.%d.%d", &b[0], &b[1], &b[2], &b[3], &e[0], &e[1], &e[2], &e[3]) != 8) if (sscanf(
walk,
"%d.%d.%d.%d-%d.%d.%d.%d",
TR_ARG_TUPLE(&b[0], &b[1], &b[2], &b[3]),
TR_ARG_TUPLE(&e[0], &e[1], &e[2], &e[3])) != 8)
{ {
return false; return false;
} }
tr_snprintf(str, sizeof(str), "%d.%d.%d.%d", b[0], b[1], b[2], b[3]); tr_snprintf(str, sizeof(str), "%d.%d.%d.%d", TR_ARG_TUPLE(b[0], b[1], b[2], b[3]));
if (!tr_address_from_string(&addr, str)) if (!tr_address_from_string(&addr, str))
{ {
@ -249,7 +253,7 @@ static bool parseLine1(char const* line, struct tr_ipv4_range* range)
range->begin = ntohl(addr.addr.addr4.s_addr); range->begin = ntohl(addr.addr.addr4.s_addr);
tr_snprintf(str, sizeof(str), "%d.%d.%d.%d", e[0], e[1], e[2], e[3]); tr_snprintf(str, sizeof(str), "%d.%d.%d.%d", TR_ARG_TUPLE(e[0], e[1], e[2], e[3]));
if (!tr_address_from_string(&addr, str)) if (!tr_address_from_string(&addr, str))
{ {
@ -273,13 +277,17 @@ static bool parseLine2(char const* line, struct tr_ipv4_range* range)
char str[32]; char str[32];
tr_address addr; tr_address addr;
if (sscanf(line, "%3d.%3d.%3d.%3d - %3d.%3d.%3d.%3d , %3d , ", &a[0], &a[1], &a[2], &a[3], &b[0], &b[1], &b[2], &b[3], if (sscanf(
&unk) != 9) line,
"%3d.%3d.%3d.%3d - %3d.%3d.%3d.%3d , %3d , ",
TR_ARG_TUPLE(&a[0], &a[1], &a[2], &a[3]),
TR_ARG_TUPLE(&b[0], &b[1], &b[2], &b[3]),
&unk) != 9)
{ {
return false; return false;
} }
tr_snprintf(str, sizeof(str), "%d.%d.%d.%d", a[0], a[1], a[2], a[3]); tr_snprintf(str, sizeof(str), "%d.%d.%d.%d", TR_ARG_TUPLE(a[0], a[1], a[2], a[3]));
if (!tr_address_from_string(&addr, str)) if (!tr_address_from_string(&addr, str))
{ {
@ -288,7 +296,7 @@ static bool parseLine2(char const* line, struct tr_ipv4_range* range)
range->begin = ntohl(addr.addr.addr4.s_addr); range->begin = ntohl(addr.addr.addr4.s_addr);
tr_snprintf(str, sizeof(str), "%d.%d.%d.%d", b[0], b[1], b[2], b[3]); tr_snprintf(str, sizeof(str), "%d.%d.%d.%d", TR_ARG_TUPLE(b[0], b[1], b[2], b[3]));
if (!tr_address_from_string(&addr, str)) if (!tr_address_from_string(&addr, str))
{ {
@ -311,7 +319,7 @@ static bool parseLine3(char const* line, struct tr_ipv4_range* range)
uint32_t ip_u; uint32_t ip_u;
uint32_t mask = 0xffffffff; uint32_t mask = 0xffffffff;
if (sscanf(line, "%u.%u.%u.%u/%u", &ip[0], &ip[1], &ip[2], &ip[3], &pflen) != 5) if (sscanf(line, "%u.%u.%u.%u/%u", TR_ARG_TUPLE(&ip[0], &ip[1], &ip[2], &ip[3]), &pflen) != 5)
{ {
return false; return false;
} }

View File

@ -312,7 +312,12 @@ static struct cache_block* findBlock(tr_cache* cache, tr_torrent* torrent, tr_pi
return tr_ptrArrayFindSorted(&cache->blocks, &key, cache_block_compare); return tr_ptrArrayFindSorted(&cache->blocks, &key, cache_block_compare);
} }
int tr_cacheWriteBlock(tr_cache* cache, tr_torrent* torrent, tr_piece_index_t piece, uint32_t offset, uint32_t length, int tr_cacheWriteBlock(
tr_cache* cache,
tr_torrent* torrent,
tr_piece_index_t piece,
uint32_t offset,
uint32_t length,
struct evbuffer* writeme) struct evbuffer* writeme)
{ {
TR_ASSERT(tr_amInEventThread(torrent->session)); TR_ASSERT(tr_amInEventThread(torrent->session));
@ -344,7 +349,12 @@ int tr_cacheWriteBlock(tr_cache* cache, tr_torrent* torrent, tr_piece_index_t pi
return cacheTrim(cache); return cacheTrim(cache);
} }
int tr_cacheReadBlock(tr_cache* cache, tr_torrent* torrent, tr_piece_index_t piece, uint32_t offset, uint32_t len, int tr_cacheReadBlock(
tr_cache* cache,
tr_torrent* torrent,
tr_piece_index_t piece,
uint32_t offset,
uint32_t len,
uint8_t* setme) uint8_t* setme)
{ {
int err = 0; int err = 0;

View File

@ -36,10 +36,20 @@ int tr_cacheSetLimit(tr_cache* cache, int64_t max_bytes);
int64_t tr_cacheGetLimit(tr_cache const*); int64_t tr_cacheGetLimit(tr_cache const*);
int tr_cacheWriteBlock(tr_cache* cache, tr_torrent* torrent, tr_piece_index_t piece, uint32_t offset, uint32_t len, int tr_cacheWriteBlock(
tr_cache* cache,
tr_torrent* torrent,
tr_piece_index_t piece,
uint32_t offset,
uint32_t len,
struct evbuffer* writeme); struct evbuffer* writeme);
int tr_cacheReadBlock(tr_cache* cache, tr_torrent* torrent, tr_piece_index_t piece, uint32_t offset, uint32_t len, int tr_cacheReadBlock(
tr_cache* cache,
tr_torrent* torrent,
tr_piece_index_t piece,
uint32_t offset,
uint32_t len,
uint8_t* setme); uint8_t* setme);
int tr_cachePrefetchBlock(tr_cache* cache, tr_torrent* torrent, tr_piece_index_t piece, uint32_t offset, uint32_t len); int tr_cachePrefetchBlock(tr_cache* cache, tr_torrent* torrent, tr_piece_index_t piece, uint32_t offset, uint32_t len);

View File

@ -100,7 +100,14 @@ static void three_digits(char* buf, size_t buflen, char const* name, uint8_t con
static void four_digits(char* buf, size_t buflen, char const* name, uint8_t const* digits) static void four_digits(char* buf, size_t buflen, char const* name, uint8_t const* digits)
{ {
tr_snprintf(buf, buflen, "%s %d.%d.%d.%d", name, charint(digits[0]), charint(digits[1]), charint(digits[2]), tr_snprintf(
buf,
buflen,
"%s %d.%d.%d.%d",
name,
charint(digits[0]),
charint(digits[1]),
charint(digits[2]),
charint(digits[3])); charint(digits[3]));
} }
@ -210,34 +217,69 @@ char* tr_clientForId(char* buf, size_t buflen, void const* id_in)
} }
else /* current client style: -TR111Z- is 1.11+ */ else /* current client style: -TR111Z- is 1.11+ */
{ {
tr_snprintf(buf, buflen, "Transmission %d.%02d%s", strint(id + 3, 1), strint(id + 4, 2), tr_snprintf(
buf,
buflen,
"Transmission %d.%02d%s",
strint(id + 3, 1),
strint(id + 4, 2),
(id[6] == 'Z' || id[6] == 'X') ? "+" : ""); (id[6] == 'Z' || id[6] == 'X') ? "+" : "");
} }
} }
else if (strncmp(chid + 1, "UT", 2) == 0) else if (strncmp(chid + 1, "UT", 2) == 0)
{ {
tr_snprintf(buf, buflen, "\xc2\xb5Torrent %d.%d.%d%s", strint(id + 3, 1), strint(id + 4, 1), strint(id + 5, 1), tr_snprintf(
buf,
buflen,
"\xc2\xb5Torrent %d.%d.%d%s",
strint(id + 3, 1),
strint(id + 4, 1),
strint(id + 5, 1),
getMnemonicEnd(id[6])); getMnemonicEnd(id[6]));
} }
else if (strncmp(chid + 1, "BT", 2) == 0) else if (strncmp(chid + 1, "BT", 2) == 0)
{ {
tr_snprintf(buf, buflen, "BitTorrent %d.%d.%d%s", strint(id + 3, 1), strint(id + 4, 1), strint(id + 5, 1), tr_snprintf(
buf,
buflen,
"BitTorrent %d.%d.%d%s",
strint(id + 3, 1),
strint(id + 4, 1),
strint(id + 5, 1),
getMnemonicEnd(id[6])); getMnemonicEnd(id[6]));
} }
else if (strncmp(chid + 1, "UM", 2) == 0) else if (strncmp(chid + 1, "UM", 2) == 0)
{ {
tr_snprintf(buf, buflen, "\xc2\xb5Torrent Mac %d.%d.%d%s", strint(id + 3, 1), strint(id + 4, 1), strint(id + 5, 1), tr_snprintf(
buf,
buflen,
"\xc2\xb5Torrent Mac %d.%d.%d%s",
strint(id + 3, 1),
strint(id + 4, 1),
strint(id + 5, 1),
getMnemonicEnd(id[6])); getMnemonicEnd(id[6]));
} }
else if (strncmp(chid + 1, "UE", 2) == 0) else if (strncmp(chid + 1, "UE", 2) == 0)
{ {
tr_snprintf(buf, buflen, "\xc2\xb5Torrent Embedded %d.%d.%d%s", strint(id + 3, 1), strint(id + 4, 1), tr_snprintf(
strint(id + 5, 1), getMnemonicEnd(id[6])); buf,
buflen,
"\xc2\xb5Torrent Embedded %d.%d.%d%s",
strint(id + 3, 1),
strint(id + 4, 1),
strint(id + 5, 1),
getMnemonicEnd(id[6]));
} }
else if (strncmp(chid + 1, "UW", 2) == 0) else if (strncmp(chid + 1, "UW", 2) == 0)
{ {
tr_snprintf(buf, buflen, "\xc2\xb5Torrent Web %d.%d.%d%s", strint(id + 3, 1), strint(id + 4, 1), strint(id + 5, tr_snprintf(
1), getMnemonicEnd(id[6])); buf,
buflen,
"\xc2\xb5Torrent Web %d.%d.%d%s",
strint(id + 3, 1),
strint(id + 4, 1),
strint(id + 5, 1),
getMnemonicEnd(id[6]));
} }
/* */ /* */
else if (strncmp(chid + 1, "AZ", 2) == 0) else if (strncmp(chid + 1, "AZ", 2) == 0)
@ -655,23 +697,47 @@ char* tr_clientForId(char* buf, size_t buflen, void const* id_in)
{ {
if (strncmp(chid + 1, "UT", 2) == 0) if (strncmp(chid + 1, "UT", 2) == 0)
{ {
tr_snprintf(buf, buflen, "\xc2\xb5Torrent %d.%d.%d%s", strint(id + 3, 1), strint(id + 4, 1), strint(id + 5, 2), tr_snprintf(
buf,
buflen,
"\xc2\xb5Torrent %d.%d.%d%s",
strint(id + 3, 1),
strint(id + 4, 1),
strint(id + 5, 2),
getMnemonicEnd(id[7])); getMnemonicEnd(id[7]));
} }
else if (strncmp(chid + 1, "UM", 2) == 0) else if (strncmp(chid + 1, "UM", 2) == 0)
{ {
tr_snprintf(buf, buflen, "\xc2\xb5Torrent Mac %d.%d.%d%s", strint(id + 3, 1), strint(id + 4, 1), strint(id + 5, 2), tr_snprintf(
buf,
buflen,
"\xc2\xb5Torrent Mac %d.%d.%d%s",
strint(id + 3, 1),
strint(id + 4, 1),
strint(id + 5, 2),
getMnemonicEnd(id[7])); getMnemonicEnd(id[7]));
} }
else if (strncmp(chid + 1, "UE", 2) == 0) else if (strncmp(chid + 1, "UE", 2) == 0)
{ {
tr_snprintf(buf, buflen, "\xc2\xb5Torrent Embedded %d.%d.%d%s", strint(id + 3, 1), strint(id + 4, 1), tr_snprintf(
strint(id + 5, 2), getMnemonicEnd(id[7])); buf,
buflen,
"\xc2\xb5Torrent Embedded %d.%d.%d%s",
strint(id + 3, 1),
strint(id + 4, 1),
strint(id + 5, 2),
getMnemonicEnd(id[7]));
} }
else if (strncmp(chid + 1, "UW", 2) == 0) else if (strncmp(chid + 1, "UW", 2) == 0)
{ {
tr_snprintf(buf, buflen, "\xc2\xb5Torrent Web %d.%d.%d%s", strint(id + 3, 1), strint(id + 4, 1), strint(id + 5, tr_snprintf(
2), getMnemonicEnd(id[7])); buf,
buflen,
"\xc2\xb5Torrent Web %d.%d.%d%s",
strint(id + 3, 1),
strint(id + 4, 1),
strint(id + 5, 2),
getMnemonicEnd(id[7]));
} }
if (!tr_str_is_empty(buf)) if (!tr_str_is_empty(buf))

View File

@ -40,8 +40,7 @@ typedef struct tr_completion
/* number of bytes we want or have now. [0..sizeWhenDone] */ /* number of bytes we want or have now. [0..sizeWhenDone] */
uint64_t sizeNow; uint64_t sizeNow;
} } tr_completion;
tr_completion;
/** /**
*** Life Cycle *** Life Cycle

View File

@ -6,11 +6,10 @@
* *
*/ */
/* *INDENT-OFF* */
#if defined(CYASSL_IS_WOLFSSL) #if defined(CYASSL_IS_WOLFSSL)
#define API_HEADER(x) <wolfssl/x> #define API_HEADER(x) <wolfssl/x>
#define API_HEADER_CRYPT(x) API_HEADER(wolfcrypt/x) #define API_HEADER_CRYPT(x) API_HEADER(wolfcrypt/x)
#define API(x) wc_ ## x #define API(x) wc_##x
#define API_VERSION_HEX LIBWOLFSSL_VERSION_HEX #define API_VERSION_HEX LIBWOLFSSL_VERSION_HEX
#else #else
#define API_HEADER(x) <cyassl/x> #define API_HEADER(x) <cyassl/x>
@ -25,7 +24,6 @@
#include API_HEADER_CRYPT(random.h) #include API_HEADER_CRYPT(random.h)
#include API_HEADER_CRYPT(sha.h) #include API_HEADER_CRYPT(sha.h)
#include API_HEADER(version.h) #include API_HEADER(version.h)
/* *INDENT-ON* */
#include "transmission.h" #include "transmission.h"
#include "crypto-utils.h" #include "crypto-utils.h"
@ -204,7 +202,10 @@ void tr_rc4_process(tr_rc4_ctx_t handle, void const* input, void* output, size_t
**** ****
***/ ***/
tr_dh_ctx_t tr_dh_new(uint8_t const* prime_num, size_t prime_num_length, uint8_t const* generator_num, tr_dh_ctx_t tr_dh_new(
uint8_t const* prime_num,
size_t prime_num_length,
uint8_t const* generator_num,
size_t generator_num_length) size_t generator_num_length)
{ {
TR_ASSERT(prime_num != NULL); TR_ASSERT(prime_num != NULL);
@ -258,8 +259,13 @@ bool tr_dh_make_key(tr_dh_ctx_t raw_handle, size_t private_key_length, uint8_t*
tr_lockLock(rng_lock); tr_lockLock(rng_lock);
if (!check_result(API(DhGenerateKeyPair)(&handle->dh, get_rng(), handle->private_key, &my_private_key_length, public_key, if (!check_result(API(DhGenerateKeyPair)(
&my_public_key_length))) &handle->dh,
get_rng(),
handle->private_key,
&my_private_key_length,
public_key,
&my_public_key_length)))
{ {
tr_lockUnlock(rng_lock); tr_lockUnlock(rng_lock);
return false; return false;
@ -290,8 +296,14 @@ tr_dh_secret_t tr_dh_agree(tr_dh_ctx_t raw_handle, uint8_t const* other_public_k
ret = tr_dh_secret_new(handle->key_length); ret = tr_dh_secret_new(handle->key_length);
if (check_result(API(DhAgree)(&handle->dh, ret->key, &my_secret_key_length, handle->private_key, handle->private_key_length, if (check_result(API(DhAgree)(
other_public_key, other_public_key_length))) &handle->dh,
ret->key,
&my_secret_key_length,
handle->private_key,
handle->private_key_length,
other_public_key,
other_public_key_length)))
{ {
tr_dh_secret_align(ret, my_secret_key_length); tr_dh_secret_align(ret, my_secret_key_length);
} }

View File

@ -43,16 +43,28 @@ static void tr_dh_secret_align(struct tr_dh_secret* handle, size_t current_key_l
tr_dh_align_key(handle->key, current_key_length, handle->key_length); tr_dh_align_key(handle->key, current_key_length, handle->key_length);
} }
bool tr_dh_secret_derive(tr_dh_secret_t raw_handle, void const* prepend_data, size_t prepend_data_size, void const* append_data, bool tr_dh_secret_derive(
size_t append_data_size, uint8_t* hash) tr_dh_secret_t raw_handle,
void const* prepend_data,
size_t prepend_data_size,
void const* append_data,
size_t append_data_size,
uint8_t* hash)
{ {
TR_ASSERT(raw_handle != NULL); TR_ASSERT(raw_handle != NULL);
TR_ASSERT(hash != NULL); TR_ASSERT(hash != NULL);
struct tr_dh_secret* handle = raw_handle; struct tr_dh_secret* handle = raw_handle;
return tr_sha1(hash, prepend_data == NULL ? "" : prepend_data, prepend_data == NULL ? 0 : (int)prepend_data_size, return tr_sha1(
handle->key, (int)handle->key_length, append_data, append_data == NULL ? 0 : (int)append_data_size, NULL); hash,
prepend_data == NULL ? "" : prepend_data,
prepend_data == NULL ? 0 : (int)prepend_data_size,
handle->key,
(int)handle->key_length,
append_data,
append_data == NULL ? 0 : (int)append_data_size,
NULL);
} }
void tr_dh_secret_free(tr_dh_secret_t handle) void tr_dh_secret_free(tr_dh_secret_t handle)

View File

@ -297,7 +297,10 @@ static inline void DH_get0_key(DH const* dh, BIGNUM const** pub_key, BIGNUM cons
#endif #endif
tr_dh_ctx_t tr_dh_new(uint8_t const* prime_num, size_t prime_num_length, uint8_t const* generator_num, tr_dh_ctx_t tr_dh_new(
uint8_t const* prime_num,
size_t prime_num_length,
uint8_t const* generator_num,
size_t generator_num_length) size_t generator_num_length)
{ {
TR_ASSERT(prime_num != NULL); TR_ASSERT(prime_num != NULL);

View File

@ -6,17 +6,15 @@
* *
*/ */
/* *INDENT-OFF* */
#if defined(POLARSSL_IS_MBEDTLS) #if defined(POLARSSL_IS_MBEDTLS)
#define API_HEADER(x) <mbedtls/x> #define API_HEADER(x) <mbedtls/x>
#define API(x) mbedtls_ ## x #define API(x) mbedtls_##x
#define API_VERSION_NUMBER MBEDTLS_VERSION_NUMBER #define API_VERSION_NUMBER MBEDTLS_VERSION_NUMBER
#else #else
#define API_HEADER(x) <polarssl/x> #define API_HEADER(x) <polarssl/x>
#define API(x) x #define API(x) x
#define API_VERSION_NUMBER POLARSSL_VERSION_NUMBER #define API_VERSION_NUMBER POLARSSL_VERSION_NUMBER
#endif #endif
/* *INDENT-ON* */
#include API_HEADER(arc4.h) #include API_HEADER(arc4.h)
#include API_HEADER(base64.h) #include API_HEADER(base64.h)
@ -43,10 +41,10 @@
#define MY_NAME "tr_crypto_utils" #define MY_NAME "tr_crypto_utils"
typedef API (ctr_drbg_context) api_ctr_drbg_context; typedef API(ctr_drbg_context) api_ctr_drbg_context;
typedef API (sha1_context) api_sha1_context; typedef API(sha1_context) api_sha1_context;
typedef API (arc4_context) api_arc4_context; typedef API(arc4_context) api_arc4_context;
typedef API (dhm_context) api_dhm_context; typedef API(dhm_context) api_dhm_context;
static void log_polarssl_error(int error_code, char const* file, int line) static void log_polarssl_error(int error_code, char const* file, int line)
{ {
@ -235,7 +233,10 @@ void tr_rc4_process(tr_rc4_ctx_t handle, void const* input, void* output, size_t
**** ****
***/ ***/
tr_dh_ctx_t tr_dh_new(uint8_t const* prime_num, size_t prime_num_length, uint8_t const* generator_num, tr_dh_ctx_t tr_dh_new(
uint8_t const* prime_num,
size_t prime_num_length,
uint8_t const* generator_num,
size_t generator_num_length) size_t generator_num_length)
{ {
TR_ASSERT(prime_num != NULL); TR_ASSERT(prime_num != NULL);

View File

@ -81,7 +81,10 @@ void tr_rc4_process(tr_rc4_ctx_t handle, void const* input, void* output, size_t
/** /**
* @brief Allocate and initialize new Diffie-Hellman (DH) key exchange context. * @brief Allocate and initialize new Diffie-Hellman (DH) key exchange context.
*/ */
tr_dh_ctx_t tr_dh_new(uint8_t const* prime_num, size_t prime_num_length, uint8_t const* generator_num, tr_dh_ctx_t tr_dh_new(
uint8_t const* prime_num,
size_t prime_num_length,
uint8_t const* generator_num,
size_t generator_num_length); size_t generator_num_length);
/** /**
@ -103,8 +106,13 @@ tr_dh_secret_t tr_dh_agree(tr_dh_ctx_t handle, uint8_t const* other_public_key,
* @brief Calculate SHA1 hash of DH secret key, prepending and/or appending * @brief Calculate SHA1 hash of DH secret key, prepending and/or appending
* given data to the key during calculation. * given data to the key during calculation.
*/ */
bool tr_dh_secret_derive(tr_dh_secret_t handle, void const* prepend_data, size_t prepend_data_size, void const* append_data, bool tr_dh_secret_derive(
size_t append_data_size, uint8_t* hash); tr_dh_secret_t handle,
void const* prepend_data,
size_t prepend_data_size,
void const* append_data,
size_t append_data_size,
uint8_t* hash);
/** /**
* @brief Free DH secret key returned by @ref tr_dh_agree. * @brief Free DH secret key returned by @ref tr_dh_agree.

View File

@ -21,16 +21,15 @@
#define PRIME_LEN 96 #define PRIME_LEN 96
#define DH_PRIVKEY_LEN 20 #define DH_PRIVKEY_LEN 20
static uint8_t const dh_P[PRIME_LEN] = static uint8_t const dh_P[PRIME_LEN] = {
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, //
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, //
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, //
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, //
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, //
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, //
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, //
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x3A, 0x36, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x05, 0x63, //
0xA6, 0x3A, 0x36, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x05, 0x63,
}; };
static uint8_t const dh_G[] = { 2 }; static uint8_t const dh_G[] = { 2 };
@ -157,8 +156,13 @@ void tr_cryptoEncrypt(tr_crypto* crypto, size_t buf_len, void const* buf_in, voi
tr_rc4_process(crypto->enc_key, buf_in, buf_out, buf_len); tr_rc4_process(crypto->enc_key, buf_in, buf_out, buf_len);
} }
bool tr_cryptoSecretKeySha1(tr_crypto const* crypto, void const* prepend_data, size_t prepend_data_size, bool tr_cryptoSecretKeySha1(
void const* append_data, size_t append_data_size, uint8_t* hash) tr_crypto const* crypto,
void const* prepend_data,
size_t prepend_data_size,
void const* append_data,
size_t append_data_size,
uint8_t* hash)
{ {
TR_ASSERT(crypto != NULL); TR_ASSERT(crypto != NULL);
TR_ASSERT(crypto->mySecret != NULL); TR_ASSERT(crypto->mySecret != NULL);

View File

@ -43,8 +43,7 @@ typedef struct
uint8_t torrentHash[SHA_DIGEST_LENGTH]; uint8_t torrentHash[SHA_DIGEST_LENGTH];
bool isIncoming; bool isIncoming;
bool torrentHashIsSet; bool torrentHashIsSet;
} } tr_crypto;
tr_crypto;
/** @brief construct a new tr_crypto object */ /** @brief construct a new tr_crypto object */
void tr_cryptoConstruct(tr_crypto* crypto, uint8_t const* torrentHash, bool isIncoming); void tr_cryptoConstruct(tr_crypto* crypto, uint8_t const* torrentHash, bool isIncoming);
@ -70,8 +69,13 @@ void tr_cryptoEncryptInit(tr_crypto* crypto);
void tr_cryptoEncrypt(tr_crypto* crypto, size_t buflen, void const* buf_in, void* buf_out); void tr_cryptoEncrypt(tr_crypto* crypto, size_t buflen, void const* buf_in, void* buf_out);
bool tr_cryptoSecretKeySha1(tr_crypto const* crypto, void const* prepend_data, size_t prepend_data_size, bool tr_cryptoSecretKeySha1(
void const* append_data, size_t append_data_size, uint8_t* hash); tr_crypto const* crypto,
void const* prepend_data,
size_t prepend_data_size,
void const* append_data,
size_t append_data_size,
uint8_t* hash);
/* @} */ /* @} */

View File

@ -26,8 +26,7 @@ typedef struct tr_error
int code; int code;
/** @brief Error message */ /** @brief Error message */
char* message; char* message;
} } tr_error;
tr_error;
/** /**
* @brief Create new error object using literal error message. * @brief Create new error object using literal error message.
@ -126,8 +125,8 @@ void tr_error_prefix(tr_error** error, char const* prefix_format, ...) TR_GNUC_P
* @param[in] prefix_format Prefix format string. * @param[in] prefix_format Prefix format string.
* @param[in] ... Format arguments. * @param[in] ... Format arguments.
*/ */
void tr_error_propagate_prefixed(tr_error** new_error, tr_error** old_error, char const* prefix_format, ...) TR_GNUC_PRINTF(3, void tr_error_propagate_prefixed(tr_error** new_error, tr_error** old_error, char const* prefix_format, ...)
4); TR_GNUC_PRINTF(3, 4);
/** @} */ /** @} */

View File

@ -146,7 +146,11 @@ static void cached_file_close(struct tr_cached_file* o)
* errno values include ENOENT if the parent folder doesn't exist, * errno values include ENOENT if the parent folder doesn't exist,
* plus the errno values set by tr_sys_dir_create () and tr_sys_file_open (). * plus the errno values set by tr_sys_dir_create () and tr_sys_file_open ().
*/ */
static int cached_file_open(struct tr_cached_file* o, char const* filename, bool writable, tr_preallocation_mode allocation, static int cached_file_open(
struct tr_cached_file* o,
char const* filename,
bool writable,
tr_preallocation_mode allocation,
uint64_t file_size) uint64_t file_size)
{ {
int flags; int flags;
@ -214,8 +218,12 @@ static int cached_file_open(struct tr_cached_file* o, char const* filename, bool
if (!success) if (!success)
{ {
tr_logAddError(_("Couldn't preallocate file \"%1$s\" (%2$s, size: %3$" PRIu64 "): %4$s"), tr_logAddError(
filename, type, file_size, error->message); _("Couldn't preallocate file \"%1$s\" (%2$s, size: %3$" PRIu64 "): %4$s"),
filename,
type,
file_size,
error->message);
goto FAIL; goto FAIL;
} }
@ -263,13 +271,12 @@ struct tr_fileset
static void fileset_construct(struct tr_fileset* set, int n) static void fileset_construct(struct tr_fileset* set, int n)
{ {
struct tr_cached_file const TR_CACHED_FILE_INIT = struct tr_cached_file const TR_CACHED_FILE_INIT = {
{
.is_writable = false, .is_writable = false,
.fd = TR_BAD_SYS_FILE, .fd = TR_BAD_SYS_FILE,
.torrent_id = 0, .torrent_id = 0,
.file_index = 0, .file_index = 0,
.used_at = 0 .used_at = 0,
}; };
set->begin = tr_new(struct tr_cached_file, n); set->begin = tr_new(struct tr_cached_file, n);
@ -468,8 +475,14 @@ void tr_fdTorrentClose(tr_session* session, int torrent_id)
} }
/* returns an fd on success, or a TR_BAD_SYS_FILE on failure and sets errno */ /* returns an fd on success, or a TR_BAD_SYS_FILE on failure and sets errno */
tr_sys_file_t tr_fdFileCheckout(tr_session* session, int torrent_id, tr_file_index_t i, char const* filename, bool writable, tr_sys_file_t tr_fdFileCheckout(
tr_preallocation_mode allocation, uint64_t file_size) tr_session* session,
int torrent_id,
tr_file_index_t i,
char const* filename,
bool writable,
tr_preallocation_mode allocation,
uint64_t file_size)
{ {
struct tr_fileset* set = get_fileset(session); struct tr_fileset* set = get_fileset(session);
struct tr_cached_file* o = fileset_lookup(set, torrent_id, i); struct tr_cached_file* o = fileset_lookup(set, torrent_id, i);

View File

@ -40,8 +40,14 @@
* *
* @see tr_fdFileClose * @see tr_fdFileClose
*/ */
tr_sys_file_t tr_fdFileCheckout(tr_session* session, int torrent_id, tr_file_index_t file_num, char const* filename, tr_sys_file_t tr_fdFileCheckout(
bool do_write, tr_preallocation_mode preallocation_mode, uint64_t preallocation_file_size); tr_session* session,
int torrent_id,
tr_file_index_t file_num,
char const* filename,
bool do_write,
tr_preallocation_mode preallocation_mode,
uint64_t preallocation_file_size);
tr_sys_file_t tr_fdFileGetCached(tr_session* session, int torrent_id, tr_file_index_t file_num, bool doWrite); tr_sys_file_t tr_fdFileGetCached(tr_session* session, int torrent_id, tr_file_index_t file_num, bool doWrite);

View File

@ -30,23 +30,23 @@
/* OS-specific file copy (copy_file_range, sendfile64, or copyfile). */ /* OS-specific file copy (copy_file_range, sendfile64, or copyfile). */
#if defined(__linux__) #if defined(__linux__)
# include <linux/version.h> #include <linux/version.h>
/* Linux's copy_file_range(2) is buggy prior to 5.3. */ /* Linux's copy_file_range(2) is buggy prior to 5.3. */
# if defined(HAVE_COPY_FILE_RANGE) && LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) #if defined(HAVE_COPY_FILE_RANGE) && LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
# define USE_COPY_FILE_RANGE #define USE_COPY_FILE_RANGE
# elif defined(HAVE_SENDFILE64) #elif defined(HAVE_SENDFILE64)
# include <sys/sendfile.h> #include <sys/sendfile.h>
# define USE_SENDFILE64 #define USE_SENDFILE64
# endif #endif
#elif defined(__APPLE__) && defined(HAVE_COPYFILE) #elif defined(__APPLE__) && defined(HAVE_COPYFILE)
# include <copyfile.h> #include <copyfile.h>
# ifndef COPYFILE_CLONE /* macos < 10.12 */ #ifndef COPYFILE_CLONE /* macos < 10.12 */
# define COPYFILE_CLONE 0 #define COPYFILE_CLONE 0
# endif #endif
# define USE_COPYFILE #define USE_COPYFILE
#elif defined(HAVE_COPY_FILE_RANGE) #elif defined(HAVE_COPY_FILE_RANGE)
/* Presently this is only FreeBSD 13+. */ /* Presently this is only FreeBSD 13+. */
# define USE_COPY_FILE_RANGE #define USE_COPY_FILE_RANGE
#endif /* __linux__ */ #endif /* __linux__ */
#include "transmission.h" #include "transmission.h"
@ -622,12 +622,12 @@ tr_sys_file_t tr_sys_file_open(char const* path, int flags, int permissions, tr_
native_flags |= O_WRONLY; native_flags |= O_WRONLY;
} }
native_flags |= native_flags |= //
((flags & TR_SYS_FILE_CREATE) != 0 ? O_CREAT : 0) | ((flags & TR_SYS_FILE_CREATE) != 0 ? O_CREAT : 0) | //
((flags & TR_SYS_FILE_CREATE_NEW) != 0 ? O_CREAT | O_EXCL : 0) | ((flags & TR_SYS_FILE_CREATE_NEW) != 0 ? O_CREAT | O_EXCL : 0) | //
((flags & TR_SYS_FILE_APPEND) != 0 ? O_APPEND : 0) | ((flags & TR_SYS_FILE_APPEND) != 0 ? O_APPEND : 0) | //
((flags & TR_SYS_FILE_TRUNCATE) != 0 ? O_TRUNC : 0) | ((flags & TR_SYS_FILE_TRUNCATE) != 0 ? O_TRUNC : 0) | //
((flags & TR_SYS_FILE_SEQUENTIAL) != 0 ? O_SEQUENTIAL : 0) | ((flags & TR_SYS_FILE_SEQUENTIAL) != 0 ? O_SEQUENTIAL : 0) | //
O_BINARY | O_LARGEFILE | O_CLOEXEC; O_BINARY | O_LARGEFILE | O_CLOEXEC;
ret = open(path, native_flags, permissions); ret = open(path, native_flags, permissions);
@ -759,7 +759,12 @@ bool tr_sys_file_read(tr_sys_file_t handle, void* buffer, uint64_t size, uint64_
return ret; return ret;
} }
bool tr_sys_file_read_at(tr_sys_file_t handle, void* buffer, uint64_t size, uint64_t offset, uint64_t* bytes_read, bool tr_sys_file_read_at(
tr_sys_file_t handle,
void* buffer,
uint64_t size,
uint64_t offset,
uint64_t* bytes_read,
tr_error** error) tr_error** error)
{ {
TR_ASSERT(handle != TR_BAD_SYS_FILE); TR_ASSERT(handle != TR_BAD_SYS_FILE);
@ -835,7 +840,12 @@ bool tr_sys_file_write(tr_sys_file_t handle, void const* buffer, uint64_t size,
return ret; return ret;
} }
bool tr_sys_file_write_at(tr_sys_file_t handle, void const* buffer, uint64_t size, uint64_t offset, uint64_t* bytes_written, bool tr_sys_file_write_at(
tr_sys_file_t handle,
void const* buffer,
uint64_t size,
uint64_t offset,
uint64_t* bytes_written,
tr_error** error) tr_error** error)
{ {
TR_ASSERT(handle != TR_BAD_SYS_FILE); TR_ASSERT(handle != TR_BAD_SYS_FILE);
@ -920,7 +930,8 @@ bool tr_sys_file_advise(tr_sys_file_t handle, uint64_t offset, uint64_t size, tr
#if defined(HAVE_POSIX_FADVISE) #if defined(HAVE_POSIX_FADVISE)
int const native_advice = advice == TR_SYS_FILE_ADVICE_WILL_NEED ? POSIX_FADV_WILLNEED : int const native_advice = advice == TR_SYS_FILE_ADVICE_WILL_NEED ?
POSIX_FADV_WILLNEED :
(advice == TR_SYS_FILE_ADVICE_DONT_NEED ? POSIX_FADV_DONTNEED : POSIX_FADV_NORMAL); (advice == TR_SYS_FILE_ADVICE_DONT_NEED ? POSIX_FADV_DONTNEED : POSIX_FADV_NORMAL);
TR_ASSERT(native_advice != POSIX_FADV_NORMAL); TR_ASSERT(native_advice != POSIX_FADV_NORMAL);
@ -940,10 +951,9 @@ bool tr_sys_file_advise(tr_sys_file_t handle, uint64_t offset, uint64_t size, tr
goto skip_darwin_fcntl; goto skip_darwin_fcntl;
} }
struct radvisory const radv = struct radvisory const radv = {
{
.ra_offset = offset, .ra_offset = offset,
.ra_count = size .ra_count = size,
}; };
ret = fcntl(handle, F_RDADVISE, &radv) != -1; ret = fcntl(handle, F_RDADVISE, &radv) != -1;
@ -1109,8 +1119,8 @@ bool tr_sys_file_lock(tr_sys_file_t handle, int operation, tr_error** error)
{ {
TR_ASSERT(handle != TR_BAD_SYS_FILE); TR_ASSERT(handle != TR_BAD_SYS_FILE);
TR_ASSERT((operation & ~(TR_SYS_FILE_LOCK_SH | TR_SYS_FILE_LOCK_EX | TR_SYS_FILE_LOCK_NB | TR_SYS_FILE_LOCK_UN)) == 0); TR_ASSERT((operation & ~(TR_SYS_FILE_LOCK_SH | TR_SYS_FILE_LOCK_EX | TR_SYS_FILE_LOCK_NB | TR_SYS_FILE_LOCK_UN)) == 0);
TR_ASSERT(!!(operation & TR_SYS_FILE_LOCK_SH) + !!(operation & TR_SYS_FILE_LOCK_EX) + TR_ASSERT(
!!(operation & TR_SYS_FILE_LOCK_UN) == 1); !!(operation & TR_SYS_FILE_LOCK_SH) + !!(operation & TR_SYS_FILE_LOCK_EX) + !!(operation & TR_SYS_FILE_LOCK_UN) == 1);
bool ret; bool ret;
@ -1138,8 +1148,7 @@ bool tr_sys_file_lock(tr_sys_file_t handle, int operation, tr_error** error)
do do
{ {
ret = fcntl(handle, (operation & TR_SYS_FILE_LOCK_NB) != 0 ? F_OFD_SETLK : F_OFD_SETLKW, &fl) != -1; ret = fcntl(handle, (operation & TR_SYS_FILE_LOCK_NB) != 0 ? F_OFD_SETLK : F_OFD_SETLKW, &fl) != -1;
} } while (!ret && errno == EINTR);
while (!ret && errno == EINTR);
if (!ret && errno == EAGAIN) if (!ret && errno == EAGAIN)
{ {
@ -1173,8 +1182,7 @@ bool tr_sys_file_lock(tr_sys_file_t handle, int operation, tr_error** error)
do do
{ {
ret = flock(handle, native_operation) != -1; ret = flock(handle, native_operation) != -1;
} } while (!ret && errno == EINTR);
while (!ret && errno == EINTR);
#else #else
@ -1216,8 +1224,7 @@ char* tr_sys_dir_get_current(tr_error** error)
ret = getcwd(tmp, size); ret = getcwd(tmp, size);
size += 2048; size += 2048;
} } while (ret == NULL && errno == ERANGE);
while (ret == NULL && errno == ERANGE);
if (ret == NULL) if (ret == NULL)
{ {

View File

@ -19,7 +19,7 @@
#include "utils.h" #include "utils.h"
#ifndef MAXSIZE_T #ifndef MAXSIZE_T
#define MAXSIZE_T ((SIZE_T)~((SIZE_T)0)) #define MAXSIZE_T ((SIZE_T) ~((SIZE_T)0))
#endif #endif
/* MSDN (http://msdn.microsoft.com/en-us/library/2k2xf226.aspx) only mentions /* MSDN (http://msdn.microsoft.com/en-us/library/2k2xf226.aspx) only mentions
@ -81,7 +81,11 @@ static time_t filetime_to_unix_time(FILETIME const* t)
return tmp / 1000000UL; return tmp / 1000000UL;
} }
static void stat_to_sys_path_info(DWORD attributes, DWORD size_low, DWORD size_high, FILETIME const* mtime, static void stat_to_sys_path_info(
DWORD attributes,
DWORD size_low,
DWORD size_high,
FILETIME const* mtime,
tr_sys_path_info* info) tr_sys_path_info* info)
{ {
TR_ASSERT(mtime != NULL); TR_ASSERT(mtime != NULL);
@ -153,8 +157,9 @@ static wchar_t* path_to_native_path_ex(char const* path, int extra_chars_after,
bool const is_unc = is_unc_path(path); bool const is_unc = is_unc_path(path);
/* `-2` for UNC since we overwrite existing prefix slashes */ /* `-2` for UNC since we overwrite existing prefix slashes */
int const extra_chars_before = is_relative ? 0 : (is_unc ? TR_N_ELEMENTS(native_unc_path_prefix) - 2 : int const extra_chars_before = is_relative ?
TR_N_ELEMENTS(native_local_path_prefix)); 0 :
(is_unc ? TR_N_ELEMENTS(native_unc_path_prefix) - 2 : TR_N_ELEMENTS(native_local_path_prefix));
/* TODO (?): TR_ASSERT(!is_relative); */ /* TODO (?): TR_ASSERT(!is_relative); */
@ -213,7 +218,7 @@ static char* native_path_to_path(wchar_t const* wide_path)
bool const is_local = !is_unc && wcsncmp(wide_path, native_local_path_prefix, TR_N_ELEMENTS(native_local_path_prefix)) == 0; bool const is_local = !is_unc && wcsncmp(wide_path, native_local_path_prefix, TR_N_ELEMENTS(native_local_path_prefix)) == 0;
size_t const skip_chars = is_unc ? TR_N_ELEMENTS(native_unc_path_prefix) : size_t const skip_chars = is_unc ? TR_N_ELEMENTS(native_unc_path_prefix) :
(is_local ? TR_N_ELEMENTS(native_local_path_prefix) : 0); (is_local ? TR_N_ELEMENTS(native_local_path_prefix) : 0);
char* const path = tr_win32_native_to_utf8_ex(wide_path + skip_chars, -1, is_unc ? 2 : 0, 0, NULL); char* const path = tr_win32_native_to_utf8_ex(wide_path + skip_chars, -1, is_unc ? 2 : 0, 0, NULL);
@ -235,7 +240,13 @@ static tr_sys_file_t open_file(char const* path, DWORD access, DWORD disposition
if (wide_path != NULL) if (wide_path != NULL)
{ {
ret = CreateFileW(wide_path, access, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, disposition, flags, ret = CreateFileW(
wide_path,
access,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
disposition,
flags,
NULL); NULL);
} }
@ -294,8 +305,11 @@ static bool create_dir(char const* path, int flags, int permissions, bool okay_i
return ret; return ret;
} }
static void create_temp_path(char* path_template, void (* callback)(char const* path, void* param, static void create_temp_path(
tr_error** error), void* callback_param, tr_error** error) char* path_template,
void (*callback)(char const* path, void* param, tr_error** error),
void* callback_param,
tr_error** error)
{ {
TR_ASSERT(path_template != NULL); TR_ASSERT(path_template != NULL);
TR_ASSERT(callback != NULL); TR_ASSERT(callback != NULL);
@ -428,8 +442,12 @@ bool tr_sys_path_get_info(char const* path, int flags, tr_sys_path_info* info, t
if (ret) if (ret)
{ {
stat_to_sys_path_info(attributes.dwFileAttributes, attributes.nFileSizeLow, attributes.nFileSizeHigh, stat_to_sys_path_info(
&attributes.ftLastWriteTime, info); attributes.dwFileAttributes,
attributes.nFileSizeLow,
attributes.nFileSizeHigh,
&attributes.ftLastWriteTime,
info);
} }
else else
{ {
@ -543,8 +561,14 @@ char* tr_sys_path_resolve(char const* path, tr_error** error)
goto fail; goto fail;
} }
handle = CreateFileW(wide_path, FILE_READ_EA, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, handle = CreateFileW(
FILE_FLAG_BACKUP_SEMANTICS, NULL); wide_path,
FILE_READ_EA,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL);
if (handle == INVALID_HANDLE_VALUE) if (handle == INVALID_HANDLE_VALUE)
{ {
@ -961,8 +985,12 @@ bool tr_sys_file_get_info(tr_sys_file_t handle, tr_sys_path_info* info, tr_error
if (ret) if (ret)
{ {
stat_to_sys_path_info(attributes.dwFileAttributes, attributes.nFileSizeLow, attributes.nFileSizeHigh, stat_to_sys_path_info(
&attributes.ftLastWriteTime, info); attributes.dwFileAttributes,
attributes.nFileSizeLow,
attributes.nFileSizeHigh,
&attributes.ftLastWriteTime,
info);
} }
else else
{ {
@ -1035,7 +1063,12 @@ bool tr_sys_file_read(tr_sys_file_t handle, void* buffer, uint64_t size, uint64_
return ret; return ret;
} }
bool tr_sys_file_read_at(tr_sys_file_t handle, void* buffer, uint64_t size, uint64_t offset, uint64_t* bytes_read, bool tr_sys_file_read_at(
tr_sys_file_t handle,
void* buffer,
uint64_t size,
uint64_t offset,
uint64_t* bytes_read,
tr_error** error) tr_error** error)
{ {
TR_ASSERT(handle != TR_BAD_SYS_FILE); TR_ASSERT(handle != TR_BAD_SYS_FILE);
@ -1104,7 +1137,12 @@ bool tr_sys_file_write(tr_sys_file_t handle, void const* buffer, uint64_t size,
return ret; return ret;
} }
bool tr_sys_file_write_at(tr_sys_file_t handle, void const* buffer, uint64_t size, uint64_t offset, uint64_t* bytes_written, bool tr_sys_file_write_at(
tr_sys_file_t handle,
void const* buffer,
uint64_t size,
uint64_t offset,
uint64_t* bytes_written,
tr_error** error) tr_error** error)
{ {
TR_ASSERT(handle != TR_BAD_SYS_FILE); TR_ASSERT(handle != TR_BAD_SYS_FILE);
@ -1264,8 +1302,8 @@ bool tr_sys_file_lock(tr_sys_file_t handle, int operation, tr_error** error)
{ {
TR_ASSERT(handle != TR_BAD_SYS_FILE); TR_ASSERT(handle != TR_BAD_SYS_FILE);
TR_ASSERT((operation & ~(TR_SYS_FILE_LOCK_SH | TR_SYS_FILE_LOCK_EX | TR_SYS_FILE_LOCK_NB | TR_SYS_FILE_LOCK_UN)) == 0); TR_ASSERT((operation & ~(TR_SYS_FILE_LOCK_SH | TR_SYS_FILE_LOCK_EX | TR_SYS_FILE_LOCK_NB | TR_SYS_FILE_LOCK_UN)) == 0);
TR_ASSERT(!!(operation & TR_SYS_FILE_LOCK_SH) + !!(operation & TR_SYS_FILE_LOCK_EX) + TR_ASSERT(
!!(operation & TR_SYS_FILE_LOCK_UN) == 1); !!(operation & TR_SYS_FILE_LOCK_SH) + !!(operation & TR_SYS_FILE_LOCK_EX) + !!(operation & TR_SYS_FILE_LOCK_UN) == 1);
bool ret; bool ret;
OVERLAPPED overlapped = { .Pointer = 0, .hEvent = NULL }; OVERLAPPED overlapped = { .Pointer = 0, .hEvent = NULL };

View File

@ -57,8 +57,7 @@ typedef enum
TR_STD_SYS_FILE_IN, TR_STD_SYS_FILE_IN,
TR_STD_SYS_FILE_OUT, TR_STD_SYS_FILE_OUT,
TR_STD_SYS_FILE_ERR TR_STD_SYS_FILE_ERR
} } tr_std_sys_file_t;
tr_std_sys_file_t;
typedef enum typedef enum
{ {
@ -69,16 +68,14 @@ typedef enum
TR_SYS_FILE_APPEND = (1 << 4), TR_SYS_FILE_APPEND = (1 << 4),
TR_SYS_FILE_TRUNCATE = (1 << 5), TR_SYS_FILE_TRUNCATE = (1 << 5),
TR_SYS_FILE_SEQUENTIAL = (1 << 6) TR_SYS_FILE_SEQUENTIAL = (1 << 6)
} } tr_sys_file_open_flags_t;
tr_sys_file_open_flags_t;
typedef enum typedef enum
{ {
TR_SEEK_SET, TR_SEEK_SET,
TR_SEEK_CUR, TR_SEEK_CUR,
TR_SEEK_END TR_SEEK_END
} } tr_seek_origin_t;
tr_seek_origin_t;
typedef enum typedef enum
{ {
@ -86,49 +83,42 @@ typedef enum
TR_SYS_FILE_LOCK_EX = (1 << 1), TR_SYS_FILE_LOCK_EX = (1 << 1),
TR_SYS_FILE_LOCK_NB = (1 << 2), TR_SYS_FILE_LOCK_NB = (1 << 2),
TR_SYS_FILE_LOCK_UN = (1 << 3) TR_SYS_FILE_LOCK_UN = (1 << 3)
} } tr_sys_file_lock_flags_t;
tr_sys_file_lock_flags_t;
typedef enum typedef enum
{ {
TR_SYS_PATH_NO_FOLLOW = (1 << 0) TR_SYS_PATH_NO_FOLLOW = (1 << 0)
} } tr_sys_path_get_info_flags_t;
tr_sys_path_get_info_flags_t;
typedef enum typedef enum
{ {
TR_SYS_FILE_ADVICE_WILL_NEED, TR_SYS_FILE_ADVICE_WILL_NEED,
TR_SYS_FILE_ADVICE_DONT_NEED TR_SYS_FILE_ADVICE_DONT_NEED
} } tr_sys_file_advice_t;
tr_sys_file_advice_t;
typedef enum typedef enum
{ {
TR_SYS_FILE_PREALLOC_SPARSE = (1 << 0) TR_SYS_FILE_PREALLOC_SPARSE = (1 << 0)
} } tr_sys_file_preallocate_flags_t;
tr_sys_file_preallocate_flags_t;
typedef enum typedef enum
{ {
TR_SYS_DIR_CREATE_PARENTS = (1 << 0) TR_SYS_DIR_CREATE_PARENTS = (1 << 0)
} } tr_sys_dir_create_flags_t;
tr_sys_dir_create_flags_t;
typedef enum typedef enum
{ {
TR_SYS_PATH_IS_FILE, TR_SYS_PATH_IS_FILE,
TR_SYS_PATH_IS_DIRECTORY, TR_SYS_PATH_IS_DIRECTORY,
TR_SYS_PATH_IS_OTHER TR_SYS_PATH_IS_OTHER
} } tr_sys_path_type_t;
tr_sys_path_type_t;
typedef struct tr_sys_path_info typedef struct tr_sys_path_info
{ {
tr_sys_path_type_t type; tr_sys_path_type_t type;
uint64_t size; uint64_t size;
time_t last_modified_at; time_t last_modified_at;
} } tr_sys_path_info;
tr_sys_path_info;
/** /**
* @name Platform-specific wrapper functions * @name Platform-specific wrapper functions
@ -369,7 +359,11 @@ bool tr_sys_file_get_info(tr_sys_file_t handle, tr_sys_path_info* info, struct t
* *
* @return `True` on success, `false` otherwise (with `error` set accordingly). * @return `True` on success, `false` otherwise (with `error` set accordingly).
*/ */
bool tr_sys_file_seek(tr_sys_file_t handle, int64_t offset, tr_seek_origin_t origin, uint64_t* new_offset, bool tr_sys_file_seek(
tr_sys_file_t handle,
int64_t offset,
tr_seek_origin_t origin,
uint64_t* new_offset,
struct tr_error** error); struct tr_error** error);
/** /**
@ -402,7 +396,12 @@ bool tr_sys_file_read(tr_sys_file_t handle, void* buffer, uint64_t size, uint64_
* *
* @return `True` on success, `false` otherwise (with `error` set accordingly). * @return `True` on success, `false` otherwise (with `error` set accordingly).
*/ */
bool tr_sys_file_read_at(tr_sys_file_t handle, void* buffer, uint64_t size, uint64_t offset, uint64_t* bytes_read, bool tr_sys_file_read_at(
tr_sys_file_t handle,
void* buffer,
uint64_t size,
uint64_t offset,
uint64_t* bytes_read,
struct tr_error** error); struct tr_error** error);
/** /**
@ -418,7 +417,11 @@ bool tr_sys_file_read_at(tr_sys_file_t handle, void* buffer, uint64_t size, uint
* *
* @return `True` on success, `false` otherwise (with `error` set accordingly). * @return `True` on success, `false` otherwise (with `error` set accordingly).
*/ */
bool tr_sys_file_write(tr_sys_file_t handle, void const* buffer, uint64_t size, uint64_t* bytes_written, bool tr_sys_file_write(
tr_sys_file_t handle,
void const* buffer,
uint64_t size,
uint64_t* bytes_written,
struct tr_error** error); struct tr_error** error);
/** /**
@ -436,7 +439,12 @@ bool tr_sys_file_write(tr_sys_file_t handle, void const* buffer, uint64_t size,
* *
* @return `True` on success, `false` otherwise (with `error` set accordingly). * @return `True` on success, `false` otherwise (with `error` set accordingly).
*/ */
bool tr_sys_file_write_at(tr_sys_file_t handle, void const* buffer, uint64_t size, uint64_t offset, uint64_t* bytes_written, bool tr_sys_file_write_at(
tr_sys_file_t handle,
void const* buffer,
uint64_t size,
uint64_t offset,
uint64_t* bytes_written,
struct tr_error** error); struct tr_error** error);
/** /**
@ -473,7 +481,11 @@ bool tr_sys_file_truncate(tr_sys_file_t handle, uint64_t size, struct tr_error**
* *
* @return `True` on success, `false` otherwise (with `error` set accordingly). * @return `True` on success, `false` otherwise (with `error` set accordingly).
*/ */
bool tr_sys_file_advise(tr_sys_file_t handle, uint64_t offset, uint64_t size, tr_sys_file_advice_t advice, bool tr_sys_file_advise(
tr_sys_file_t handle,
uint64_t offset,
uint64_t size,
tr_sys_file_advice_t advice,
struct tr_error** error); struct tr_error** error);
/** /**

View File

@ -103,8 +103,7 @@ typedef enum
AWAITING_PAD_D, AWAITING_PAD_D,
/* */ /* */
N_STATES N_STATES
} } handshake_state_t;
handshake_state_t;
struct tr_handshake struct tr_handshake
{ {
@ -132,16 +131,16 @@ struct tr_handshake
**/ **/
#define dbgmsg(handshake, ...) \ #define dbgmsg(handshake, ...) \
do { \ do \
{ \
char addrstr[TR_ADDRSTRLEN]; \ char addrstr[TR_ADDRSTRLEN]; \
tr_peerIoGetAddrStr(handshake->io, addrstr, sizeof(addrstr)); \ tr_peerIoGetAddrStr(handshake->io, addrstr, sizeof(addrstr)); \
tr_logAddDeepNamed(addrstr, __VA_ARGS__); \ tr_logAddDeepNamed(addrstr, __VA_ARGS__); \
} while(0) } while (0)
static char const* getStateName(handshake_state_t const state) static char const* getStateName(handshake_state_t const state)
{ {
static char const* const state_strings[N_STATES] = static char const* const state_strings[N_STATES] = {
{
"awaiting handshake", /* AWAITING_HANDSHAKE */ "awaiting handshake", /* AWAITING_HANDSHAKE */
"awaiting peer id", /* AWAITING_PEER_ID */ "awaiting peer id", /* AWAITING_PEER_ID */
"awaiting ya", /* AWAITING_YA */ "awaiting ya", /* AWAITING_YA */
@ -215,8 +214,7 @@ typedef enum
HANDSHAKE_ENCRYPTION_WRONG, HANDSHAKE_ENCRYPTION_WRONG,
HANDSHAKE_BAD_TORRENT, HANDSHAKE_BAD_TORRENT,
HANDSHAKE_PEER_IS_SELF, HANDSHAKE_PEER_IS_SELF,
} } handshake_parse_err_t;
handshake_parse_err_t;
static handshake_parse_err_t parseHandshake(tr_handshake* handshake, struct evbuffer* inbuf) static handshake_parse_err_t parseHandshake(tr_handshake* handshake, struct evbuffer* inbuf)
{ {
@ -261,7 +259,7 @@ static handshake_parse_err_t parseHandshake(tr_handshake* handshake, struct evbu
/* peer id */ /* peer id */
handshake->havePeerID = true; handshake->havePeerID = true;
dbgmsg(handshake, "peer-id is [%*.*s]", PEER_ID_LEN, PEER_ID_LEN, peer_id); dbgmsg(handshake, "peer-id is [%*.*s]", TR_ARG_TUPLE(PEER_ID_LEN, PEER_ID_LEN, peer_id));
tor = tr_torrentFindFromHash(handshake->session, hash); tor = tr_torrentFindFromHash(handshake->session, hash);
@ -1093,8 +1091,13 @@ static ReadState canRead(struct tr_peerIo* io, void* arg, size_t* piece)
static bool fireDoneFunc(tr_handshake* handshake, bool isConnected) static bool fireDoneFunc(tr_handshake* handshake, bool isConnected)
{ {
uint8_t const* peer_id = (isConnected && handshake->havePeerID) ? tr_peerIoGetPeersId(handshake->io) : NULL; uint8_t const* peer_id = (isConnected && handshake->havePeerID) ? tr_peerIoGetPeersId(handshake->io) : NULL;
bool const success = (*handshake->doneCB)(handshake, handshake->io, handshake->haveReadAnythingFromPeer, isConnected, bool const success = (*handshake->doneCB)(
peer_id, handshake->doneUserData); handshake,
handshake->io,
handshake->haveReadAnythingFromPeer,
isConnected,
peer_id,
handshake->doneUserData);
return success; return success;
} }

View File

@ -25,11 +25,19 @@ struct tr_peerIo;
typedef struct tr_handshake tr_handshake; typedef struct tr_handshake tr_handshake;
/* returns true on success, false on error */ /* returns true on success, false on error */
typedef bool (* handshakeDoneCB)(struct tr_handshake* handshake, struct tr_peerIo* io, bool readAnythingFromPeer, typedef bool (*handshakeDoneCB)(
bool isConnected, uint8_t const* peerId, void* userData); struct tr_handshake* handshake,
struct tr_peerIo* io,
bool readAnythingFromPeer,
bool isConnected,
uint8_t const* peerId,
void* userData);
/** @brief instantiate a new handshake */ /** @brief instantiate a new handshake */
tr_handshake* tr_handshakeNew(struct tr_peerIo* io, tr_encryption_mode encryptionMode, handshakeDoneCB doneCB, tr_handshake* tr_handshakeNew(
struct tr_peerIo* io,
tr_encryption_mode encryptionMode,
handshakeDoneCB doneCB,
void* doneUserData); void* doneUserData);
tr_address const* tr_handshakeGetAddr(struct tr_handshake const* handshake, tr_port* port); tr_address const* tr_handshakeGetAddr(struct tr_handshake const* handshake, tr_port* port);

View File

@ -42,10 +42,8 @@ typedef struct tr_recentHistory
{ {
unsigned int n; unsigned int n;
time_t date; time_t date;
} } slices[TR_RECENT_HISTORY_PERIOD_SEC];
slices[TR_RECENT_HISTORY_PERIOD_SEC]; } tr_recentHistory;
}
tr_recentHistory;
/** /**
* @brief add a counter to the recent history object. * @brief add a counter to the recent history object.

View File

@ -37,8 +37,14 @@ enum
}; };
/* returns 0 on success, or an errno on failure */ /* returns 0 on success, or an errno on failure */
static int readOrWriteBytes(tr_session* session, tr_torrent* tor, int ioMode, tr_file_index_t fileIndex, uint64_t fileOffset, static int readOrWriteBytes(
void* buf, size_t buflen) tr_session* session,
tr_torrent* tor,
int ioMode,
tr_file_index_t fileIndex,
uint64_t fileOffset,
void* buf,
size_t buflen)
{ {
tr_sys_file_t fd; tr_sys_file_t fd;
int err = 0; int err = 0;
@ -79,7 +85,7 @@ static int readOrWriteBytes(tr_session* session, tr_torrent* tor, int ioMode, tr
/* figure out where the file should go, so we can create it */ /* figure out where the file should go, so we can create it */
base = tr_torrentGetCurrentDir(tor); base = tr_torrentGetCurrentDir(tor);
subpath = tr_sessionIsIncompleteFileNamingEnabled(tor->session) ? tr_torrentBuildPartial(tor, fileIndex) : subpath = tr_sessionIsIncompleteFileNamingEnabled(tor->session) ? tr_torrentBuildPartial(tor, fileIndex) :
tr_strdup(file->name); tr_strdup(file->name);
} }
if (err == 0) if (err == 0)
@ -88,8 +94,8 @@ static int readOrWriteBytes(tr_session* session, tr_torrent* tor, int ioMode, tr
char* filename = tr_buildPath(base, subpath, NULL); char* filename = tr_buildPath(base, subpath, NULL);
int const prealloc = (file->dnd || !doWrite) ? TR_PREALLOCATE_NONE : tor->session->preallocationMode; int const prealloc = (file->dnd || !doWrite) ? TR_PREALLOCATE_NONE : tor->session->preallocationMode;
if ((fd = tr_fdFileCheckout(session, tor->uniqueId, fileIndex, filename, doWrite, prealloc, if ((fd = tr_fdFileCheckout(session, tor->uniqueId, fileIndex, filename, doWrite, prealloc, file->length)) ==
file->length)) == TR_BAD_SYS_FILE) TR_BAD_SYS_FILE)
{ {
err = errno; err = errno;
tr_logAddTorErr(tor, "tr_fdFileCheckout failed for \"%s\": %s", filename, tr_strerror(err)); tr_logAddTorErr(tor, "tr_fdFileCheckout failed for \"%s\": %s", filename, tr_strerror(err));
@ -163,7 +169,11 @@ static int compareOffsetToFile(void const* a, void const* b)
return 0; return 0;
} }
void tr_ioFindFileLocation(tr_torrent const* tor, tr_piece_index_t pieceIndex, uint32_t pieceOffset, tr_file_index_t* fileIndex, void tr_ioFindFileLocation(
tr_torrent const* tor,
tr_piece_index_t pieceIndex,
uint32_t pieceOffset,
tr_file_index_t* fileIndex,
uint64_t* fileOffset) uint64_t* fileOffset)
{ {
TR_ASSERT(tr_isTorrent(tor)); TR_ASSERT(tr_isTorrent(tor));
@ -185,7 +195,12 @@ void tr_ioFindFileLocation(tr_torrent const* tor, tr_piece_index_t pieceIndex, u
} }
/* returns 0 on success, or an errno on failure */ /* returns 0 on success, or an errno on failure */
static int readOrWritePiece(tr_torrent* tor, int ioMode, tr_piece_index_t pieceIndex, uint32_t pieceOffset, uint8_t* buf, static int readOrWritePiece(
tr_torrent* tor,
int ioMode,
tr_piece_index_t pieceIndex,
uint32_t pieceOffset,
uint8_t* buf,
size_t buflen) size_t buflen)
{ {
int err = 0; int err = 0;

View File

@ -41,7 +41,11 @@ bool tr_ioTestPiece(tr_torrent* tor, tr_piece_index_t piece);
/** /**
* Converts a piece index + offset into a file index + offset. * Converts a piece index + offset into a file index + offset.
*/ */
void tr_ioFindFileLocation(tr_torrent const* tor, tr_piece_index_t pieceIndex, uint32_t pieceOffset, tr_file_index_t* fileIndex, void tr_ioFindFileLocation(
tr_torrent const* tor,
tr_piece_index_t pieceIndex,
uint32_t pieceOffset,
tr_file_index_t* fileIndex,
uint64_t* fileOffset); uint64_t* fileOffset);
/* @} */ /* @} */

View File

@ -11,11 +11,10 @@
#include "platform.h" #include "platform.h"
#include "utils.h" #include "utils.h"
static tr_list const TR_LIST_CLEAR = static tr_list const TR_LIST_CLEAR = {
{
.data = NULL, .data = NULL,
.next = NULL, .next = NULL,
.prev = NULL .prev = NULL,
}; };
static tr_list* recycled_nodes = NULL; static tr_list* recycled_nodes = NULL;

View File

@ -25,11 +25,10 @@ typedef struct tr_list
void* data; void* data;
struct tr_list* next; struct tr_list* next;
struct tr_list* prev; struct tr_list* prev;
} } tr_list;
tr_list;
typedef tr_voidptr_compare_func TrListCompareFunc; typedef tr_voidptr_compare_func TrListCompareFunc;
typedef void (* TrListForeachFunc)(void*); typedef void (*TrListForeachFunc)(void*);
/** /**
* @brief return the number of items in the list * @brief return the number of items in the list

View File

@ -25,7 +25,7 @@ static inline bool tr_logLevelIsActive(tr_log_level level)
return tr_logGetLevel() >= level; return tr_logGetLevel() >= level;
} }
void tr_logAddMessage(char const* file, int line, tr_log_level level, char const* torrent, char const* fmt, ...) \ void tr_logAddMessage(char const* file, int line, tr_log_level level, char const* torrent, char const* fmt, ...)
TR_GNUC_PRINTF(5, 6); TR_GNUC_PRINTF(5, 6);
#define tr_logAddNamed(level, name, ...) \ #define tr_logAddNamed(level, name, ...) \
@ -35,8 +35,7 @@ void tr_logAddMessage(char const* file, int line, tr_log_level level, char const
{ \ { \
tr_logAddMessage(__FILE__, __LINE__, level, name, __VA_ARGS__); \ tr_logAddMessage(__FILE__, __LINE__, level, name, __VA_ARGS__); \
} \ } \
} \ } while (0)
while (0)
#define tr_logAddNamedError(name, ...) tr_logAddNamed(TR_LOG_ERROR, name, __VA_ARGS__) #define tr_logAddNamedError(name, ...) tr_logAddNamed(TR_LOG_ERROR, name, __VA_ARGS__)
#define tr_logAddNamedInfo(name, ...) tr_logAddNamed(TR_LOG_INFO, name, __VA_ARGS__) #define tr_logAddNamedInfo(name, ...) tr_logAddNamed(TR_LOG_INFO, name, __VA_ARGS__)
@ -59,7 +58,7 @@ tr_sys_file_t tr_logGetFile(void);
/** @brief return true if deep logging has been enabled by the user, false otherwise */ /** @brief return true if deep logging has been enabled by the user, false otherwise */
bool tr_logGetDeepEnabled(void); bool tr_logGetDeepEnabled(void);
void tr_logAddDeep(char const* file, int line, char const* name, char const* fmt, ...) TR_GNUC_PRINTF(4, 5) \ void tr_logAddDeep(char const* file, int line, char const* name, char const* fmt, ...) TR_GNUC_PRINTF(4, 5)
TR_GNUC_NONNULL(1, 4); TR_GNUC_NONNULL(1, 4);
#define tr_logAddDeepNamed(name, ...) \ #define tr_logAddDeepNamed(name, ...) \
@ -69,8 +68,7 @@ void tr_logAddDeep(char const* file, int line, char const* name, char const* fmt
{ \ { \
tr_logAddDeep(__FILE__, __LINE__, name, __VA_ARGS__); \ tr_logAddDeep(__FILE__, __LINE__, name, __VA_ARGS__); \
} \ } \
} \ } while (0)
while (0)
/** @brief set the buffer with the current time formatted for deep logging. */ /** @brief set the buffer with the current time formatted for deep logging. */
char* tr_logGetTimeStr(char* buf, size_t buflen) TR_GNUC_NONNULL(1); char* tr_logGetTimeStr(char* buf, size_t buflen) TR_GNUC_NONNULL(1);

View File

@ -24,8 +24,7 @@
/* this base32 code converted from code by Robert Kaye and Gordon Mohr /* this base32 code converted from code by Robert Kaye and Gordon Mohr
* and is public domain. see http://bitzi.com/publicdomain for more info */ * and is public domain. see http://bitzi.com/publicdomain for more info */
static int const base32Lookup[] = static int const base32Lookup[] = {
{
0xFF, 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, /* '0', '1', '2', '3', '4', '5', '6', '7' */ 0xFF, 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, /* '0', '1', '2', '3', '4', '5', '6', '7' */
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* '8', '9', ':', ';', '<', '=', '>', '?' */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* '8', '9', ':', ';', '<', '=', '>', '?' */
0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G' */ 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G' */

View File

@ -29,8 +29,7 @@ typedef struct tr_magnet_info
int webseedCount; int webseedCount;
char** webseeds; char** webseeds;
} } tr_magnet_info;
tr_magnet_info;
tr_magnet_info* tr_magnetParse(char const* uri); tr_magnet_info* tr_magnetParse(char const* uri);

View File

@ -349,7 +349,10 @@ static uint8_t* getHashInfo(tr_metainfo_builder* b)
return ret; return ret;
} }
static void getFileInfo(char const* topFile, tr_metainfo_builder_file const* file, tr_variant* uninitialized_length, static void getFileInfo(
char const* topFile,
tr_metainfo_builder_file const* file,
tr_variant* uninitialized_length,
tr_variant* uninitialized_path) tr_variant* uninitialized_path)
{ {
size_t offset; size_t offset;
@ -491,8 +494,7 @@ static void tr_realMakeMetaInfo(tr_metainfo_builder* builder)
} }
/* save the file */ /* save the file */
if ((builder->result == TR_MAKEMETA_OK) && if ((builder->result == TR_MAKEMETA_OK) && (!builder->abortFlag) &&
(!builder->abortFlag) &&
(tr_variantToFile(&top, TR_VARIANT_FMT_BENC, builder->outputFile) != 0)) (tr_variantToFile(&top, TR_VARIANT_FMT_BENC, builder->outputFile) != 0))
{ {
builder->my_errno = errno; builder->my_errno = errno;
@ -565,8 +567,13 @@ static void makeMetaWorkerFunc(void* user_data)
workerThread = NULL; workerThread = NULL;
} }
void tr_makeMetaInfo(tr_metainfo_builder* builder, char const* outputFile, tr_tracker_info const* trackers, int trackerCount, void tr_makeMetaInfo(
char const* comment, bool isPrivate) tr_metainfo_builder* builder,
char const* outputFile,
tr_tracker_info const* trackers,
int trackerCount,
char const* comment,
bool isPrivate)
{ {
tr_lock* lock; tr_lock* lock;

View File

@ -17,8 +17,7 @@ typedef struct tr_metainfo_builder_file
{ {
char* filename; char* filename;
uint64_t size; uint64_t size;
} } tr_metainfo_builder_file;
tr_metainfo_builder_file;
typedef enum typedef enum
{ {
@ -27,8 +26,7 @@ typedef enum
TR_MAKEMETA_CANCELLED, TR_MAKEMETA_CANCELLED,
TR_MAKEMETA_IO_READ, /* see builder.errfile, builder.my_errno */ TR_MAKEMETA_IO_READ, /* see builder.errfile, builder.my_errno */
TR_MAKEMETA_IO_WRITE /* see builder.errfile, builder.my_errno */ TR_MAKEMETA_IO_WRITE /* see builder.errfile, builder.my_errno */
} } tr_metainfo_builder_err;
tr_metainfo_builder_err;
typedef struct tr_metainfo_builder typedef struct tr_metainfo_builder
{ {
@ -82,8 +80,7 @@ typedef struct tr_metainfo_builder
**/ **/
struct tr_metainfo_builder* nextBuilder; struct tr_metainfo_builder* nextBuilder;
} } tr_metainfo_builder;
tr_metainfo_builder;
tr_metainfo_builder* tr_metaInfoBuilderCreate(char const* topFile); tr_metainfo_builder* tr_metaInfoBuilderCreate(char const* topFile);
@ -114,7 +111,12 @@ void tr_metaInfoBuilderFree(tr_metainfo_builder*);
* *
* @param trackerCount size of the `trackers' array * @param trackerCount size of the `trackers' array
*/ */
void tr_makeMetaInfo(tr_metainfo_builder* builder, char const* outputFile, tr_tracker_info const* trackers, int trackerCount, void tr_makeMetaInfo(
char const* comment, bool isPrivate); tr_metainfo_builder* builder,
char const* outputFile,
tr_tracker_info const* trackers,
int trackerCount,
char const* comment,
bool isPrivate);
TR_END_DECLS TR_END_DECLS

View File

@ -97,11 +97,10 @@ char* tr_metainfo_sanitize_path_component(char const* str, size_t len, bool* is_
/* https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file */ /* https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file */
char const* const reserved_chars = "<>:\"/\\|?*"; char const* const reserved_chars = "<>:\"/\\|?*";
char const* const reserved_names[] = char const* const reserved_names[] = {
{ "CON", "PRN", "AUX", "NUL", //
"CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", //
"COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9", //
"LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9"
}; };
char* const ret = tr_new(char, len + 2); char* const ret = tr_new(char, len + 2);
@ -265,8 +264,7 @@ static char const* parseFiles(tr_info* inf, tr_variant* files, tr_variant const*
break; break;
} }
if (!tr_variantDictFindList(file, TR_KEY_path_utf_8, &path) && if (!tr_variantDictFindList(file, TR_KEY_path_utf_8, &path) && !tr_variantDictFindList(file, TR_KEY_path, &path))
!tr_variantDictFindList(file, TR_KEY_path, &path))
{ {
result = "path"; result = "path";
break; break;
@ -473,7 +471,7 @@ static char* fix_webseed_url(tr_info const* inf, char const* url_in)
{ {
if (inf->fileCount > 1 && len > 0 && url[len - 1] != '/') if (inf->fileCount > 1 && len > 0 && url[len - 1] != '/')
{ {
ret = tr_strdup_printf("%*.*s/", (int)len, (int)len, url); ret = tr_strdup_printf("%*.*s/", TR_ARG_TUPLE((int)len, (int)len, url));
} }
else else
{ {
@ -523,7 +521,11 @@ static void geturllist(tr_info* inf, tr_variant* meta)
} }
} }
static char const* tr_metainfoParseImpl(tr_session const* session, tr_info* inf, bool* hasInfoDict, size_t* infoDictLength, static char const* tr_metainfoParseImpl(
tr_session const* session,
tr_info* inf,
bool* hasInfoDict,
size_t* infoDictLength,
tr_variant const* meta_in) tr_variant const* meta_in)
{ {
int64_t i; int64_t i;
@ -661,8 +663,7 @@ static char const* tr_metainfoParseImpl(tr_session const* session, tr_info* inf,
inf->dateCreated = i; inf->dateCreated = i;
/* private */ /* private */
if (!tr_variantDictFindInt(infoDict, TR_KEY_private, &i) && if (!tr_variantDictFindInt(infoDict, TR_KEY_private, &i) && !tr_variantDictFindInt(meta, TR_KEY_private, &i))
!tr_variantDictFindInt(meta, TR_KEY_private, &i))
{ {
i = 0; i = 0;
} }
@ -705,8 +706,8 @@ static char const* tr_metainfoParseImpl(tr_session const* session, tr_info* inf,
/* files */ /* files */
if (!isMagnet) if (!isMagnet)
{ {
if ((str = parseFiles(inf, tr_variantDictFind(infoDict, TR_KEY_files), tr_variantDictFind(infoDict, if ((str = parseFiles(inf, tr_variantDictFind(infoDict, TR_KEY_files), tr_variantDictFind(infoDict, TR_KEY_length))) !=
TR_KEY_length))) != NULL) NULL)
{ {
return str; return str;
} }
@ -738,7 +739,11 @@ static char const* tr_metainfoParseImpl(tr_session const* session, tr_info* inf,
return NULL; return NULL;
} }
bool tr_metainfoParse(tr_session const* session, tr_variant const* meta_in, tr_info* inf, bool* hasInfoDict, bool tr_metainfoParse(
tr_session const* session,
tr_variant const* meta_in,
tr_info* inf,
bool* hasInfoDict,
size_t* infoDictLength) size_t* infoDictLength)
{ {
char const* badTag = tr_metainfoParseImpl(session, inf, hasInfoDict, infoDictLength, meta_in); char const* badTag = tr_metainfoParseImpl(session, inf, hasInfoDict, infoDictLength, meta_in);
@ -798,7 +803,10 @@ void tr_metainfoRemoveSaved(tr_session const* session, tr_info const* inf)
tr_free(filename); tr_free(filename);
} }
void tr_metainfoMigrateFile(tr_session const* session, tr_info const* info, enum tr_metainfo_basename_format old_format, void tr_metainfoMigrateFile(
tr_session const* session,
tr_info const* info,
enum tr_metainfo_basename_format old_format,
enum tr_metainfo_basename_format new_format) enum tr_metainfo_basename_format new_format)
{ {
char* old_filename = getTorrentFilename(session, info, old_format); char* old_filename = getTorrentFilename(session, info, old_format);

View File

@ -24,14 +24,21 @@ enum tr_metainfo_basename_format
TR_METAINFO_BASENAME_HASH TR_METAINFO_BASENAME_HASH
}; };
bool tr_metainfoParse(tr_session const* session, tr_variant const* variant, tr_info* setmeInfo, bool* setmeHasInfoDict, bool tr_metainfoParse(
tr_session const* session,
tr_variant const* variant,
tr_info* setmeInfo,
bool* setmeHasInfoDict,
size_t* setmeInfoDictLength); size_t* setmeInfoDictLength);
void tr_metainfoRemoveSaved(tr_session const* session, tr_info const* info); void tr_metainfoRemoveSaved(tr_session const* session, tr_info const* info);
char* tr_metainfoGetBasename(tr_info const*, enum tr_metainfo_basename_format format); char* tr_metainfoGetBasename(tr_info const*, enum tr_metainfo_basename_format format);
void tr_metainfoMigrateFile(tr_session const* session, tr_info const* info, enum tr_metainfo_basename_format old_format, void tr_metainfoMigrateFile(
tr_session const* session,
tr_info const* info,
enum tr_metainfo_basename_format old_format,
enum tr_metainfo_basename_format new_format); enum tr_metainfo_basename_format new_format);
/** @brief Private function that's exposed here only for unit tests */ /** @brief Private function that's exposed here only for unit tests */

View File

@ -7,8 +7,7 @@
#include "mime-types.h" #include "mime-types.h"
struct mime_type_suffix const mime_type_suffixes[MIME_TYPE_SUFFIX_COUNT] = struct mime_type_suffix const mime_type_suffixes[MIME_TYPE_SUFFIX_COUNT] = {
{
{ "123", "application/vnd.lotus-1-2-3" }, { "123", "application/vnd.lotus-1-2-3" },
{ "1km", "application/vnd.1000minds.decision-model+xml" }, { "1km", "application/vnd.1000minds.decision-model+xml" },
{ "3dml", "text/vnd.in3d.3dml" }, { "3dml", "text/vnd.in3d.3dml" },

View File

@ -40,8 +40,7 @@ typedef enum
TR_NATPMP_RECV_MAP, TR_NATPMP_RECV_MAP,
TR_NATPMP_SEND_UNMAP, TR_NATPMP_SEND_UNMAP,
TR_NATPMP_RECV_UNMAP TR_NATPMP_RECV_UNMAP
} } tr_natpmp_state;
tr_natpmp_state;
struct tr_natpmp struct tr_natpmp
{ {
@ -74,7 +73,13 @@ static void logVal(char const* func, int ret)
} }
else else
{ {
tr_logAddNamedDbg(getKey(), "%s failed. Natpmp returned %d (%s); errno is %d (%s)", func, ret, strnatpmperr(ret), errno, tr_logAddNamedDbg(
getKey(),
"%s failed. Natpmp returned %d (%s); errno is %d (%s)",
func,
ret,
strnatpmperr(ret),
errno,
tr_strerror(errno)); tr_strerror(errno));
} }
} }
@ -144,8 +149,7 @@ int tr_natpmpPulse(struct tr_natpmp* nat, tr_port private_port, bool is_enabled,
} }
} }
if ((nat->state == TR_NATPMP_IDLE || nat->state == TR_NATPMP_ERR) && if ((nat->state == TR_NATPMP_IDLE || nat->state == TR_NATPMP_ERR) && (nat->is_mapped) &&
(nat->is_mapped) &&
(!is_enabled || nat->private_port != private_port)) (!is_enabled || nat->private_port != private_port))
{ {
nat->state = TR_NATPMP_SEND_UNMAP; nat->state = TR_NATPMP_SEND_UNMAP;

View File

@ -49,19 +49,17 @@
#include "utils.h" /* tr_time(), tr_logAddDebug() */ #include "utils.h" /* tr_time(), tr_logAddDebug() */
#ifndef IN_MULTICAST #ifndef IN_MULTICAST
#define IN_MULTICAST(a) (((a) & 0xf0000000) == 0xe0000000) #define IN_MULTICAST(a) (((a)&0xf0000000) == 0xe0000000)
#endif #endif
tr_address const tr_in6addr_any = tr_address const tr_in6addr_any = {
{
.type = TR_AF_INET6, .type = TR_AF_INET6,
.addr.addr6 = IN6ADDR_ANY_INIT .addr.addr6 = IN6ADDR_ANY_INIT,
}; };
tr_address const tr_inaddr_any = tr_address const tr_inaddr_any = {
{
.type = TR_AF_INET, .type = TR_AF_INET,
.addr.addr4.s_addr = INADDR_ANY .addr.addr4.s_addr = INADDR_ANY,
}; };
char* tr_net_strerror(char* buf, size_t buflen, int err) char* tr_net_strerror(char* buf, size_t buflen, int err)
@ -153,9 +151,8 @@ int tr_address_compare(tr_address const* a, tr_address const* b)
return a->type == TR_AF_INET ? 1 : -1; return a->type == TR_AF_INET ? 1 : -1;
} }
return a->type == TR_AF_INET ? return a->type == TR_AF_INET ? memcmp(&a->addr.addr4, &b->addr.addr4, sizeof(a->addr.addr4)) :
memcmp(&a->addr.addr4, &b->addr.addr4, sizeof(a->addr.addr4)) : memcmp(&a->addr.addr6.s6_addr, &b->addr.addr6.s6_addr, sizeof(a->addr.addr6.s6_addr));
memcmp(&a->addr.addr6.s6_addr, &b->addr.addr6.s6_addr, sizeof(a->addr.addr6.s6_addr));
} }
/*********************************************************************** /***********************************************************************
@ -213,8 +210,11 @@ void tr_netSetCongestionControl(tr_socket_t s, char const* algorithm)
if (setsockopt(s, IPPROTO_TCP, TCP_CONGESTION, (void const*)algorithm, strlen(algorithm) + 1) == -1) if (setsockopt(s, IPPROTO_TCP, TCP_CONGESTION, (void const*)algorithm, strlen(algorithm) + 1) == -1)
{ {
char err_buf[512]; char err_buf[512];
tr_logAddNamedInfo("Net", "Can't set congestion control algorithm '%s': %s", algorithm, tr_net_strerror(err_buf, tr_logAddNamedInfo(
sizeof(err_buf), sockerrno)); "Net",
"Can't set congestion control algorithm '%s': %s",
algorithm,
tr_net_strerror(err_buf, sizeof(err_buf), sockerrno));
} }
#else #else
@ -309,7 +309,9 @@ struct tr_peer_socket tr_netOpenPeerSocket(tr_session* session, tr_address const
if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, (void const*)&n, sizeof(n)) == -1) if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, (void const*)&n, sizeof(n)) == -1)
{ {
tr_logAddInfo("Unable to set SO_RCVBUF on socket %" PRIdMAX ": %s", (intmax_t)s, tr_logAddInfo(
"Unable to set SO_RCVBUF on socket %" PRIdMAX ": %s",
(intmax_t)s,
tr_net_strerror(err_buf, sizeof(err_buf), sockerrno)); tr_net_strerror(err_buf, sizeof(err_buf), sockerrno));
} }
} }
@ -329,7 +331,10 @@ struct tr_peer_socket tr_netOpenPeerSocket(tr_session* session, tr_address const
if (bind(s, (struct sockaddr*)&source_sock, sourcelen) == -1) if (bind(s, (struct sockaddr*)&source_sock, sourcelen) == -1)
{ {
tr_logAddError(_("Couldn't set source address %s on %" PRIdMAX ": %s"), tr_address_to_string(source_addr), (intmax_t)s, tr_logAddError(
_("Couldn't set source address %s on %" PRIdMAX ": %s"),
tr_address_to_string(source_addr),
(intmax_t)s,
tr_net_strerror(err_buf, sizeof(err_buf), sockerrno)); tr_net_strerror(err_buf, sizeof(err_buf), sockerrno));
tr_netClose(session, s); tr_netClose(session, s);
return ret; return ret;
@ -345,8 +350,13 @@ struct tr_peer_socket tr_netOpenPeerSocket(tr_session* session, tr_address const
if ((tmperrno != ENETUNREACH && tmperrno != EHOSTUNREACH) || addr->type == TR_AF_INET) if ((tmperrno != ENETUNREACH && tmperrno != EHOSTUNREACH) || addr->type == TR_AF_INET)
{ {
tr_logAddError(_("Couldn't connect socket %" PRIdMAX " to %s, port %d (errno %d - %s)"), (intmax_t)s, tr_logAddError(
tr_address_to_string(addr), (int)ntohs(port), tmperrno, tr_net_strerror(err_buf, sizeof(err_buf), tmperrno)); _("Couldn't connect socket %" PRIdMAX " to %s, port %d (errno %d - %s)"),
(intmax_t)s,
tr_address_to_string(addr),
(int)ntohs(port),
tmperrno,
tr_net_strerror(err_buf, sizeof(err_buf), tmperrno));
} }
tr_netClose(session, s); tr_netClose(session, s);

View File

@ -83,8 +83,7 @@ typedef enum tr_address_type
TR_AF_INET, TR_AF_INET,
TR_AF_INET6, TR_AF_INET6,
NUM_TR_AF_INET_TYPES NUM_TR_AF_INET_TYPES
} } tr_address_type;
tr_address_type;
typedef struct tr_address typedef struct tr_address
{ {
@ -93,10 +92,8 @@ typedef struct tr_address
{ {
struct in6_addr addr6; struct in6_addr addr6;
struct in_addr addr4; struct in_addr addr4;
} } addr;
addr; } tr_address;
}
tr_address;
extern tr_address const tr_inaddr_any; extern tr_address const tr_inaddr_any;
extern tr_address const tr_in6addr_any; extern tr_address const tr_in6addr_any;

View File

@ -52,8 +52,7 @@ typedef enum
TR_PEER_CLIENT_GOT_HAVE_NONE, TR_PEER_CLIENT_GOT_HAVE_NONE,
TR_PEER_PEER_GOT_PIECE_DATA, TR_PEER_PEER_GOT_PIECE_DATA,
TR_PEER_ERROR TR_PEER_ERROR
} } PeerEventType;
PeerEventType;
typedef struct typedef struct
{ {
@ -65,20 +64,19 @@ typedef struct
uint32_t length; /* for GOT_BLOCK + GOT_PIECE_DATA */ uint32_t length; /* for GOT_BLOCK + GOT_PIECE_DATA */
int err; /* errno for GOT_ERROR */ int err; /* errno for GOT_ERROR */
tr_port port; /* for GOT_PORT */ tr_port port; /* for GOT_PORT */
} } tr_peer_event;
tr_peer_event;
extern tr_peer_event const TR_PEER_EVENT_INIT; extern tr_peer_event const TR_PEER_EVENT_INIT;
typedef void (* tr_peer_callback)(struct tr_peer* peer, tr_peer_event const* event, void* client_data); typedef void (*tr_peer_callback)(struct tr_peer* peer, tr_peer_event const* event, void* client_data);
/*** /***
**** ****
***/ ***/
typedef void (* tr_peer_destruct_func)(struct tr_peer* peer); typedef void (*tr_peer_destruct_func)(struct tr_peer* peer);
typedef bool (* tr_peer_is_transferring_pieces_func)(struct tr_peer const* peer, uint64_t now, tr_direction direction, typedef bool (
unsigned int* Bps); *tr_peer_is_transferring_pieces_func)(struct tr_peer const* peer, uint64_t now, tr_direction direction, unsigned int* Bps);
struct tr_peer_virtual_funcs struct tr_peer_virtual_funcs
{ {
@ -129,8 +127,7 @@ typedef struct tr_peer
tr_recentHistory cancelsSentToPeer; tr_recentHistory cancelsSentToPeer;
struct tr_peer_virtual_funcs const* funcs; struct tr_peer_virtual_funcs const* funcs;
} } tr_peer;
tr_peer;
void tr_peerConstruct(struct tr_peer* peer, tr_torrent const* tor); void tr_peerConstruct(struct tr_peer* peer, tr_torrent const* tor);
@ -151,8 +148,7 @@ typedef struct tr_swarm_stats
int activeWebseedCount; int activeWebseedCount;
int peerCount; int peerCount;
int peerFromCount[TR_PEER_FROM__MAX]; int peerFromCount[TR_PEER_FROM__MAX];
} } tr_swarm_stats;
tr_swarm_stats;
extern tr_swarm_stats const TR_SWARM_STATS_INIT; extern tr_swarm_stats const TR_SWARM_STATS_INIT;

View File

@ -71,11 +71,12 @@ static size_t guessPacketOverhead(size_t d)
**/ **/
#define dbgmsg(io, ...) \ #define dbgmsg(io, ...) \
do { \ do \
{ \
char addrstr[TR_ADDRSTRLEN]; \ char addrstr[TR_ADDRSTRLEN]; \
tr_peerIoGetAddrStr(io, addrstr, sizeof(addrstr)); \ tr_peerIoGetAddrStr(io, addrstr, sizeof(addrstr)); \
tr_logAddDeepNamed(addrstr, __VA_ARGS__); \ tr_logAddDeepNamed(addrstr, __VA_ARGS__); \
} while(0) } while (0)
/** /**
*** ***
@ -90,11 +91,10 @@ struct tr_datatype
static struct tr_datatype* datatype_pool = NULL; static struct tr_datatype* datatype_pool = NULL;
static struct tr_datatype const TR_DATATYPE_INIT = static struct tr_datatype const TR_DATATYPE_INIT = {
{
.next = NULL, .next = NULL,
.length = 0, .length = 0,
.isPieceData = false .isPieceData = false,
}; };
static struct tr_datatype* datatype_new(void) static struct tr_datatype* datatype_new(void)
@ -329,7 +329,12 @@ static void event_read_cb(evutil_socket_t fd, short event, void* vio)
what |= BEV_EVENT_ERROR; what |= BEV_EVENT_ERROR;
} }
dbgmsg(io, "event_read_cb got an error. res is %d, what is %hd, errno is %d (%s)", res, what, e, dbgmsg(
io,
"event_read_cb got an error. res is %d, what is %hd, errno is %d (%s)",
res,
what,
e,
tr_net_strerror(errstr, sizeof(errstr), e)); tr_net_strerror(errstr, sizeof(errstr), e));
if (io->gotError != NULL) if (io->gotError != NULL)
@ -577,14 +582,13 @@ static void utp_on_overhead(void* closure, uint8_t /* bool */ send, size_t count
tr_bandwidthUsed(&io->bandwidth, send ? TR_UP : TR_DOWN, count, false, tr_time_msec()); tr_bandwidthUsed(&io->bandwidth, send ? TR_UP : TR_DOWN, count, false, tr_time_msec());
} }
static struct UTPFunctionTable utp_function_table = static struct UTPFunctionTable utp_function_table = {
{
.on_read = utp_on_read, .on_read = utp_on_read,
.on_write = utp_on_write, .on_write = utp_on_write,
.get_rb_size = utp_get_rb_size, .get_rb_size = utp_get_rb_size,
.on_state = utp_on_state_change, .on_state = utp_on_state_change,
.on_error = utp_on_error, .on_error = utp_on_error,
.on_overhead = utp_on_overhead .on_overhead = utp_on_overhead,
}; };
/* Dummy UTP callbacks. */ /* Dummy UTP callbacks. */
@ -638,20 +642,26 @@ static void dummy_on_overhead(void* closure, uint8_t /* bool */ send, size_t cou
TR_UNUSED(type); TR_UNUSED(type);
} }
static struct UTPFunctionTable dummy_utp_function_table = static struct UTPFunctionTable dummy_utp_function_table = {
{
.on_read = dummy_read, .on_read = dummy_read,
.on_write = dummy_write, .on_write = dummy_write,
.get_rb_size = dummy_get_rb_size, .get_rb_size = dummy_get_rb_size,
.on_state = dummy_on_state_change, .on_state = dummy_on_state_change,
.on_error = dummy_on_error, .on_error = dummy_on_error,
.on_overhead = dummy_on_overhead .on_overhead = dummy_on_overhead,
}; };
#endif /* #ifdef WITH_UTP */ #endif /* #ifdef WITH_UTP */
static tr_peerIo* tr_peerIoNew(tr_session* session, tr_bandwidth* parent, tr_address const* addr, tr_port port, static tr_peerIo* tr_peerIoNew(
uint8_t const* torrentHash, bool isIncoming, bool isSeed, struct tr_peer_socket const socket) tr_session* session,
tr_bandwidth* parent,
tr_address const* addr,
tr_port port,
uint8_t const* torrentHash,
bool isIncoming,
bool isSeed,
struct tr_peer_socket const socket)
{ {
TR_ASSERT(session != NULL); TR_ASSERT(session != NULL);
TR_ASSERT(session->events != NULL); TR_ASSERT(session->events != NULL);
@ -719,7 +729,11 @@ static tr_peerIo* tr_peerIoNew(tr_session* session, tr_bandwidth* parent, tr_add
return io; return io;
} }
tr_peerIo* tr_peerIoNewIncoming(tr_session* session, tr_bandwidth* parent, tr_address const* addr, tr_port port, tr_peerIo* tr_peerIoNewIncoming(
tr_session* session,
tr_bandwidth* parent,
tr_address const* addr,
tr_port port,
struct tr_peer_socket const socket) struct tr_peer_socket const socket)
{ {
TR_ASSERT(session != NULL); TR_ASSERT(session != NULL);
@ -728,8 +742,14 @@ tr_peerIo* tr_peerIoNewIncoming(tr_session* session, tr_bandwidth* parent, tr_ad
return tr_peerIoNew(session, parent, addr, port, NULL, true, false, socket); return tr_peerIoNew(session, parent, addr, port, NULL, true, false, socket);
} }
tr_peerIo* tr_peerIoNewOutgoing(tr_session* session, tr_bandwidth* parent, tr_address const* addr, tr_port port, tr_peerIo* tr_peerIoNewOutgoing(
uint8_t const* torrentHash, bool isSeed, bool utp) tr_session* session,
tr_bandwidth* parent,
tr_address const* addr,
tr_port port,
uint8_t const* torrentHash,
bool isSeed,
bool utp)
{ {
TR_ASSERT(session != NULL); TR_ASSERT(session != NULL);
TR_ASSERT(tr_address_is_valid(addr)); TR_ASSERT(tr_address_is_valid(addr));
@ -745,8 +765,10 @@ tr_peerIo* tr_peerIoNewOutgoing(tr_session* session, tr_bandwidth* parent, tr_ad
if (socket.type == TR_PEER_SOCKET_TYPE_NONE) if (socket.type == TR_PEER_SOCKET_TYPE_NONE)
{ {
socket = tr_netOpenPeerSocket(session, addr, port, isSeed); socket = tr_netOpenPeerSocket(session, addr, port, isSeed);
dbgmsg(NULL, "tr_netOpenPeerSocket returned fd %" PRIdMAX, (intmax_t)(socket.type != TR_PEER_SOCKET_TYPE_NONE ? dbgmsg(
socket.handle.tcp : TR_BAD_SOCKET)); NULL,
"tr_netOpenPeerSocket returned fd %" PRIdMAX,
(intmax_t)(socket.type != TR_PEER_SOCKET_TYPE_NONE ? socket.handle.tcp : TR_BAD_SOCKET));
} }
if (socket.type == TR_PEER_SOCKET_TYPE_NONE) if (socket.type == TR_PEER_SOCKET_TYPE_NONE)
@ -1121,8 +1143,12 @@ void tr_peerIoSetEncryption(tr_peerIo* io, tr_encryption_type encryption_type)
*** ***
**/ **/
static inline void processBuffer(tr_crypto* crypto, struct evbuffer* buffer, size_t offset, size_t size, void (* callback)( static inline void processBuffer(
tr_crypto*, size_t, void const*, void*)) tr_crypto* crypto,
struct evbuffer* buffer,
size_t offset,
size_t size,
void (*callback)(tr_crypto*, size_t, void const*, void*))
{ {
struct evbuffer_ptr pos; struct evbuffer_ptr pos;
struct evbuffer_iovec iovec; struct evbuffer_iovec iovec;
@ -1140,8 +1166,7 @@ static inline void processBuffer(tr_crypto* crypto, struct evbuffer* buffer, siz
TR_ASSERT(size >= iovec.iov_len); TR_ASSERT(size >= iovec.iov_len);
size -= iovec.iov_len; size -= iovec.iov_len;
} } while (evbuffer_ptr_set(buffer, &pos, iovec.iov_len, EVBUFFER_PTR_ADD) == 0);
while (evbuffer_ptr_set(buffer, &pos, iovec.iov_len, EVBUFFER_PTR_ADD) == 0);
TR_ASSERT(size == 0); TR_ASSERT(size == 0);
} }
@ -1343,7 +1368,12 @@ static int tr_peerIoTryRead(tr_peerIo* io, size_t howmuch)
what |= BEV_EVENT_EOF; what |= BEV_EVENT_EOF;
} }
dbgmsg(io, "tr_peerIoTryRead got an error. res is %d, what is %hd, errno is %d (%s)", res, what, e, dbgmsg(
io,
"tr_peerIoTryRead got an error. res is %d, what is %hd, errno is %d (%s)",
res,
what,
e,
tr_net_strerror(err_buf, sizeof(err_buf), e)); tr_net_strerror(err_buf, sizeof(err_buf), e));
io->gotError(io, what, io->userData); io->gotError(io, what, io->userData);
@ -1398,7 +1428,12 @@ static int tr_peerIoTryWrite(tr_peerIo* io, size_t howmuch)
char errstr[512]; char errstr[512];
short const what = BEV_EVENT_WRITING | BEV_EVENT_ERROR; short const what = BEV_EVENT_WRITING | BEV_EVENT_ERROR;
dbgmsg(io, "tr_peerIoTryWrite got an error. res is %d, what is %hd, errno is %d (%s)", n, what, e, dbgmsg(
io,
"tr_peerIoTryWrite got an error. res is %d, what is %hd, errno is %d (%s)",
n,
what,
e,
tr_net_strerror(errstr, sizeof(errstr), e)); tr_net_strerror(errstr, sizeof(errstr), e));
io->gotError(io, what, io->userData); io->gotError(io, what, io->userData);

View File

@ -40,22 +40,20 @@ typedef enum
READ_NOW, READ_NOW,
READ_LATER, READ_LATER,
READ_ERR READ_ERR
} } ReadState;
ReadState;
typedef enum typedef enum
{ {
/* these match the values in MSE's crypto_select */ /* these match the values in MSE's crypto_select */
PEER_ENCRYPTION_NONE = (1 << 0), PEER_ENCRYPTION_NONE = (1 << 0),
PEER_ENCRYPTION_RC4 = (1 << 1) PEER_ENCRYPTION_RC4 = (1 << 1)
} } tr_encryption_type;
tr_encryption_type;
typedef ReadState (* tr_can_read_cb)(struct tr_peerIo* io, void* user_data, size_t* setme_piece_byte_count); typedef ReadState (*tr_can_read_cb)(struct tr_peerIo* io, void* user_data, size_t* setme_piece_byte_count);
typedef void (* tr_did_write_cb)(struct tr_peerIo* io, size_t bytesWritten, bool wasPieceData, void* userData); typedef void (*tr_did_write_cb)(struct tr_peerIo* io, size_t bytesWritten, bool wasPieceData, void* userData);
typedef void (* tr_net_error_cb)(struct tr_peerIo* io, short what, void* userData); typedef void (*tr_net_error_cb)(struct tr_peerIo* io, short what, void* userData);
typedef struct tr_peerIo typedef struct tr_peerIo
{ {
@ -102,17 +100,26 @@ typedef struct tr_peerIo
struct event* event_read; struct event* event_read;
struct event* event_write; struct event* event_write;
} } tr_peerIo;
tr_peerIo;
/** /**
*** ***
**/ **/
tr_peerIo* tr_peerIoNewOutgoing(tr_session* session, struct tr_bandwidth* parent, struct tr_address const* addr, tr_port port, tr_peerIo* tr_peerIoNewOutgoing(
uint8_t const* torrentHash, bool isSeed, bool utp); tr_session* session,
struct tr_bandwidth* parent,
struct tr_address const* addr,
tr_port port,
uint8_t const* torrentHash,
bool isSeed,
bool utp);
tr_peerIo* tr_peerIoNewIncoming(tr_session* session, struct tr_bandwidth* parent, struct tr_address const* addr, tr_port port, tr_peerIo* tr_peerIoNewIncoming(
tr_session* session,
struct tr_bandwidth* parent,
struct tr_address const* addr,
tr_port port,
struct tr_peer_socket const socket); struct tr_peer_socket const socket);
void tr_peerIoRefImpl(char const* file, int line, tr_peerIo* io); void tr_peerIoRefImpl(char const* file, int line, tr_peerIo* io);

View File

@ -82,23 +82,21 @@ enum
CANCEL_HISTORY_SEC = 60 CANCEL_HISTORY_SEC = 60
}; };
tr_peer_event const TR_PEER_EVENT_INIT = tr_peer_event const TR_PEER_EVENT_INIT = {
{
.eventType = TR_PEER_CLIENT_GOT_BLOCK, .eventType = TR_PEER_CLIENT_GOT_BLOCK,
.pieceIndex = 0, .pieceIndex = 0,
.bitfield = NULL, .bitfield = NULL,
.offset = 0, .offset = 0,
.length = 0, .length = 0,
.err = 0, .err = 0,
.port = 0 .port = 0,
}; };
tr_swarm_stats const TR_SWARM_STATS_INIT = tr_swarm_stats const TR_SWARM_STATS_INIT = {
{
.activePeerCount = { 0, 0 }, .activePeerCount = { 0, 0 },
.activeWebseedCount = 0, .activeWebseedCount = 0,
.peerCount = 0, .peerCount = 0,
.peerFromCount = { 0, 0, 0, 0, 0, 0, 0 } .peerFromCount = { 0, 0, 0, 0, 0, 0, 0 },
}; };
/** /**
@ -156,9 +154,7 @@ static bool tr_isAtom(struct peer_atom const* atom)
static char const* tr_atomAddrStr(struct peer_atom const* atom) static char const* tr_atomAddrStr(struct peer_atom const* atom)
{ {
static char addrstr[TR_ADDRSTRLEN]; static char addrstr[TR_ADDRSTRLEN];
return atom != NULL ? return atom != NULL ? tr_address_and_port_to_string(addrstr, sizeof(addrstr), &atom->addr, atom->port) : "[no atom]";
tr_address_and_port_to_string(addrstr, sizeof(addrstr), &atom->addr, atom->port) :
"[no atom]";
} }
struct block_request struct block_request
@ -225,8 +221,7 @@ typedef struct tr_swarm
* requests are considered 'fast' are allowed to request a block that's * requests are considered 'fast' are allowed to request a block that's
* already been requested from another (slower?) peer. */ * already been requested from another (slower?) peer. */
int endgame; int endgame;
} } tr_swarm;
tr_swarm;
struct tr_peerMgr struct tr_peerMgr
{ {
@ -735,8 +730,8 @@ static void requestListAdd(tr_swarm* s, tr_block_index_t block, tr_peer* peer)
/* insert the request to our array... */ /* insert the request to our array... */
{ {
bool exact; bool exact;
int const pos = tr_lowerBound(&key, s->requests, s->requestCount, sizeof(struct block_request), compareReqByBlock, int const
&exact); pos = tr_lowerBound(&key, s->requests, s->requestCount, sizeof(struct block_request), compareReqByBlock, &exact);
TR_ASSERT(!exact); TR_ASSERT(!exact);
memmove(s->requests + pos + 1, s->requests + pos, sizeof(struct block_request) * (s->requestCount++ - pos)); memmove(s->requests + pos + 1, s->requests + pos, sizeof(struct block_request) * (s->requestCount++ - pos));
s->requests[pos] = key; s->requests[pos] = key;
@ -787,8 +782,7 @@ static void getBlockRequestPeers(tr_swarm* s, tr_block_index_t block, tr_ptrArra
static void decrementPendingReqCount(struct block_request const* b) static void decrementPendingReqCount(struct block_request const* b)
{ {
if ((b->peer != NULL) && if ((b->peer != NULL) && (b->peer->pendingReqsToPeer > 0))
(b->peer->pendingReqsToPeer > 0))
{ {
--b->peer->pendingReqsToPeer; --b->peer->pendingReqsToPeer;
} }
@ -1335,7 +1329,12 @@ void tr_peerMgrRebuildRequests(tr_torrent* tor)
pieceListRebuild(tor->swarm); pieceListRebuild(tor->swarm);
} }
void tr_peerMgrGetNextRequests(tr_torrent* tor, tr_peer* peer, int numwant, tr_block_index_t* setme, int* numgot, void tr_peerMgrGetNextRequests(
tr_torrent* tor,
tr_peer* peer,
int numwant,
tr_block_index_t* setme,
int* numgot,
bool get_intervals) bool get_intervals)
{ {
/* sanity clause */ /* sanity clause */
@ -1382,7 +1381,7 @@ void tr_peerMgrGetNextRequests(tr_torrent* tor, tr_peer* peer, int numwant, tr_b
tr_torGetPieceBlockRange(tor, p->index, &first, &last); tr_torGetPieceBlockRange(tor, p->index, &first, &last);
for (tr_block_index_t b = first; b <= last && (got < numwant || (get_intervals && setme[2 * got - 1] == b - 1)); for (tr_block_index_t b = first; b <= last && (got < numwant || (get_intervals && setme[2 * got - 1] == b - 1));
++b) ++b)
{ {
int peerCount; int peerCount;
tr_peer** peers; tr_peer** peers;
@ -1474,8 +1473,13 @@ void tr_peerMgrGetNextRequests(tr_torrent* tor, tr_peer* peer, int numwant, tr_b
bool exact; bool exact;
/* relative position! */ /* relative position! */
int const newpos = tr_lowerBound(&s->pieces[i], &s->pieces[i + 1], s->pieceCount - (i + 1), int const newpos = tr_lowerBound(
sizeof(struct weighted_piece), comparePieceByWeight, &exact); &s->pieces[i],
&s->pieces[i + 1],
s->pieceCount - (i + 1),
sizeof(struct weighted_piece),
comparePieceByWeight,
&exact);
if (newpos > 0) if (newpos > 0)
{ {
@ -1887,8 +1891,10 @@ static void peerCallbackFunc(tr_peer* peer, tr_peer_event const* e, void* vs)
{ {
/* some protocol error from the peer */ /* some protocol error from the peer */
peer->doPurge = true; peer->doPurge = true;
tordbg(s, "setting %s doPurge flag because we got an ERANGE, EMSGSIZE, or ENOTCONN error", tr_atomAddrStr( tordbg(
peer->atom)); s,
"setting %s doPurge flag because we got an ERANGE, EMSGSIZE, or ENOTCONN error",
tr_atomAddrStr(peer->atom));
} }
else else
{ {
@ -1936,8 +1942,13 @@ static int getDefaultShelfLife(uint8_t from)
} }
} }
static void ensureAtomExists(tr_swarm* s, tr_address const* addr, tr_port const port, uint8_t const flags, static void ensureAtomExists(
int8_t const seedProbability, uint8_t const from) tr_swarm* s,
tr_address const* addr,
tr_port const port,
uint8_t const flags,
int8_t const seedProbability,
uint8_t const from)
{ {
TR_ASSERT(tr_address_is_valid(addr)); TR_ASSERT(tr_address_is_valid(addr));
TR_ASSERT(from < TR_PEER_FROM__MAX); TR_ASSERT(from < TR_PEER_FROM__MAX);
@ -2012,8 +2023,13 @@ static void createBitTorrentPeer(tr_torrent* tor, struct tr_peerIo* io, struct p
} }
/* FIXME: this is kind of a mess. */ /* FIXME: this is kind of a mess. */
static bool myHandshakeDoneCB(tr_handshake* handshake, tr_peerIo* io, bool readAnythingFromPeer, bool isConnected, static bool myHandshakeDoneCB(
uint8_t const* peer_id, void* vmanager) tr_handshake* handshake,
tr_peerIo* io,
bool readAnythingFromPeer,
bool isConnected,
uint8_t const* peer_id,
void* vmanager)
{ {
TR_ASSERT(io != NULL); TR_ASSERT(io != NULL);
@ -2114,7 +2130,8 @@ static bool myHandshakeDoneCB(tr_handshake* handshake, tr_peerIo* io, bool readA
client = TR_KEY_NONE; client = TR_KEY_NONE;
} }
tr_peerIo* stolen = tr_handshakeStealIO(handshake); /* this steals its refcount too, which is balanced by our unref in peerDelete() */ /* this steals its refcount too, which is balanced by our unref in peerDelete() */
tr_peerIo* stolen = tr_handshakeStealIO(handshake);
tr_peerIoSetParent(stolen, &s->tor->bandwidth); tr_peerIoSetParent(stolen, &s->tor->bandwidth);
createBitTorrentPeer(s->tor, stolen, atom, client); createBitTorrentPeer(s->tor, stolen, atom, client);
@ -2206,7 +2223,11 @@ void tr_peerMgrAddPex(tr_torrent* tor, uint8_t from, tr_pex const* pex, int8_t s
} }
} }
tr_pex* tr_peerMgrCompactToPex(void const* compact, size_t compactLen, uint8_t const* added_f, size_t added_f_len, tr_pex* tr_peerMgrCompactToPex(
void const* compact,
size_t compactLen,
uint8_t const* added_f,
size_t added_f_len,
size_t* pexCount) size_t* pexCount)
{ {
size_t n = compactLen / 6; size_t n = compactLen / 6;
@ -2231,7 +2252,11 @@ tr_pex* tr_peerMgrCompactToPex(void const* compact, size_t compactLen, uint8_t c
return pex; return pex;
} }
tr_pex* tr_peerMgrCompact6ToPex(void const* compact, size_t compactLen, uint8_t const* added_f, size_t added_f_len, tr_pex* tr_peerMgrCompact6ToPex(
void const* compact,
size_t compactLen,
uint8_t const* added_f,
size_t added_f_len,
size_t* pexCount) size_t* pexCount)
{ {
size_t n = compactLen / 18; size_t n = compactLen / 18;
@ -2271,7 +2296,11 @@ void tr_peerMgrGotBadPiece(tr_torrent* tor, tr_piece_index_t pieceIndex)
if (tr_bitfieldHas(&peer->blame, pieceIndex)) if (tr_bitfieldHas(&peer->blame, pieceIndex))
{ {
tordbg(s, "peer %s contributed to corrupt piece (%d); now has %d strikes", tr_atomAddrStr(peer->atom), pieceIndex, tordbg(
s,
"peer %s contributed to corrupt piece (%d); now has %d strikes",
tr_atomAddrStr(peer->atom),
pieceIndex,
(int)peer->strikes + 1); (int)peer->strikes + 1);
addStrike(s, peer); addStrike(s, peer);
} }
@ -2932,8 +2961,7 @@ typedef enum
RECHOKE_STATE_GOOD, RECHOKE_STATE_GOOD,
RECHOKE_STATE_UNTESTED, RECHOKE_STATE_UNTESTED,
RECHOKE_STATE_BAD RECHOKE_STATE_BAD
} } tr_rechoke_state;
tr_rechoke_state;
struct tr_rechoke_info struct tr_rechoke_info
{ {
@ -3018,7 +3046,10 @@ static void rechokeDownloads(tr_swarm* s)
double const cancelRate = cancels / (double)(cancels + blocks); double const cancelRate = cancels / (double)(cancels + blocks);
double const mult = 1 - MIN(cancelRate, 0.5); double const mult = 1 - MIN(cancelRate, 0.5);
maxPeers = s->interestedCount * mult; maxPeers = s->interestedCount * mult;
tordbg(s, "cancel rate is %.3f -- reducing the number of peers we're interested in by %.0f percent", cancelRate, tordbg(
s,
"cancel rate is %.3f -- reducing the number of peers we're interested in by %.0f percent",
cancelRate,
mult * 100); mult * 100);
s->lastCancel = now; s->lastCancel = now;
} }
@ -3032,8 +3063,11 @@ static void rechokeDownloads(tr_swarm* s)
double const mult = MIN(timeSinceCancel, maxHistory) / (double)maxHistory; double const mult = MIN(timeSinceCancel, maxHistory) / (double)maxHistory;
int const inc = maxIncrease * mult; int const inc = maxIncrease * mult;
maxPeers = s->maxPeers + inc; maxPeers = s->maxPeers + inc;
tordbg(s, "time since last cancel is %jd -- increasing the number of peers we're interested in by %d", tordbg(
(intmax_t)timeSinceCancel, inc); s,
"time since last cancel is %jd -- increasing the number of peers we're interested in by %d",
(intmax_t)timeSinceCancel,
inc);
} }
} }
@ -3189,8 +3223,8 @@ static int getRate(tr_torrent const* tor, struct peer_atom* atom, uint64_t now)
* because there may only be a small window of opportunity to share */ * because there may only be a small window of opportunity to share */
else if (tr_torrentIsPrivate(tor)) else if (tr_torrentIsPrivate(tor))
{ {
Bps = tr_peerGetPieceSpeed_Bps(atom->peer, now, TR_PEER_TO_CLIENT) + tr_peerGetPieceSpeed_Bps(atom->peer, now, Bps = tr_peerGetPieceSpeed_Bps(atom->peer, now, TR_PEER_TO_CLIENT) +
TR_CLIENT_TO_PEER); tr_peerGetPieceSpeed_Bps(atom->peer, now, TR_CLIENT_TO_PEER);
} }
/* downloading a public torrent */ /* downloading a public torrent */
else else
@ -3403,7 +3437,7 @@ static bool shouldPeerBeClosed(tr_swarm const* s, tr_peer const* peer, int peerC
/* if we have >= relaxIfFewerThan, strictness is 100%. /* if we have >= relaxIfFewerThan, strictness is 100%.
* if we have zero connections, strictness is 0% */ * if we have zero connections, strictness is 0% */
float const strictness = peerCount >= relaxStrictnessIfFewerThanN ? 1.0 : float const strictness = peerCount >= relaxStrictnessIfFewerThanN ? 1.0 :
peerCount / (float)relaxStrictnessIfFewerThanN; peerCount / (float)relaxStrictnessIfFewerThanN;
int const lo = MIN_UPLOAD_IDLE_SECS; int const lo = MIN_UPLOAD_IDLE_SECS;
int const hi = MAX_UPLOAD_IDLE_SECS; int const hi = MAX_UPLOAD_IDLE_SECS;
int const limit = hi - (hi - lo) * strictness; int const limit = hi - (hi - lo) * strictness;
@ -4324,8 +4358,14 @@ static void initiateConnection(tr_peerMgr* mgr, tr_swarm* s, struct peer_atom* a
tordbg(s, "Starting an OUTGOING%s connection with %s", utp ? " µTP" : "", tr_atomAddrStr(atom)); tordbg(s, "Starting an OUTGOING%s connection with %s", utp ? " µTP" : "", tr_atomAddrStr(atom));
io = tr_peerIoNewOutgoing(mgr->session, &mgr->session->bandwidth, &atom->addr, atom->port, s->tor->info.hash, io = tr_peerIoNewOutgoing(
s->tor->completeness == TR_SEED, utp); mgr->session,
&mgr->session->bandwidth,
&atom->addr,
atom->port,
s->tor->info.hash,
s->tor->completeness == TR_SEED,
utp);
if (io == NULL) if (io == NULL)
{ {

View File

@ -54,8 +54,7 @@ typedef struct tr_pex
tr_address addr; tr_address addr;
tr_port port; /* this field is in network byte order */ tr_port port; /* this field is in network byte order */
uint8_t flags; uint8_t flags;
} } tr_pex;
tr_pex;
struct peer_atom; struct peer_atom;
struct tr_peerIo; struct tr_peerIo;
@ -81,7 +80,12 @@ void tr_peerMgrSetUtpSupported(tr_torrent* tor, tr_address const* addr);
void tr_peerMgrSetUtpFailed(tr_torrent* tor, tr_address const* addr, bool failed); void tr_peerMgrSetUtpFailed(tr_torrent* tor, tr_address const* addr, bool failed);
void tr_peerMgrGetNextRequests(tr_torrent* torrent, tr_peer* peer, int numwant, tr_block_index_t* setme, int* numgot, void tr_peerMgrGetNextRequests(
tr_torrent* torrent,
tr_peer* peer,
int numwant,
tr_block_index_t* setme,
int* numgot,
bool get_intervals); bool get_intervals);
bool tr_peerMgrDidPeerRequest(tr_torrent const* torrent, tr_peer const* peer, tr_block_index_t block); bool tr_peerMgrDidPeerRequest(tr_torrent const* torrent, tr_peer const* peer, tr_block_index_t block);
@ -90,10 +94,18 @@ void tr_peerMgrRebuildRequests(tr_torrent* torrent);
void tr_peerMgrAddIncoming(tr_peerMgr* manager, tr_address* addr, tr_port port, struct tr_peer_socket const socket); void tr_peerMgrAddIncoming(tr_peerMgr* manager, tr_address* addr, tr_port port, struct tr_peer_socket const socket);
tr_pex* tr_peerMgrCompactToPex(void const* compact, size_t compactLen, uint8_t const* added_f, size_t added_f_len, tr_pex* tr_peerMgrCompactToPex(
void const* compact,
size_t compactLen,
uint8_t const* added_f,
size_t added_f_len,
size_t* setme_pex_count); size_t* setme_pex_count);
tr_pex* tr_peerMgrCompact6ToPex(void const* compact, size_t compactLen, uint8_t const* added_f, size_t added_f_len, tr_pex* tr_peerMgrCompact6ToPex(
void const* compact,
size_t compactLen,
uint8_t const* added_f,
size_t added_f_len,
size_t* pexCount); size_t* pexCount);
/** /**
@ -107,7 +119,11 @@ enum
TR_PEERS_INTERESTING TR_PEERS_INTERESTING
}; };
int tr_peerMgrGetPeers(tr_torrent const* tor, tr_pex** setme_pex, uint8_t address_type, uint8_t peer_list_mode, int tr_peerMgrGetPeers(
tr_torrent const* tor,
tr_pex** setme_pex,
uint8_t address_type,
uint8_t peer_list_mode,
int max_peer_count); int max_peer_count);
void tr_peerMgrStartTorrent(tr_torrent* tor); void tr_peerMgrStartTorrent(tr_torrent* tor);

View File

@ -110,8 +110,7 @@ typedef enum
ENCRYPTION_PREFERENCE_UNKNOWN, ENCRYPTION_PREFERENCE_UNKNOWN,
ENCRYPTION_PREFERENCE_YES, ENCRYPTION_PREFERENCE_YES,
ENCRYPTION_PREFERENCE_NO ENCRYPTION_PREFERENCE_NO
} } encryption_preference_t;
encryption_preference_t;
/** /**
*** ***
@ -269,7 +268,9 @@ static void myDebug(char const* file, int line, struct tr_peerMsgs const* msgs,
char* base = tr_sys_path_basename(file, NULL); char* base = tr_sys_path_basename(file, NULL);
char* message; char* message;
evbuffer_add_printf(buf, "[%s] %s - %s [%s]: ", evbuffer_add_printf(
buf,
"[%s] %s - %s [%s]: ",
tr_logGetTimeStr(timestr, sizeof(timestr)), tr_logGetTimeStr(timestr, sizeof(timestr)),
tr_torrentName(msgs->torrent), tr_torrentName(msgs->torrent),
tr_peerIoGetAddrStr(msgs->io, addrstr, sizeof(addrstr)), tr_peerIoGetAddrStr(msgs->io, addrstr, sizeof(addrstr)),
@ -294,8 +295,7 @@ static void myDebug(char const* file, int line, struct tr_peerMsgs const* msgs,
{ \ { \
myDebug(__FILE__, __LINE__, msgs, __VA_ARGS__); \ myDebug(__FILE__, __LINE__, msgs, __VA_ARGS__); \
} \ } \
} \ } while (0)
while (0)
/** /**
*** ***
@ -968,7 +968,7 @@ static void parseLtepHandshake(tr_peerMsgs* msgs, uint32_t len, struct evbuffer*
/* arbitrary limit, should be more than enough */ /* arbitrary limit, should be more than enough */
if (len <= 4096) if (len <= 4096)
{ {
dbgmsg(msgs, "here is the handshake: [%*.*s]", (int)len, (int)len, tmp); dbgmsg(msgs, "here is the handshake: [%*.*s]", TR_ARG_TUPLE((int)len, (int)len, tmp));
} }
else else
{ {
@ -1015,8 +1015,7 @@ static void parseLtepHandshake(tr_peerMsgs* msgs, uint32_t len, struct evbuffer*
} }
/* look for metainfo size (BEP 9) */ /* look for metainfo size (BEP 9) */
if (tr_variantDictFindInt(&val, TR_KEY_metadata_size, &i) && if (tr_variantDictFindInt(&val, TR_KEY_metadata_size, &i) && tr_torrentSetMetadataSizeHint(msgs->torrent, i))
tr_torrentSetMetadataSizeHint(msgs->torrent, i))
{ {
msgs->metadata_size_hint = (size_t)i; msgs->metadata_size_hint = (size_t)i;
} }
@ -1035,18 +1034,14 @@ static void parseLtepHandshake(tr_peerMsgs* msgs, uint32_t len, struct evbuffer*
dbgmsg(msgs, "peer's port is now %d", (int)i); dbgmsg(msgs, "peer's port is now %d", (int)i);
} }
if (tr_peerIoIsIncoming(msgs->io) && if (tr_peerIoIsIncoming(msgs->io) && tr_variantDictFindRaw(&val, TR_KEY_ipv4, &addr, &addr_len) && addr_len == 4)
tr_variantDictFindRaw(&val, TR_KEY_ipv4, &addr, &addr_len) &&
addr_len == 4)
{ {
pex.addr.type = TR_AF_INET; pex.addr.type = TR_AF_INET;
memcpy(&pex.addr.addr.addr4, addr, 4); memcpy(&pex.addr.addr.addr4, addr, 4);
tr_peerMgrAddPex(msgs->torrent, TR_PEER_FROM_LTEP, &pex, seedProbability); tr_peerMgrAddPex(msgs->torrent, TR_PEER_FROM_LTEP, &pex, seedProbability);
} }
if (tr_peerIoIsIncoming(msgs->io) && if (tr_peerIoIsIncoming(msgs->io) && tr_variantDictFindRaw(&val, TR_KEY_ipv6, &addr, &addr_len) && addr_len == 16)
tr_variantDictFindRaw(&val, TR_KEY_ipv6, &addr, &addr_len) &&
addr_len == 16)
{ {
pex.addr.type = TR_AF_INET6; pex.addr.type = TR_AF_INET6;
memcpy(&pex.addr.addr.addr6, addr, 16); memcpy(&pex.addr.addr.addr6, addr, 16);
@ -1483,7 +1478,13 @@ static int readBtPiece(tr_peerMsgs* msgs, struct evbuffer* inbuf, size_t inlen,
fireClientGotPieceData(msgs, n); fireClientGotPieceData(msgs, n);
*setme_piece_bytes_read += n; *setme_piece_bytes_read += n;
dbgmsg(msgs, "got %zu bytes for block %u:%u->%u ... %d remain", n, req->index, req->offset, req->length, dbgmsg(
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))); (int)(req->length - evbuffer_get_length(block_buffer)));
if (evbuffer_get_length(block_buffer) < req->length) if (evbuffer_get_length(block_buffer) < req->length)
@ -1624,7 +1625,10 @@ static int readBtMessage(tr_peerMsgs* msgs, struct evbuffer* inbuf, size_t inlen
if (req->index == r.index && req->offset == r.offset && req->length == r.length) if (req->index == r.index && req->offset == r.offset && req->length == r.length)
{ {
tr_removeElementFromArray(msgs->peerAskedFor, i, sizeof(struct peer_request), tr_removeElementFromArray(
msgs->peerAskedFor,
i,
sizeof(struct peer_request),
msgs->peer.pendingReqsToClient); msgs->peer.pendingReqsToClient);
--msgs->peer.pendingReqsToClient; --msgs->peer.pendingReqsToClient;
break; break;
@ -2104,8 +2108,13 @@ static size_t fillOutputBuffer(tr_peerMsgs* msgs, time_t now)
evbuffer_add_uint32(out, req.offset); evbuffer_add_uint32(out, req.offset);
evbuffer_reserve_space(out, req.length, iovec, 1); evbuffer_reserve_space(out, req.length, iovec, 1);
err = tr_cacheReadBlock(getSession(msgs)->cache, msgs->torrent, req.index, req.offset, req.length, err = tr_cacheReadBlock(
iovec[0].iov_base) != 0; getSession(msgs)->cache,
msgs->torrent,
req.index,
req.offset,
req.length,
iovec[0].iov_base) != 0;
iovec[0].iov_len = req.length; iovec[0].iov_len = req.length;
evbuffer_commit_space(out, iovec, 1); evbuffer_commit_space(out, iovec, 1);
@ -2116,7 +2125,9 @@ static size_t fillOutputBuffer(tr_peerMsgs* msgs, time_t now)
if (err) if (err)
{ {
tr_torrentSetLocalError(msgs->torrent, _("Please Verify Local Data! Piece #%zu is corrupt."), tr_torrentSetLocalError(
msgs->torrent,
_("Please Verify Local Data! Piece #%zu is corrupt."),
(size_t)req.index); (size_t)req.index);
} }
} }
@ -2272,8 +2283,7 @@ typedef struct
int addedCount; int addedCount;
int droppedCount; int droppedCount;
int elementCount; int elementCount;
} } PexDiffs;
PexDiffs;
static void pexAddedCb(void const* vpex, void* userData) static void pexAddedCb(void const* vpex, void* userData)
{ {
@ -2306,7 +2316,7 @@ static inline void pexElementCb(void const* vpex, void* userData)
diffs->elements[diffs->elementCount++] = *pex; diffs->elements[diffs->elementCount++] = *pex;
} }
typedef void (* tr_set_func)(void const* element, void* userData); typedef void (*tr_set_func)(void const* element, void* userData);
/** /**
* @brief find the differences and commonalities in two sorted sets * @brief find the differences and commonalities in two sorted sets
@ -2321,8 +2331,17 @@ typedef void (* tr_set_func)(void const* element, void* userData);
* @param in_both called for items that are in both sets * @param in_both called for items that are in both sets
* @param userData user data passed along to in_a, in_b, and in_both * @param userData user data passed along to in_a, in_b, and in_both
*/ */
static void tr_set_compare(void const* va, size_t aCount, void const* vb, size_t bCount, tr_voidptr_compare_func compare, static void tr_set_compare(
size_t elementSize, tr_set_func in_a_cb, tr_set_func in_b_cb, tr_set_func in_both_cb, void* userData) void const* va,
size_t aCount,
void const* vb,
size_t bCount,
tr_voidptr_compare_func compare,
size_t elementSize,
tr_set_func in_a_cb,
tr_set_func in_b_cb,
tr_set_func in_both_cb,
void* userData)
{ {
uint8_t const* a = va; uint8_t const* a = va;
uint8_t const* b = vb; uint8_t const* b = vb;
@ -2383,18 +2402,45 @@ static void sendPex(tr_peerMsgs* msgs)
diffs.droppedCount = 0; diffs.droppedCount = 0;
diffs.elements = tr_new(tr_pex, newCount + msgs->pexCount); diffs.elements = tr_new(tr_pex, newCount + msgs->pexCount);
diffs.elementCount = 0; diffs.elementCount = 0;
tr_set_compare(msgs->pex, msgs->pexCount, newPex, newCount, tr_pexCompare, sizeof(tr_pex), pexDroppedCb, pexAddedCb, tr_set_compare(
pexElementCb, &diffs); msgs->pex,
msgs->pexCount,
newPex,
newCount,
tr_pexCompare,
sizeof(tr_pex),
pexDroppedCb,
pexAddedCb,
pexElementCb,
&diffs);
diffs6.added = tr_new(tr_pex, newCount6); diffs6.added = tr_new(tr_pex, newCount6);
diffs6.addedCount = 0; diffs6.addedCount = 0;
diffs6.dropped = tr_new(tr_pex, msgs->pexCount6); diffs6.dropped = tr_new(tr_pex, msgs->pexCount6);
diffs6.droppedCount = 0; diffs6.droppedCount = 0;
diffs6.elements = tr_new(tr_pex, newCount6 + msgs->pexCount6); diffs6.elements = tr_new(tr_pex, newCount6 + msgs->pexCount6);
diffs6.elementCount = 0; diffs6.elementCount = 0;
tr_set_compare(msgs->pex6, msgs->pexCount6, newPex6, newCount6, tr_pexCompare, sizeof(tr_pex), pexDroppedCb, pexAddedCb, tr_set_compare(
pexElementCb, &diffs6); msgs->pex6,
dbgmsg(msgs, "pex: old peer count %d+%d, new peer count %d+%d, added %d+%d, removed %d+%d", msgs->pexCount, msgs->pexCount6,
msgs->pexCount6, newCount, newCount6, diffs.addedCount, diffs6.addedCount, diffs.droppedCount, diffs6.droppedCount); newPex6,
newCount6,
tr_pexCompare,
sizeof(tr_pex),
pexDroppedCb,
pexAddedCb,
pexElementCb,
&diffs6);
dbgmsg(
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);
if (diffs.addedCount == 0 && diffs.droppedCount == 0 && diffs6.addedCount == 0 && diffs6.droppedCount == 0) if (diffs.addedCount == 0 && diffs.droppedCount == 0 && diffs6.addedCount == 0 && diffs6.droppedCount == 0)
{ {
@ -2559,7 +2605,10 @@ static void pexPulse(evutil_socket_t fd, short what, void* vmsgs)
**** tr_peer virtual functions **** tr_peer virtual functions
***/ ***/
static bool peermsgs_is_transferring_pieces(struct tr_peer const* peer, uint64_t now, tr_direction direction, static bool peermsgs_is_transferring_pieces(
struct tr_peer const* peer,
uint64_t now,
tr_direction direction,
unsigned int* setme_Bps) unsigned int* setme_Bps)
{ {
unsigned int Bps = 0; unsigned int Bps = 0;
@ -2613,10 +2662,9 @@ static void peermsgs_destruct(tr_peer* peer)
} }
} }
static struct tr_peer_virtual_funcs const my_funcs = static struct tr_peer_virtual_funcs const my_funcs = {
{
.destruct = peermsgs_destruct, .destruct = peermsgs_destruct,
.is_transferring_pieces = peermsgs_is_transferring_pieces .is_transferring_pieces = peermsgs_is_transferring_pieces,
}; };
/*** /***

View File

@ -68,7 +68,11 @@ void tr_peerMsgsPulse(tr_peerMsgs* msgs);
void tr_peerMsgsCancel(tr_peerMsgs* msgs, tr_block_index_t block); 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, uint8_t const* infohash, size_t tr_generateAllowedSet(
tr_piece_index_t* setmePieces,
size_t desiredSetSize,
size_t pieceCount,
uint8_t const* infohash,
struct tr_address const* addr); struct tr_address const* addr);
/* @} */ /* @} */

View File

@ -326,8 +326,10 @@ static int64_t getquota(char const* device)
int64_t spaceused; int64_t spaceused;
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__APPLE__) #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__APPLE__)
if (quotactl(device, QCMD(Q_GETQUOTA, USRQUOTA), getuid(), (caddr_t)&dq) == 0) if (quotactl(device, QCMD(Q_GETQUOTA, USRQUOTA), getuid(), (caddr_t)&dq) != 0)
{ {
return -1;
}
#elif defined(__sun) #elif defined(__sun)
struct quotctl op; struct quotctl op;
int fd = open(device, O_RDONLY); int fd = open(device, O_RDONLY);
@ -341,55 +343,54 @@ static int64_t getquota(char const* device)
op.uid = getuid(); op.uid = getuid();
op.addr = (caddr_t)&dq; op.addr = (caddr_t)&dq;
if (ioctl(fd, Q_QUOTACTL, &op) == 0) if (ioctl(fd, Q_QUOTACTL, &op) != 0)
{ {
close(fd); close(fd);
#else return -1;
if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device, getuid(), (caddr_t)&dq) == 0)
{
#endif
if (dq.dqb_bsoftlimit > 0)
{
/* Use soft limit first */
limit = dq.dqb_bsoftlimit;
}
else if (dq.dqb_bhardlimit > 0)
{
limit = dq.dqb_bhardlimit;
}
else
{
/* No quota enabled for this user */
return -1;
}
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
spaceused = (int64_t)dq.dqb_curblocks >> 1;
#elif defined(__APPLE__)
spaceused = (int64_t)dq.dqb_curbytes;
#elif defined(__UCLIBC__) && !TR_UCLIBC_CHECK_VERSION(1, 0, 18)
spaceused = (int64_t)btodb(dq.dqb_curblocks);
#elif defined(__sun) || (defined(_LINUX_QUOTA_VERSION) && _LINUX_QUOTA_VERSION < 2)
spaceused = (int64_t)dq.dqb_curblocks >> 1;
#else
spaceused = btodb(dq.dqb_curspace);
#endif
freespace = limit - spaceused;
#ifdef __APPLE__
return freespace < 0 ? 0 : freespace;
#else
return freespace < 0 ? 0 : (freespace * 1024);
#endif
} }
#if defined(__sun)
close(fd); close(fd);
#else
if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device, getuid(), (caddr_t)&dq) != 0)
{
return -1;
}
#endif #endif
/* something went wrong */ if (dq.dqb_bsoftlimit > 0)
return -1; {
/* Use soft limit first */
limit = dq.dqb_bsoftlimit;
}
else if (dq.dqb_bhardlimit > 0)
{
limit = dq.dqb_bhardlimit;
}
else
{
/* No quota enabled for this user */
return -1;
}
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
spaceused = (int64_t)dq.dqb_curblocks >> 1;
#elif defined(__APPLE__)
spaceused = (int64_t)dq.dqb_curbytes;
#elif defined(__UCLIBC__) && !TR_UCLIBC_CHECK_VERSION(1, 0, 18)
spaceused = (int64_t)btodb(dq.dqb_curblocks);
#elif defined(__sun) || (defined(_LINUX_QUOTA_VERSION) && _LINUX_QUOTA_VERSION < 2)
spaceused = (int64_t)dq.dqb_curblocks >> 1;
#else
spaceused = btodb(dq.dqb_curspace);
#endif
freespace = limit - spaceused;
#ifdef __APPLE__
return freespace < 0 ? 0 : freespace;
#else
return freespace < 0 ? 0 : (freespace * 1024);
#endif
} }
#endif #endif

View File

@ -73,7 +73,7 @@ static bool tr_areThreadsEqual(tr_thread_id a, tr_thread_id b)
/** @brief portability wrapper around OS-dependent threads */ /** @brief portability wrapper around OS-dependent threads */
struct tr_thread struct tr_thread
{ {
void (* func)(void*); void (*func)(void*);
void* arg; void* arg;
tr_thread_id thread; tr_thread_id thread;
@ -113,7 +113,7 @@ static ThreadFuncReturnType ThreadFunc(void* _t)
#endif #endif
} }
tr_thread* tr_threadNew(void (* func)(void*), void* arg) tr_thread* tr_threadNew(void (*func)(void*), void* arg)
{ {
tr_thread* t = tr_new0(tr_thread, 1); tr_thread* t = tr_new0(tr_thread, 1);
@ -529,11 +529,10 @@ char const* tr_getWebClientDir(tr_session const* session)
/* Generally, Web interface should be stored in a Web subdir of /* Generally, Web interface should be stored in a Web subdir of
* calling executable dir. */ * calling executable dir. */
static REFKNOWNFOLDERID known_folder_ids[] = static REFKNOWNFOLDERID known_folder_ids[] = {
{
&FOLDERID_LocalAppData, &FOLDERID_LocalAppData,
&FOLDERID_RoamingAppData, &FOLDERID_RoamingAppData,
&FOLDERID_ProgramData &FOLDERID_ProgramData,
}; };
for (size_t i = 0; s == NULL && i < TR_N_ELEMENTS(known_folder_ids); ++i) for (size_t i = 0; s == NULL && i < TR_N_ELEMENTS(known_folder_ids); ++i)

View File

@ -50,7 +50,7 @@ char* tr_getSessionIdDir(void);
typedef struct tr_thread tr_thread; typedef struct tr_thread tr_thread;
/** @brief Instantiate a new process thread */ /** @brief Instantiate a new process thread */
tr_thread* tr_threadNew(void (* func)(void*), void* arg); tr_thread* tr_threadNew(void (*func)(void*), void* arg);
/** @brief Return nonzero if this function is being called from `thread' /** @brief Return nonzero if this function is being called from `thread'
@param thread the thread being tested */ @param thread the thread being tested */

View File

@ -103,7 +103,10 @@ static void natPulse(tr_shared* s, bool do_check)
if (newStatus != oldStatus) if (newStatus != oldStatus)
{ {
tr_logAddNamedInfo(getKey(), _("State changed from \"%1$s\" to \"%2$s\""), getNatStateStr(oldStatus), tr_logAddNamedInfo(
getKey(),
_("State changed from \"%1$s\" to \"%2$s\""),
getNatStateStr(oldStatus),
getNatStateStr(newStatus)); getNatStateStr(newStatus));
} }
} }

View File

@ -28,14 +28,16 @@ typedef struct tr_ptrArray
void** items; void** items;
int n_items; int n_items;
int n_alloc; int n_alloc;
} } tr_ptrArray;
tr_ptrArray;
typedef tr_voidptr_compare_func PtrArrayCompareFunc; typedef tr_voidptr_compare_func PtrArrayCompareFunc;
typedef void (* PtrArrayForeachFunc)(void*); typedef void (*PtrArrayForeachFunc)(void*);
#define TR_PTR_ARRAY_INIT_STATIC { NULL, 0, 0 } #define TR_PTR_ARRAY_INIT_STATIC \
{ \
NULL, 0, 0, \
}
extern tr_ptrArray const TR_PTR_ARRAY_INIT; extern tr_ptrArray const TR_PTR_ARRAY_INIT;

View File

@ -21,10 +21,12 @@ struct tr_key_struct
size_t len; size_t len;
}; };
#define Q(name) { "" name "", sizeof("" name "") - 1 } #define Q(name) \
{ \
"" name "", sizeof("" name "") - 1, \
}
static struct tr_key_struct const my_static[] = static struct tr_key_struct const my_static[] = {
{
Q(""), Q(""),
Q("activeTorrentCount"), Q("activeTorrentCount"),
Q("activity-date"), Q("activity-date"),
@ -412,7 +414,7 @@ static struct tr_key_struct const my_static[] =
Q("watch-dir"), Q("watch-dir"),
Q("watch-dir-enabled"), Q("watch-dir-enabled"),
Q("webseeds"), Q("webseeds"),
Q("webseedsSendingToUs") Q("webseedsSendingToUs"),
}; };
#undef Q #undef Q

View File

@ -207,8 +207,13 @@ static uint64_t loadDND(tr_variant* dict, tr_torrent* tor)
} }
else else
{ {
tr_logAddTorDbg(tor, "Couldn't load DND flags. DND list (%p) has %zu" " children; torrent has %d files", (void*)list, tr_logAddTorDbg(
tr_variantListSize(list), (int)n); tor,
"Couldn't load DND flags. DND list (%p) has %zu"
" children; torrent has %d files",
(void*)list,
tr_variantListSize(list),
(int)n);
} }
return ret; return ret;
@ -930,8 +935,8 @@ static uint64_t loadFromFile(tr_torrent* tor, uint64_t fieldsToLoad, bool* didRe
fieldsLoaded |= TR_FR_TIME_DOWNLOADING; fieldsLoaded |= TR_FR_TIME_DOWNLOADING;
} }
if ((fieldsToLoad & TR_FR_BANDWIDTH_PRIORITY) != 0 && if ((fieldsToLoad & TR_FR_BANDWIDTH_PRIORITY) != 0 && tr_variantDictFindInt(&top, TR_KEY_bandwidth_priority, &i) &&
tr_variantDictFindInt(&top, TR_KEY_bandwidth_priority, &i) && tr_isPriority(i)) tr_isPriority(i))
{ {
tr_torrentSetPriority(tor, i); tr_torrentSetPriority(tor, i);
fieldsLoaded |= TR_FR_BANDWIDTH_PRIORITY; fieldsLoaded |= TR_FR_BANDWIDTH_PRIORITY;

View File

@ -272,9 +272,7 @@ static char const* mimetype_guess(char const* path)
{ {
char const* suffix; char const* suffix;
char const* mime_type; char const* mime_type;
} } const types[] = {
const types[] =
{
/* these are the ones we need for serving the web client's files... */ /* these are the ones we need for serving the web client's files... */
{ "css", "text/css" }, { "css", "text/css" },
{ "gif", "image/gif" }, { "gif", "image/gif" },
@ -282,7 +280,7 @@ static char const* mimetype_guess(char const* path)
{ "ico", "image/vnd.microsoft.icon" }, { "ico", "image/vnd.microsoft.icon" },
{ "js", "application/javascript" }, { "js", "application/javascript" },
{ "png", "image/png" }, { "png", "image/png" },
{ "svg", "image/svg+xml" } { "svg", "image/svg+xml" },
}; };
char const* dot = strrchr(path, '.'); char const* dot = strrchr(path, '.');
@ -297,7 +295,10 @@ static char const* mimetype_guess(char const* path)
return "application/octet-stream"; return "application/octet-stream";
} }
static void add_response(struct evhttp_request* req, struct tr_rpc_server* server, struct evbuffer* out, static void add_response(
struct evhttp_request* req,
struct tr_rpc_server* server,
struct evbuffer* out,
struct evbuffer* content) struct evbuffer* content)
{ {
char const* key = "Accept-Encoding"; char const* key = "Accept-Encoding";
@ -439,7 +440,9 @@ static void handle_web_client(struct evhttp_request* req, struct tr_rpc_server*
if (tr_str_is_empty(webClientDir)) if (tr_str_is_empty(webClientDir))
{ {
send_simple_response(req, HTTP_NOTFOUND, send_simple_response(
req,
HTTP_NOTFOUND,
"<p>Couldn't find Transmission's web interface files!</p>" "<p>Couldn't find Transmission's web interface files!</p>"
"<p>Users: to tell Transmission where to look, " "<p>Users: to tell Transmission where to look, "
"set the TRANSMISSION_WEB_HOME environment " "set the TRANSMISSION_WEB_HOME environment "
@ -467,7 +470,10 @@ static void handle_web_client(struct evhttp_request* req, struct tr_rpc_server*
} }
else else
{ {
char* filename = tr_strdup_printf("%s%s%s", webClientDir, TR_PATH_DELIMITER_STR, char* filename = tr_strdup_printf(
"%s%s%s",
webClientDir,
TR_PATH_DELIMITER_STR,
tr_str_is_empty(subpath) ? "index.html" : subpath); tr_str_is_empty(subpath) ? "index.html" : subpath);
serve_file(req, server, filename); serve_file(req, server, filename);
tr_free(filename); tr_free(filename);
@ -522,7 +528,10 @@ static void handle_rpc(struct evhttp_request* req, struct tr_rpc_server* server)
{ {
if (req->type == EVHTTP_REQ_POST) if (req->type == EVHTTP_REQ_POST)
{ {
handle_rpc_from_json(req, server, (char const*)evbuffer_pullup(req->input_buffer, -1), handle_rpc_from_json(
req,
server,
(char const*)evbuffer_pullup(req->input_buffer, -1),
evbuffer_get_length(req->input_buffer)); evbuffer_get_length(req->input_buffer));
return; return;
} }
@ -651,7 +660,9 @@ static void handle_request(struct evhttp_request* req, void* arg)
if (!isAddressAllowed(server, req->remote_host)) if (!isAddressAllowed(server, req->remote_host))
{ {
send_simple_response(req, 403, send_simple_response(
req,
403,
"<p>Unauthorized IP Address.</p>" "<p>Unauthorized IP Address.</p>"
"<p>Either disable the IP address whitelist or add your address to it.</p>" "<p>Either disable the IP address whitelist or add your address to it.</p>"
"<p>If you're editing settings.json, see the 'rpc-whitelist' and 'rpc-whitelist-enabled' entries.</p>" "<p>If you're editing settings.json, see the 'rpc-whitelist' and 'rpc-whitelist-enabled' entries.</p>"
@ -679,8 +690,8 @@ static void handle_request(struct evhttp_request* req, void* arg)
} }
} }
if (server->isPasswordEnabled && (pass == NULL || user == NULL || strcmp(server->username, user) != 0 || if (server->isPasswordEnabled &&
!tr_ssha1_matches(server->password, pass))) (pass == NULL || user == NULL || strcmp(server->username, user) != 0 || !tr_ssha1_matches(server->password, pass)))
{ {
evhttp_add_header(req->output_headers, "WWW-Authenticate", "Basic realm=\"" MY_REALM "\""); evhttp_add_header(req->output_headers, "WWW-Authenticate", "Basic realm=\"" MY_REALM "\"");
if (server->isAntiBruteForceEnabled) if (server->isAntiBruteForceEnabled)
@ -688,7 +699,8 @@ static void handle_request(struct evhttp_request* req, void* arg)
server->loginattempts++; server->loginattempts++;
} }
char* unauthuser = tr_strdup_printf("<p>Unauthorized User. %d unsuccessful login attempts.</p>", char* unauthuser = tr_strdup_printf(
"<p>Unauthorized User. %d unsuccessful login attempts.</p>",
server->loginattempts); server->loginattempts);
send_simple_response(req, 401, unauthuser); send_simple_response(req, 401, unauthuser);
tr_free(unauthuser); tr_free(unauthuser);
@ -746,7 +758,8 @@ static void handle_request(struct evhttp_request* req, void* arg)
"<a href=\"https://en.wikipedia.org/wiki/Cross-site_request_forgery\">CSRF</a> " "<a href=\"https://en.wikipedia.org/wiki/Cross-site_request_forgery\">CSRF</a> "
"attacks.</p>" "attacks.</p>"
"<p><code>%s: %s</code></p>", "<p><code>%s: %s</code></p>",
TR_RPC_SESSION_ID_HEADER, sessionId); TR_RPC_SESSION_ID_HEADER,
sessionId);
evhttp_add_header(req->output_headers, TR_RPC_SESSION_ID_HEADER, sessionId); evhttp_add_header(req->output_headers, TR_RPC_SESSION_ID_HEADER, sessionId);
send_simple_response(req, 409, tmp); send_simple_response(req, 409, tmp);
tr_free(tmp); tr_free(tmp);
@ -839,7 +852,11 @@ static void startServer(void* vserver)
return; return;
} }
tr_logAddNamedError(MY_NAME, "Unable to bind to %s:%d after %d attempts, giving up", address, port, tr_logAddNamedError(
MY_NAME,
"Unable to bind to %s:%d after %d attempts, giving up",
address,
port,
SERVER_START_RETRY_COUNT); SERVER_START_RETRY_COUNT);
} }
else else
@ -964,8 +981,10 @@ static void tr_rpcSetList(char const* whitelistStr, tr_list** list)
if (strcspn(token, "+-") < len) if (strcspn(token, "+-") < len)
{ {
tr_logAddNamedInfo(MY_NAME, tr_logAddNamedInfo(
"Adding address to whitelist: %s (And it has a '+' or '-'! Are you using an old ACL by mistake?)", token); MY_NAME,
"Adding address to whitelist: %s (And it has a '+' or '-'! Are you using an old ACL by mistake?)",
token);
} }
else else
{ {
@ -1302,7 +1321,11 @@ tr_rpc_server* tr_rpcInit(tr_session* session, tr_variant* settings)
if (s->isEnabled) if (s->isEnabled)
{ {
tr_logAddNamedInfo(MY_NAME, _("Serving RPC and Web requests on %s:%d%s"), tr_rpcGetBindAddress(s), (int)s->port, tr_logAddNamedInfo(
MY_NAME,
_("Serving RPC and Web requests on %s:%d%s"),
tr_rpcGetBindAddress(s),
(int)s->port,
s->url); s->url);
tr_runInEventThread(session, startServer, s); tr_runInEventThread(session, startServer, s);

View File

@ -53,8 +53,7 @@ typedef enum
{ {
TR_FORMAT_OBJECT = 0, TR_FORMAT_OBJECT = 0,
TR_FORMAT_TABLE TR_FORMAT_TABLE
} } tr_format;
tr_format;
/*** /***
**** ****
@ -204,7 +203,10 @@ static void notifyBatchQueueChange(tr_session* session, tr_torrent** torrents, i
notify(session, TR_RPC_SESSION_QUEUE_POSITIONS_CHANGED, NULL); notify(session, TR_RPC_SESSION_QUEUE_POSITIONS_CHANGED, NULL);
} }
static char const* queueMoveTop(tr_session* session, tr_variant* args_in, tr_variant* args_out, static char const* queueMoveTop(
tr_session* session,
tr_variant* args_in,
tr_variant* args_out,
struct tr_rpc_idle_data* idle_data) struct tr_rpc_idle_data* idle_data)
{ {
TR_UNUSED(args_out); TR_UNUSED(args_out);
@ -218,7 +220,10 @@ static char const* queueMoveTop(tr_session* session, tr_variant* args_in, tr_var
return NULL; return NULL;
} }
static char const* queueMoveUp(tr_session* session, tr_variant* args_in, tr_variant* args_out, static char const* queueMoveUp(
tr_session* session,
tr_variant* args_in,
tr_variant* args_out,
struct tr_rpc_idle_data* idle_data) struct tr_rpc_idle_data* idle_data)
{ {
TR_UNUSED(args_out); TR_UNUSED(args_out);
@ -232,7 +237,10 @@ static char const* queueMoveUp(tr_session* session, tr_variant* args_in, tr_vari
return NULL; return NULL;
} }
static char const* queueMoveDown(tr_session* session, tr_variant* args_in, tr_variant* args_out, static char const* queueMoveDown(
tr_session* session,
tr_variant* args_in,
tr_variant* args_out,
struct tr_rpc_idle_data* idle_data) struct tr_rpc_idle_data* idle_data)
{ {
TR_UNUSED(args_out); TR_UNUSED(args_out);
@ -246,7 +254,10 @@ static char const* queueMoveDown(tr_session* session, tr_variant* args_in, tr_va
return NULL; return NULL;
} }
static char const* queueMoveBottom(tr_session* session, tr_variant* args_in, tr_variant* args_out, static char const* queueMoveBottom(
tr_session* session,
tr_variant* args_in,
tr_variant* args_out,
struct tr_rpc_idle_data* idle_data) struct tr_rpc_idle_data* idle_data)
{ {
TR_UNUSED(args_out); TR_UNUSED(args_out);
@ -268,7 +279,10 @@ static int compareTorrentByQueuePosition(void const* va, void const* vb)
return a->queuePosition - b->queuePosition; return a->queuePosition - b->queuePosition;
} }
static char const* torrentStart(tr_session* session, tr_variant* args_in, tr_variant* args_out, static char const* torrentStart(
tr_session* session,
tr_variant* args_in,
tr_variant* args_out,
struct tr_rpc_idle_data* idle_data) struct tr_rpc_idle_data* idle_data)
{ {
TR_UNUSED(args_out); TR_UNUSED(args_out);
@ -296,7 +310,10 @@ static char const* torrentStart(tr_session* session, tr_variant* args_in, tr_var
return NULL; return NULL;
} }
static char const* torrentStartNow(tr_session* session, tr_variant* args_in, tr_variant* args_out, static char const* torrentStartNow(
tr_session* session,
tr_variant* args_in,
tr_variant* args_out,
struct tr_rpc_idle_data* idle_data) struct tr_rpc_idle_data* idle_data)
{ {
TR_UNUSED(args_out); TR_UNUSED(args_out);
@ -324,7 +341,10 @@ static char const* torrentStartNow(tr_session* session, tr_variant* args_in, tr_
return NULL; return NULL;
} }
static char const* torrentStop(tr_session* session, tr_variant* args_in, tr_variant* args_out, static char const* torrentStop(
tr_session* session,
tr_variant* args_in,
tr_variant* args_out,
struct tr_rpc_idle_data* idle_data) struct tr_rpc_idle_data* idle_data)
{ {
TR_UNUSED(args_out); TR_UNUSED(args_out);
@ -350,7 +370,10 @@ static char const* torrentStop(tr_session* session, tr_variant* args_in, tr_vari
return NULL; return NULL;
} }
static char const* torrentRemove(tr_session* session, tr_variant* args_in, tr_variant* args_out, static char const* torrentRemove(
tr_session* session,
tr_variant* args_in,
tr_variant* args_out,
struct tr_rpc_idle_data* idle_data) struct tr_rpc_idle_data* idle_data)
{ {
TR_UNUSED(args_out); TR_UNUSED(args_out);
@ -385,7 +408,10 @@ static char const* torrentRemove(tr_session* session, tr_variant* args_in, tr_va
return NULL; return NULL;
} }
static char const* torrentReannounce(tr_session* session, tr_variant* args_in, tr_variant* args_out, static char const* torrentReannounce(
tr_session* session,
tr_variant* args_in,
tr_variant* args_out,
struct tr_rpc_idle_data* idle_data) struct tr_rpc_idle_data* idle_data)
{ {
TR_UNUSED(args_out); TR_UNUSED(args_out);
@ -411,7 +437,10 @@ static char const* torrentReannounce(tr_session* session, tr_variant* args_in, t
return NULL; return NULL;
} }
static char const* torrentVerify(tr_session* session, tr_variant* args_in, tr_variant* args_out, static char const* torrentVerify(
tr_session* session,
tr_variant* args_in,
tr_variant* args_out,
struct tr_rpc_idle_data* idle_data) struct tr_rpc_idle_data* idle_data)
{ {
TR_UNUSED(args_out); TR_UNUSED(args_out);
@ -572,7 +601,11 @@ static void addPeers(tr_torrent* tor, tr_variant* list)
tr_torrentPeersFree(peers, peerCount); tr_torrentPeersFree(peers, peerCount);
} }
static void initField(tr_torrent* const tor, tr_info const* const inf, tr_stat const* const st, tr_variant* const initme, static void initField(
tr_torrent* const tor,
tr_info const* const inf,
tr_stat const* const st,
tr_variant* const initme,
tr_quark key) tr_quark key)
{ {
char* str; char* str;
@ -936,16 +969,17 @@ static void addTorrentInfo(tr_torrent* tor, tr_format format, tr_variant* entry,
for (size_t i = 0; i < fieldCount; ++i) for (size_t i = 0; i < fieldCount; ++i)
{ {
tr_variant* child = format == TR_FORMAT_TABLE ? tr_variant* child = format == TR_FORMAT_TABLE ? tr_variantListAdd(entry) : tr_variantDictAdd(entry, fields[i]);
tr_variantListAdd(entry) :
tr_variantDictAdd(entry, fields[i]);
initField(tor, inf, st, child, fields[i]); initField(tor, inf, st, child, fields[i]);
} }
} }
} }
static char const* torrentGet(tr_session* session, tr_variant* args_in, tr_variant* args_out, static char const* torrentGet(
tr_session* session,
tr_variant* args_in,
tr_variant* args_out,
struct tr_rpc_idle_data* idle_data) struct tr_rpc_idle_data* idle_data)
{ {
TR_UNUSED(idle_data); TR_UNUSED(idle_data);
@ -982,8 +1016,7 @@ static char const* torrentGet(tr_session* session, tr_variant* args_in, tr_varia
int64_t date; int64_t date;
int64_t id; int64_t id;
if (tr_variantDictFindInt(d, TR_KEY_date, &date) && if (tr_variantDictFindInt(d, TR_KEY_date, &date) && date >= now - interval &&
date >= now - interval &&
tr_variantDictFindInt(d, TR_KEY_id, &id)) tr_variantDictFindInt(d, TR_KEY_id, &id))
{ {
tr_variantListAddInt(removed_out, id); tr_variantListAddInt(removed_out, id);
@ -1297,8 +1330,8 @@ static char const* replaceTrackers(tr_torrent* tor, tr_variant* urls)
char const* newval; char const* newval;
if (tr_variantGetInt(tr_variantListChild(urls, i), &pos) && if (tr_variantGetInt(tr_variantListChild(urls, i), &pos) &&
tr_variantGetStr(tr_variantListChild(urls, i + 1), &newval, &len) && tr_variantGetStr(tr_variantListChild(urls, i + 1), &newval, &len) && tr_urlIsValidTracker(newval) && pos < n &&
tr_urlIsValidTracker(newval) && pos < n && pos >= 0) pos >= 0)
{ {
tr_free(trackers[pos].announce); tr_free(trackers[pos].announce);
trackers[pos].announce = tr_strndup(newval, len); trackers[pos].announce = tr_strndup(newval, len);
@ -1379,7 +1412,10 @@ static char const* removeTrackers(tr_torrent* tor, tr_variant* ids)
return errmsg; return errmsg;
} }
static char const* torrentSet(tr_session* session, tr_variant* args_in, tr_variant* args_out, static char const* torrentSet(
tr_session* session,
tr_variant* args_in,
tr_variant* args_out,
struct tr_rpc_idle_data* idle_data) struct tr_rpc_idle_data* idle_data)
{ {
TR_UNUSED(args_out); TR_UNUSED(args_out);
@ -1519,7 +1555,10 @@ static char const* torrentSet(tr_session* session, tr_variant* args_in, tr_varia
return errmsg; return errmsg;
} }
static char const* torrentSetLocation(tr_session* session, tr_variant* args_in, tr_variant* args_out, static char const* torrentSetLocation(
tr_session* session,
tr_variant* args_in,
tr_variant* args_out,
struct tr_rpc_idle_data* idle_data) struct tr_rpc_idle_data* idle_data)
{ {
TR_UNUSED(args_out); TR_UNUSED(args_out);
@ -1585,7 +1624,10 @@ static void torrentRenamePathDone(tr_torrent* tor, char const* oldpath, char con
tr_idle_function_done(data, result); tr_idle_function_done(data, result);
} }
static char const* torrentRenamePath(tr_session* session, tr_variant* args_in, tr_variant* args_out, static char const* torrentRenamePath(
tr_session* session,
tr_variant* args_in,
tr_variant* args_out,
struct tr_rpc_idle_data* idle_data) struct tr_rpc_idle_data* idle_data)
{ {
TR_UNUSED(args_out); TR_UNUSED(args_out);
@ -1617,8 +1659,14 @@ static char const* torrentRenamePath(tr_session* session, tr_variant* args_in, t
**** ****
***/ ***/
static void portTested(tr_session* session, bool did_connect, bool did_timeout, long response_code, void const* response, static void portTested(
size_t response_byte_count, void* user_data) tr_session* session,
bool did_connect,
bool did_timeout,
long response_code,
void const* response,
size_t response_byte_count,
void* user_data)
{ {
TR_UNUSED(session); TR_UNUSED(session);
TR_UNUSED(did_connect); TR_UNUSED(did_connect);
@ -1629,7 +1677,11 @@ static void portTested(tr_session* session, bool did_connect, bool did_timeout,
if (response_code != 200) if (response_code != 200)
{ {
tr_snprintf(result, sizeof(result), "portTested: http error %ld: %s", response_code, tr_snprintf(
result,
sizeof(result),
"portTested: http error %ld: %s",
response_code,
tr_webGetResponseStr(response_code)); tr_webGetResponseStr(response_code));
} }
else /* success */ else /* success */
@ -1658,8 +1710,14 @@ static char const* portTest(tr_session* session, tr_variant* args_in, tr_variant
**** ****
***/ ***/
static void gotNewBlocklist(tr_session* session, bool did_connect, bool did_timeout, long response_code, void const* response, static void gotNewBlocklist(
size_t response_byte_count, void* user_data) tr_session* session,
bool did_connect,
bool did_timeout,
long response_code,
void const* response,
size_t response_byte_count,
void* user_data)
{ {
TR_UNUSED(did_connect); TR_UNUSED(did_connect);
TR_UNUSED(did_timeout); TR_UNUSED(did_timeout);
@ -1671,7 +1729,11 @@ static void gotNewBlocklist(tr_session* session, bool did_connect, bool did_time
if (response_code != 200) if (response_code != 200)
{ {
tr_snprintf(result, sizeof(result), "gotNewBlocklist: http error %ld: %s", response_code, tr_snprintf(
result,
sizeof(result),
"gotNewBlocklist: http error %ld: %s",
response_code,
tr_webGetResponseStr(response_code)); tr_webGetResponseStr(response_code));
} }
else /* successfully fetched the blocklist... */ else /* successfully fetched the blocklist... */
@ -1709,8 +1771,7 @@ static void gotNewBlocklist(tr_session* session, bool did_connect, bool did_time
stream.avail_out = buflen; stream.avail_out = buflen;
err = inflate(&stream, Z_NO_FLUSH); err = inflate(&stream, Z_NO_FLUSH);
if ((stream.avail_out < buflen) && if ((stream.avail_out < buflen) && (!tr_sys_file_write(fd, buf, buflen - stream.avail_out, NULL, &error)))
(!tr_sys_file_write(fd, buf, buflen - stream.avail_out, NULL, &error)))
{ {
tr_snprintf(result, sizeof(result), _("Couldn't save file \"%1$s\": %2$s"), filename, error->message); tr_snprintf(result, sizeof(result), _("Couldn't save file \"%1$s\": %2$s"), filename, error->message);
tr_error_clear(&error); tr_error_clear(&error);
@ -1759,7 +1820,10 @@ static void gotNewBlocklist(tr_session* session, bool did_connect, bool did_time
tr_idle_function_done(data, result); tr_idle_function_done(data, result);
} }
static char const* blocklistUpdate(tr_session* session, tr_variant* args_in, tr_variant* args_out, static char const* blocklistUpdate(
tr_session* session,
tr_variant* args_in,
tr_variant* args_out,
struct tr_rpc_idle_data* idle_data) struct tr_rpc_idle_data* idle_data)
{ {
TR_UNUSED(args_in); TR_UNUSED(args_in);
@ -1805,11 +1869,10 @@ static void addTorrentImpl(struct tr_rpc_idle_data* data, tr_ctor* ctor)
if (tor != NULL && key != 0) if (tor != NULL && key != 0)
{ {
tr_quark const fields[] = tr_quark const fields[] = {
{
TR_KEY_id, TR_KEY_id,
TR_KEY_name, TR_KEY_name,
TR_KEY_hashString TR_KEY_hashString,
}; };
addTorrentInfo(tor, TR_FORMAT_OBJECT, tr_variantDictAdd(data->args_out, key), fields, TR_N_ELEMENTS(fields)); addTorrentInfo(tor, TR_FORMAT_OBJECT, tr_variantDictAdd(data->args_out, key), fields, TR_N_ELEMENTS(fields));
@ -1831,8 +1894,14 @@ struct add_torrent_idle_data
tr_ctor* ctor; tr_ctor* ctor;
}; };
static void gotMetadataFromURL(tr_session* session, bool did_connect, bool did_timeout, long response_code, static void gotMetadataFromURL(
void const* response, size_t response_byte_count, void* user_data) tr_session* session,
bool did_connect,
bool did_timeout,
long response_code,
void const* response,
size_t response_byte_count,
void* user_data)
{ {
TR_UNUSED(session); TR_UNUSED(session);
TR_UNUSED(did_connect); TR_UNUSED(did_connect);
@ -1840,8 +1909,11 @@ static void gotMetadataFromURL(tr_session* session, bool did_connect, bool did_t
struct add_torrent_idle_data* data = user_data; struct add_torrent_idle_data* data = user_data;
dbgmsg("torrentAdd: HTTP response code was %ld (%s); response length was %zu bytes", response_code, dbgmsg(
tr_webGetResponseStr(response_code), response_byte_count); "torrentAdd: HTTP response code was %ld (%s); response length was %zu bytes",
response_code,
tr_webGetResponseStr(response_code),
response_byte_count);
if (response_code == 200 || response_code == 221) /* http or ftp success.. */ if (response_code == 200 || response_code == 221) /* http or ftp success.. */
{ {
@ -1851,7 +1923,11 @@ static void gotMetadataFromURL(tr_session* session, bool did_connect, bool did_t
else else
{ {
char result[1024]; char result[1024];
tr_snprintf(result, sizeof(result), "gotMetadataFromURL: http error %ld: %s", response_code, tr_snprintf(
result,
sizeof(result),
"gotMetadataFromURL: http error %ld: %s",
response_code,
tr_webGetResponseStr(response_code)); tr_webGetResponseStr(response_code));
tr_idle_function_done(data->data, result); tr_idle_function_done(data->data, result);
} }
@ -1889,7 +1965,10 @@ static tr_file_index_t* fileListFromList(tr_variant* list, tr_file_index_t* setm
return files; return files;
} }
static char const* torrentAdd(tr_session* session, tr_variant* args_in, tr_variant* args_out, static char const* torrentAdd(
tr_session* session,
tr_variant* args_in,
tr_variant* args_out,
struct tr_rpc_idle_data* idle_data) struct tr_rpc_idle_data* idle_data)
{ {
TR_UNUSED(args_out); TR_UNUSED(args_out);
@ -1909,8 +1988,7 @@ static char const* torrentAdd(tr_session* session, tr_variant* args_in, tr_varia
char const* download_dir = NULL; char const* download_dir = NULL;
if (tr_variantDictFindStr(args_in, TR_KEY_download_dir, &download_dir, NULL) && if (tr_variantDictFindStr(args_in, TR_KEY_download_dir, &download_dir, NULL) && tr_sys_path_is_relative(download_dir))
tr_sys_path_is_relative(download_dir))
{ {
return "download directory path is not absolute"; return "download directory path is not absolute";
} }
@ -2026,7 +2104,10 @@ static char const* torrentAdd(tr_session* session, tr_variant* args_in, tr_varia
**** ****
***/ ***/
static char const* sessionSet(tr_session* session, tr_variant* args_in, tr_variant* args_out, static char const* sessionSet(
tr_session* session,
tr_variant* args_in,
tr_variant* args_out,
struct tr_rpc_idle_data* idle_data) struct tr_rpc_idle_data* idle_data)
{ {
TR_UNUSED(args_out); TR_UNUSED(args_out);
@ -2037,14 +2118,12 @@ static char const* sessionSet(tr_session* session, tr_variant* args_in, tr_varia
char const* download_dir = NULL; char const* download_dir = NULL;
char const* incomplete_dir = NULL; char const* incomplete_dir = NULL;
if (tr_variantDictFindStr(args_in, TR_KEY_download_dir, &download_dir, NULL) && if (tr_variantDictFindStr(args_in, TR_KEY_download_dir, &download_dir, NULL) && tr_sys_path_is_relative(download_dir))
tr_sys_path_is_relative(download_dir))
{ {
return "download directory path is not absolute"; return "download directory path is not absolute";
} }
if (tr_variantDictFindStr(args_in, TR_KEY_incomplete_dir, &incomplete_dir, NULL) && if (tr_variantDictFindStr(args_in, TR_KEY_incomplete_dir, &incomplete_dir, NULL) && tr_sys_path_is_relative(incomplete_dir))
tr_sys_path_is_relative(incomplete_dir))
{ {
return "incomplete torrents directory path is not absolute"; return "incomplete torrents directory path is not absolute";
} }
@ -2290,7 +2369,10 @@ static char const* sessionSet(tr_session* session, tr_variant* args_in, tr_varia
return NULL; return NULL;
} }
static char const* sessionStats(tr_session* session, tr_variant* args_in, tr_variant* args_out, static char const* sessionStats(
tr_session* session,
tr_variant* args_in,
tr_variant* args_out,
struct tr_rpc_idle_data* idle_data) struct tr_rpc_idle_data* idle_data)
{ {
TR_UNUSED(args_in); TR_UNUSED(args_in);
@ -2661,7 +2743,10 @@ static char const* freeSpace(tr_session* session, tr_variant* args_in, tr_varian
**** ****
***/ ***/
static char const* sessionClose(tr_session* session, tr_variant* args_in, tr_variant* args_out, static char const* sessionClose(
tr_session* session,
tr_variant* args_in,
tr_variant* args_out,
struct tr_rpc_idle_data* idle_data) struct tr_rpc_idle_data* idle_data)
{ {
TR_UNUSED(args_in); TR_UNUSED(args_in);
@ -2676,16 +2761,14 @@ static char const* sessionClose(tr_session* session, tr_variant* args_in, tr_var
**** ****
***/ ***/
typedef char const* (* handler)(tr_session*, tr_variant*, tr_variant*, struct tr_rpc_idle_data*); typedef char const* (*handler)(tr_session*, tr_variant*, tr_variant*, struct tr_rpc_idle_data*);
static struct method static struct method
{ {
char const* name; char const* name;
bool immediate; bool immediate;
handler func; handler func;
} } methods[] = {
methods[] =
{
{ "port-test", false, portTest }, { "port-test", false, portTest },
{ "blocklist-update", false, blocklistUpdate }, { "blocklist-update", false, blocklistUpdate },
{ "free-space", true, freeSpace }, { "free-space", true, freeSpace },
@ -2707,7 +2790,7 @@ methods[] =
{ "queue-move-top", true, queueMoveTop }, { "queue-move-top", true, queueMoveTop },
{ "queue-move-up", true, queueMoveUp }, { "queue-move-up", true, queueMoveUp },
{ "queue-move-down", true, queueMoveDown }, { "queue-move-down", true, queueMoveDown },
{ "queue-move-bottom", true, queueMoveBottom } { "queue-move-bottom", true, queueMoveBottom },
}; };
static void noop_response_callback(tr_session* session, tr_variant* response, void* user_data) static void noop_response_callback(tr_session* session, tr_variant* response, void* user_data)
@ -2717,7 +2800,10 @@ static void noop_response_callback(tr_session* session, tr_variant* response, vo
TR_UNUSED(user_data); TR_UNUSED(user_data);
} }
void tr_rpc_request_exec_json(tr_session* session, tr_variant const* request, tr_rpc_response_func callback, void tr_rpc_request_exec_json(
tr_session* session,
tr_variant const* request,
tr_rpc_response_func callback,
void* callback_user_data) void* callback_user_data)
{ {
char const* str; char const* str;
@ -2858,8 +2944,12 @@ void tr_rpc_parse_list_str(tr_variant* setme, char const* str, size_t len)
tr_free(values); tr_free(values);
} }
void tr_rpc_request_exec_uri(tr_session* session, void const* request_uri, size_t request_uri_len, void tr_rpc_request_exec_uri(
tr_rpc_response_func callback, void* callback_user_data) tr_session* session,
void const* request_uri,
size_t request_uri_len,
tr_rpc_response_func callback,
void* callback_user_data)
{ {
char const* pch; char const* pch;
tr_variant top; tr_variant top;
@ -2887,7 +2977,9 @@ void tr_rpc_request_exec_uri(tr_session* session, void const* request_uri, size_
bool isArg = strcmp(key, "method") != 0 && strcmp(key, "tag") != 0; bool isArg = strcmp(key, "method") != 0 && strcmp(key, "tag") != 0;
tr_variant* parent = isArg ? args : &top; tr_variant* parent = isArg ? args : &top;
tr_rpc_parse_list_str(tr_variantDictAdd(parent, tr_quark_new(key, (size_t)(delim - pch))), delim + 1, tr_rpc_parse_list_str(
tr_variantDictAdd(parent, tr_quark_new(key, (size_t)(delim - pch))),
delim + 1,
next != NULL ? (size_t)(next - (delim + 1)) : strlen(delim + 1)); next != NULL ? (size_t)(next - (delim + 1)) : strlen(delim + 1));
tr_free(key); tr_free(key);
} }

View File

@ -18,15 +18,22 @@ TR_BEGIN_DECLS
**** RPC processing **** RPC processing
***/ ***/
typedef void (* tr_rpc_response_func)(tr_session* session, tr_variant* response, void* user_data); typedef void (*tr_rpc_response_func)(tr_session* session, tr_variant* response, void* user_data);
/* http://www.json.org/ */ /* http://www.json.org/ */
void tr_rpc_request_exec_json(tr_session* session, tr_variant const* request, tr_rpc_response_func callback, void tr_rpc_request_exec_json(
tr_session* session,
tr_variant const* request,
tr_rpc_response_func callback,
void* callback_user_data); void* callback_user_data);
/* see the RPC spec's "Request URI Notation" section */ /* see the RPC spec's "Request URI Notation" section */
void tr_rpc_request_exec_uri(tr_session* session, void const* request_uri, size_t request_uri_len, void tr_rpc_request_exec_uri(
tr_rpc_response_func callback, void* callback_user_data); tr_session* session,
void const* request_uri,
size_t request_uri_len,
tr_rpc_response_func callback,
void* callback_user_data);
void tr_rpc_parse_list_str(tr_variant* setme, char const* list_str, size_t list_str_len); void tr_rpc_parse_list_str(tr_variant* setme, char const* list_str, size_t list_str_len);

View File

@ -180,7 +180,12 @@ static void accept_incoming_peer(evutil_socket_t fd, short what, void* vsession)
{ {
char addrstr[TR_ADDRSTRLEN]; char addrstr[TR_ADDRSTRLEN];
tr_address_and_port_to_string(addrstr, sizeof(addrstr), &clientAddr, clientPort); tr_address_and_port_to_string(addrstr, sizeof(addrstr), &clientAddr, clientPort);
tr_logAddDeep(__FILE__, __LINE__, NULL, "new incoming connection %" PRIdMAX " (%s)", (intmax_t)clientSocket, tr_logAddDeep(
__FILE__,
__LINE__,
NULL,
"new incoming connection %" PRIdMAX " (%s)",
(intmax_t)clientSocket,
addrstr); addrstr);
} }
@ -986,8 +991,7 @@ static void sessionSetImpl(void* vdata)
free_incoming_peer_port(session); free_incoming_peer_port(session);
if (!tr_variantDictFindStr(settings, TR_KEY_bind_address_ipv4, &str, NULL) || if (!tr_variantDictFindStr(settings, TR_KEY_bind_address_ipv4, &str, NULL) || !tr_address_from_string(&b.addr, str) ||
!tr_address_from_string(&b.addr, str) ||
b.addr.type != TR_AF_INET) b.addr.type != TR_AF_INET)
{ {
b.addr = tr_inaddr_any; b.addr = tr_inaddr_any;
@ -996,8 +1000,7 @@ static void sessionSetImpl(void* vdata)
b.socket = TR_BAD_SOCKET; b.socket = TR_BAD_SOCKET;
session->bind_ipv4 = tr_memdup(&b, sizeof(struct tr_bindinfo)); session->bind_ipv4 = tr_memdup(&b, sizeof(struct tr_bindinfo));
if (!tr_variantDictFindStr(settings, TR_KEY_bind_address_ipv6, &str, NULL) || if (!tr_variantDictFindStr(settings, TR_KEY_bind_address_ipv6, &str, NULL) || !tr_address_from_string(&b.addr, str) ||
!tr_address_from_string(&b.addr, str) ||
b.addr.type != TR_AF_INET6) b.addr.type != TR_AF_INET6)
{ {
b.addr = tr_in6addr_any; b.addr = tr_in6addr_any;
@ -2064,7 +2067,10 @@ void tr_sessionClose(tr_session* session)
time_t const deadline = time(NULL) + SHUTDOWN_MAX_SECONDS; time_t const deadline = time(NULL) + SHUTDOWN_MAX_SECONDS;
dbgmsg("shutting down transmission session %p... now is %zu, deadline is %zu", (void*)session, (size_t)time(NULL), dbgmsg(
"shutting down transmission session %p... now is %zu, deadline is %zu",
(void*)session,
(size_t)time(NULL),
(size_t)deadline); (size_t)deadline);
/* close the session */ /* close the session */
@ -2081,10 +2087,14 @@ void tr_sessionClose(tr_session* session)
* for a bit while they tell the router & tracker * for a bit while they tell the router & tracker
* that we're closing now */ * that we're closing now */
while ((session->shared != NULL || session->web != NULL || session->announcer != NULL || session->announcer_udp != NULL) && while ((session->shared != NULL || session->web != NULL || session->announcer != NULL || session->announcer_udp != NULL) &&
!deadlineReached(deadline)) !deadlineReached(deadline))
{ {
dbgmsg("waiting on port unmap (%p) or announcer (%p)... now %zu deadline %zu", (void*)session->shared, dbgmsg(
(void*)session->announcer, (size_t)time(NULL), (size_t)deadline); "waiting on port unmap (%p) or announcer (%p)... now %zu deadline %zu",
(void*)session->shared,
(void*)session->announcer,
(size_t)time(NULL),
(size_t)deadline);
tr_wait_msec(50); tr_wait_msec(50);
} }
@ -2161,7 +2171,8 @@ static void sessionLoadTorrents(void* vdata)
tr_sys_path_info info; tr_sys_path_info info;
char const* dirname = tr_getTorrentDir(data->session); char const* dirname = tr_getTorrentDir(data->session);
tr_sys_dir_t odir = (tr_sys_path_get_info(dirname, 0, &info, NULL) && info.type == TR_SYS_PATH_IS_DIRECTORY) ? tr_sys_dir_t odir = (tr_sys_path_get_info(dirname, 0, &info, NULL) && info.type == TR_SYS_PATH_IS_DIRECTORY) ?
tr_sys_dir_open(dirname, NULL) : TR_BAD_SYS_DIR; tr_sys_dir_open(dirname, NULL) :
TR_BAD_SYS_DIR;
if (odir != TR_BAD_SYS_DIR) if (odir != TR_BAD_SYS_DIR)
{ {
@ -2486,7 +2497,8 @@ static void loadBlocklists(tr_session* session)
tr_blocklistFileFree(b); tr_blocklistFileFree(b);
} }
else if (tr_sys_path_get_info(path, 0, &path_info, NULL) && else if (
tr_sys_path_get_info(path, 0, &path_info, NULL) &&
path_info.last_modified_at >= binname_info.last_modified_at) /* update it */ path_info.last_modified_at >= binname_info.last_modified_at) /* update it */
{ {
char* old; char* old;
@ -2673,7 +2685,8 @@ static void metainfoLookupInit(tr_session* session)
tr_sys_path_info info; tr_sys_path_info info;
char const* dirname = tr_getTorrentDir(session); char const* dirname = tr_getTorrentDir(session);
tr_sys_dir_t odir = (tr_sys_path_get_info(dirname, 0, &info, NULL) && info.type == TR_SYS_PATH_IS_DIRECTORY) ? tr_sys_dir_t odir = (tr_sys_path_get_info(dirname, 0, &info, NULL) && info.type == TR_SYS_PATH_IS_DIRECTORY) ?
tr_sys_dir_open(dirname, NULL) : TR_BAD_SYS_DIR; tr_sys_dir_open(dirname, NULL) :
TR_BAD_SYS_DIR;
if (odir != TR_BAD_SYS_DIR) if (odir != TR_BAD_SYS_DIR)
{ {
@ -3056,7 +3069,11 @@ void tr_sessionGetNextQueuedTorrents(tr_session* session, tr_direction direction
} }
else if (num_wanted < num_candidates) else if (num_wanted < num_candidates)
{ {
tr_quickfindFirstK(candidates, num_candidates, sizeof(struct TorrentAndPosition), compareTorrentAndPositions, tr_quickfindFirstK(
candidates,
num_candidates,
sizeof(struct TorrentAndPosition),
compareTorrentAndPositions,
num_wanted); num_wanted);
} }

View File

@ -28,16 +28,14 @@ typedef enum
TR_NET_OK, TR_NET_OK,
TR_NET_ERROR, TR_NET_ERROR,
TR_NET_WAIT TR_NET_WAIT
} } tr_tristate_t;
tr_tristate_t;
typedef enum typedef enum
{ {
TR_AUTO_SWITCH_UNUSED, TR_AUTO_SWITCH_UNUSED,
TR_AUTO_SWITCH_ON, TR_AUTO_SWITCH_ON,
TR_AUTO_SWITCH_OFF, TR_AUTO_SWITCH_OFF,
} } tr_auto_switch_state_t;
tr_auto_switch_state_t;
enum enum
{ {

View File

@ -18,14 +18,13 @@
**** ****
***/ ***/
struct tr_session_stats const TR_SESSION_STATS_INIT = struct tr_session_stats const TR_SESSION_STATS_INIT = {
{
.ratio = 0.0F, .ratio = 0.0F,
.uploadedBytes = 0, .uploadedBytes = 0,
.downloadedBytes = 0, .downloadedBytes = 0,
.filesAdded = 0, .filesAdded = 0,
.sessionCount = 0, .sessionCount = 0,
.secondsActive = 0 .secondsActive = 0,
}; };
/** @brief Opaque, per-session data structure for bandwidth use statistics */ /** @brief Opaque, per-session data structure for bandwidth use statistics */

View File

@ -32,8 +32,7 @@ static void handle_sigchld(int i)
{ {
/* FIXME: Only check for our own PIDs */ /* FIXME: Only check for our own PIDs */
rc = waitpid(-1, NULL, WNOHANG); rc = waitpid(-1, NULL, WNOHANG);
} } while (rc > 0 || (rc == -1 && errno == EINTR));
while (rc > 0 || (rc == -1 && errno == EINTR));
/* FIXME: Call old handler, if any */ /* FIXME: Call old handler, if any */
} }
@ -95,8 +94,7 @@ static bool tr_spawn_async_in_parent(int pipe_fd, tr_error** error)
do do
{ {
count = read(pipe_fd, &child_errno, sizeof(child_errno)); count = read(pipe_fd, &child_errno, sizeof(child_errno));
} } while (count == -1 && errno == EINTR);
while (count == -1 && errno == EINTR);
close(pipe_fd); close(pipe_fd);

View File

@ -305,7 +305,10 @@ static void append_argument(char** arguments, char const* argument)
static bool contains_batch_metachars(char const* text) static bool contains_batch_metachars(char const* text)
{ {
/* First part - chars explicitly documented by `cmd.exe /?` as "special" */ /* First part - chars explicitly documented by `cmd.exe /?` as "special" */
return strpbrk(text, "&<>()@^|" "%!^\"") != NULL; return strpbrk(
text,
"&<>()@^|"
"%!^\"") != NULL;
} }
static enum tr_app_type get_app_type(char const* app) static enum tr_app_type get_app_type(char const* app)
@ -392,17 +395,25 @@ bool tr_spawn_async(char* const* cmd, char* const* env, char const* work_dir, tr
wchar_t* current_dir = work_dir != NULL ? tr_win32_utf8_to_native(work_dir, -1) : NULL; wchar_t* current_dir = work_dir != NULL ? tr_win32_utf8_to_native(work_dir, -1) : NULL;
STARTUPINFOW si = STARTUPINFOW si = {
{
.cb = sizeof(si), .cb = sizeof(si),
.dwFlags = STARTF_USESHOWWINDOW, .dwFlags = STARTF_USESHOWWINDOW,
.wShowWindow = SW_HIDE .wShowWindow = SW_HIDE,
}; };
PROCESS_INFORMATION pi; PROCESS_INFORMATION pi;
bool const ret = CreateProcessW(NULL, cmd_line, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT | bool const ret = CreateProcessW(
CREATE_NO_WINDOW | CREATE_DEFAULT_ERROR_MODE, env_block, current_dir, &si, &pi); NULL,
cmd_line,
NULL,
NULL,
FALSE,
NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT | CREATE_NO_WINDOW | CREATE_DEFAULT_ERROR_MODE,
env_block,
current_dir,
&si,
&pi);
if (ret) if (ret)
{ {

View File

@ -154,8 +154,7 @@ bool tr_torrentIsPieceTransferAllowed(tr_torrent const* tor, tr_direction direct
bool allowed = true; bool allowed = true;
if (tr_torrentUsesSpeedLimit(tor, direction) && if (tr_torrentUsesSpeedLimit(tor, direction) && tr_torrentGetSpeedLimit_Bps(tor, direction) <= 0)
tr_torrentGetSpeedLimit_Bps(tor, direction) <= 0)
{ {
allowed = false; allowed = false;
} }
@ -200,8 +199,7 @@ static int peerIdTTL(tr_torrent const* tor)
unsigned char const* tr_torrentGetPeerId(tr_torrent* tor) unsigned char const* tr_torrentGetPeerId(tr_torrent* tor)
{ {
bool const needs_new_peer_id = bool const needs_new_peer_id = (*tor->peer_id == '\0') || // doesn't have one
(*tor->peer_id == '\0') || // doesn't have one
(!tr_torrentIsPrivate(tor) && (peerIdTTL(tor) <= 0)); // has one but it's expired (!tr_torrentIsPrivate(tor) && (peerIdTTL(tor) <= 0)); // has one but it's expired
if (needs_new_peer_id) if (needs_new_peer_id)
@ -874,8 +872,11 @@ static bool setLocalErrorIfFilesDisappeared(tr_torrent* tor)
if (disappeared) if (disappeared)
{ {
tr_deeplog_tor(tor, "%s", "[LAZY] uh oh, the files disappeared"); tr_deeplog_tor(tor, "%s", "[LAZY] uh oh, the files disappeared");
tr_torrentSetLocalError(tor, "%s", _("No data found! Ensure your drives are connected or use \"Set Location\". " tr_torrentSetLocalError(
"To re-download, remove the torrent and re-add it.")); tor,
"%s",
_("No data found! Ensure your drives are connected or use \"Set Location\". "
"To re-download, remove the torrent and re-add it."));
} }
return disappeared; return disappeared;
@ -1030,7 +1031,11 @@ static void torrentInit(tr_torrent* tor, tr_ctor const* ctor)
tr_sessionUnlock(session); tr_sessionUnlock(session);
} }
static tr_parse_result torrentParseImpl(tr_ctor const* ctor, tr_info* setmeInfo, bool* setmeHasInfo, size_t* dictLength, static tr_parse_result torrentParseImpl(
tr_ctor const* ctor,
tr_info* setmeInfo,
bool* setmeHasInfo,
size_t* dictLength,
int* setme_duplicate_id) int* setme_duplicate_id)
{ {
bool doFree; bool doFree;
@ -2197,16 +2202,14 @@ static void torrentCallScript(tr_torrent const* tor, char const* script)
char* const torrent_dir = tr_sys_path_native_separators(tr_strdup(tor->currentDir)); char* const torrent_dir = tr_sys_path_native_separators(tr_strdup(tor->currentDir));
char* const cmd[] = char* const cmd[] = {
{
tr_strdup(script), tr_strdup(script),
NULL NULL,
}; };
char* labels = tr_strjoin((char const* const*)tr_ptrArrayBase(&tor->labels), tr_ptrArraySize(&tor->labels), ","); char* labels = tr_strjoin((char const* const*)tr_ptrArrayBase(&tor->labels), tr_ptrArraySize(&tor->labels), ",");
char* const env[] = char* const env[] = {
{
tr_strdup_printf("TR_APP_VERSION=%s", SHORT_VERSION_STRING), tr_strdup_printf("TR_APP_VERSION=%s", SHORT_VERSION_STRING),
tr_strdup_printf("TR_TIME_LOCALTIME=%s", ctime_str), tr_strdup_printf("TR_TIME_LOCALTIME=%s", ctime_str),
tr_strdup_printf("TR_TORRENT_DIR=%s", torrent_dir), tr_strdup_printf("TR_TORRENT_DIR=%s", torrent_dir),
@ -2214,7 +2217,7 @@ static void torrentCallScript(tr_torrent const* tor, char const* script)
tr_strdup_printf("TR_TORRENT_ID=%d", tr_torrentId(tor)), tr_strdup_printf("TR_TORRENT_ID=%d", tr_torrentId(tor)),
tr_strdup_printf("TR_TORRENT_NAME=%s", tr_torrentName(tor)), tr_strdup_printf("TR_TORRENT_NAME=%s", tr_torrentName(tor)),
tr_strdup_printf("TR_TORRENT_LABELS=%s", labels), tr_strdup_printf("TR_TORRENT_LABELS=%s", labels),
NULL NULL,
}; };
tr_logAddTorInfo(tor, "Calling script \"%s\"", script); tr_logAddTorInfo(tor, "Calling script \"%s\"", script);
@ -2249,7 +2252,10 @@ void tr_torrentRecheckCompleteness(tr_torrent* tor)
if (recentChange) if (recentChange)
{ {
tr_logAddTorInfo(tor, _("State changed from \"%1$s\" to \"%2$s\""), getCompletionString(tor->completeness), tr_logAddTorInfo(
tor,
_("State changed from \"%1$s\" to \"%2$s\""),
getCompletionString(tor->completeness),
getCompletionString(completeness)); getCompletionString(completeness));
} }
@ -2340,7 +2346,10 @@ void tr_torrentInitFilePriority(tr_torrent* tor, tr_file_index_t fileIndex, tr_p
} }
} }
void tr_torrentSetFilePriorities(tr_torrent* tor, tr_file_index_t const* files, tr_file_index_t fileCount, void tr_torrentSetFilePriorities(
tr_torrent* tor,
tr_file_index_t const* files,
tr_file_index_t fileCount,
tr_priority_t priority) tr_priority_t priority)
{ {
TR_ASSERT(tr_isTorrent(tor)); TR_ASSERT(tr_isTorrent(tor));
@ -2552,7 +2561,11 @@ uint16_t tr_torrentGetPeerLimit(tr_torrent const* tor)
**** ****
***/ ***/
void tr_torrentGetBlockLocation(tr_torrent const* tor, tr_block_index_t block, tr_piece_index_t* piece, uint32_t* offset, void tr_torrentGetBlockLocation(
tr_torrent const* tor,
tr_block_index_t block,
tr_piece_index_t* piece,
uint32_t* offset,
uint32_t* length) uint32_t* length)
{ {
uint64_t pos = block; uint64_t pos = block;
@ -2614,8 +2627,13 @@ bool tr_torrentReqIsValid(tr_torrent const* tor, tr_piece_index_t index, uint32_
if (err != 0) if (err != 0)
{ {
tr_logAddTorDbg(tor, "index %lu offset %lu length %lu err %d\n", (unsigned long)index, (unsigned long)offset, tr_logAddTorDbg(
(unsigned long)length, err); tor,
"index %lu offset %lu length %lu err %d\n",
(unsigned long)index,
(unsigned long)offset,
(unsigned long)length,
err);
} }
return err == 0; return err == 0;
@ -2652,7 +2670,10 @@ void tr_torGetFileBlockRange(tr_torrent const* tor, tr_file_index_t const file,
} }
} }
void tr_torGetPieceBlockRange(tr_torrent const* tor, tr_piece_index_t const piece, tr_block_index_t* first, void tr_torGetPieceBlockRange(
tr_torrent const* tor,
tr_piece_index_t const piece,
tr_block_index_t* first,
tr_block_index_t* last) tr_block_index_t* last)
{ {
uint64_t offset = tor->info.pieceSize; uint64_t offset = tor->info.pieceSize;
@ -2732,8 +2753,7 @@ bool tr_torrentPieceNeedsCheck(tr_torrent const* tor, tr_piece_index_t p)
for (tr_file_index_t i = f; i < inf->fileCount && pieceHasFile(p, &inf->files[i]); ++i) for (tr_file_index_t i = f; i < inf->fileCount && pieceHasFile(p, &inf->files[i]); ++i)
{ {
if (tr_cpFileIsComplete(&tor->completion, i) && if (tr_cpFileIsComplete(&tor->completion, i) && (tr_torrentGetFileMTime(tor, i) > inf->pieces[p].timeChecked))
(tr_torrentGetFileMTime(tor, i) > inf->pieces[p].timeChecked))
{ {
return true; return true;
} }
@ -2877,7 +2897,10 @@ bool tr_torrentSetAnnounceList(tr_torrent* tor, tr_tracker_info const* trackers_
**/ **/
#define BACK_COMPAT_FUNC(oldname, newname) \ #define BACK_COMPAT_FUNC(oldname, newname) \
void oldname(tr_torrent * tor, time_t t) { newname(tor, t); } void oldname(tr_torrent* tor, time_t t) \
{ \
newname(tor, t); \
}
BACK_COMPAT_FUNC(tr_torrentSetAddedDate, tr_torrentSetDateAdded) BACK_COMPAT_FUNC(tr_torrentSetAddedDate, tr_torrentSetDateAdded)
BACK_COMPAT_FUNC(tr_torrentSetActivityDate, tr_torrentSetDateActive) BACK_COMPAT_FUNC(tr_torrentSetActivityDate, tr_torrentSetDateActive)
BACK_COMPAT_FUNC(tr_torrentSetDoneDate, tr_torrentSetDateDone) BACK_COMPAT_FUNC(tr_torrentSetDoneDate, tr_torrentSetDateDone)
@ -2946,11 +2969,10 @@ uint64_t tr_torrentGetBytesLeftToAllocate(tr_torrent const* tor)
static bool isJunkFile(char const* base) static bool isJunkFile(char const* base)
{ {
static char const* files[] = static char const* files[] = {
{
".DS_Store", ".DS_Store",
"desktop.ini", "desktop.ini",
"Thumbs.db" "Thumbs.db",
}; };
for (size_t i = 0; i < TR_N_ELEMENTS(files); ++i) for (size_t i = 0; i < TR_N_ELEMENTS(files); ++i)
@ -3307,7 +3329,11 @@ static void setLocation(void* vdata)
tr_free(data); tr_free(data);
} }
void tr_torrentSetLocation(tr_torrent* tor, char const* location, bool move_from_old_location, double volatile* setme_progress, void tr_torrentSetLocation(
tr_torrent* tor,
char const* location,
bool move_from_old_location,
double volatile* setme_progress,
int volatile* setme_state) int volatile* setme_state)
{ {
TR_ASSERT(tr_isTorrent(tor)); TR_ASSERT(tr_isTorrent(tor));
@ -3344,7 +3370,7 @@ char const* tr_torrentPrimaryMimeType(tr_torrent const* tor)
struct count* counts = tr_new0(struct count, inf->fileCount); struct count* counts = tr_new0(struct count, inf->fileCount);
size_t num_counts = 0; size_t num_counts = 0;
for (tr_file const* it = inf->files, * end = it + inf->fileCount; it != end; ++it) for (tr_file const *it = inf->files, *end = it + inf->fileCount; it != end; ++it)
{ {
char const* mime_type = tr_get_mime_type_for_filename(it->name); char const* mime_type = tr_get_mime_type_for_filename(it->name);
size_t i; size_t i;
@ -3367,7 +3393,7 @@ char const* tr_torrentPrimaryMimeType(tr_torrent const* tor)
uint64_t max_len = 0; uint64_t max_len = 0;
char const* mime_type = NULL; char const* mime_type = NULL;
for (struct count const* it = counts, *end = it + num_counts; it != end; ++it) for (struct count const *it = counts, *end = it + num_counts; it != end; ++it)
{ {
if ((max_len < it->length) && (it->mime_type != NULL)) if ((max_len < it->length) && (it->mime_type != NULL))
{ {
@ -3441,9 +3467,7 @@ static void tr_torrentPieceCompleted(tr_torrent* tor, tr_piece_index_t pieceInde
{ {
tr_file const* file = &tor->info.files[i]; tr_file const* file = &tor->info.files[i];
if ((file->firstPiece <= pieceIndex) && if ((file->firstPiece <= pieceIndex) && (pieceIndex <= file->lastPiece) && tr_cpFileIsComplete(&tor->completion, i))
(pieceIndex <= file->lastPiece) &&
tr_cpFileIsComplete(&tor->completion, i))
{ {
tr_torrentFileCompleted(tor, i); tr_torrentFileCompleted(tor, i);
} }
@ -3496,7 +3520,11 @@ void tr_torrentGotBlock(tr_torrent* tor, tr_block_index_t block)
**** ****
***/ ***/
static void find_file_in_dir(char const* name, char const* search_dir, char const** base, char const** subpath, static void find_file_in_dir(
char const* name,
char const* search_dir,
char const** base,
char const** subpath,
tr_sys_path_info* file_info) tr_sys_path_info* file_info)
{ {
char* filename = tr_buildPath(search_dir, name, NULL); char* filename = tr_buildPath(search_dir, name, NULL);
@ -3691,17 +3719,13 @@ void tr_torrentSetQueuePosition(tr_torrent* tor, int pos)
while ((walk = tr_torrentNext(tor->session, walk)) != NULL) while ((walk = tr_torrentNext(tor->session, walk)) != NULL)
{ {
if ((old_pos < pos) && if ((old_pos < pos) && (old_pos <= walk->queuePosition) && (walk->queuePosition <= pos))
(old_pos <= walk->queuePosition) &&
(walk->queuePosition <= pos))
{ {
walk->queuePosition--; walk->queuePosition--;
walk->anyDate = now; walk->anyDate = now;
} }
if ((old_pos > pos) && if ((old_pos > pos) && (pos <= walk->queuePosition) && (walk->queuePosition < old_pos))
(pos <= walk->queuePosition) &&
(walk->queuePosition < old_pos))
{ {
walk->queuePosition++; walk->queuePosition++;
walk->anyDate = now; walk->anyDate = now;
@ -3789,7 +3813,7 @@ static void torrentSetQueued(tr_torrent* tor, bool queued)
} }
} }
void tr_torrentSetQueueStartCallback(tr_torrent* torrent, void (* callback)(tr_torrent*, void*), void* user_data) void tr_torrentSetQueueStartCallback(tr_torrent* torrent, void (*callback)(tr_torrent*, void*), void* user_data)
{ {
torrent->queue_started_callback = callback; torrent->queue_started_callback = callback;
torrent->queue_started_user_data = user_data; torrent->queue_started_user_data = user_data;
@ -4033,7 +4057,11 @@ static void torrentRenamePath(void* vdata)
tr_free(data); tr_free(data);
} }
void tr_torrentRenamePath(tr_torrent* tor, char const* oldpath, char const* newname, tr_torrent_rename_done_func callback, void tr_torrentRenamePath(
tr_torrent* tor,
char const* oldpath,
char const* newname,
tr_torrent_rename_done_func callback,
void* callback_user_data) void* callback_user_data)
{ {
struct rename_data* data; struct rename_data* data;

View File

@ -68,13 +68,23 @@ bool tr_torrentReqIsValid(tr_torrent const* tor, tr_piece_index_t index, uint32_
uint64_t tr_pieceOffset(tr_torrent const* tor, tr_piece_index_t index, uint32_t offset, uint32_t length); uint64_t tr_pieceOffset(tr_torrent const* tor, tr_piece_index_t index, uint32_t offset, uint32_t length);
void tr_torrentGetBlockLocation(tr_torrent const* tor, tr_block_index_t block, tr_piece_index_t* piece, uint32_t* offset, void tr_torrentGetBlockLocation(
tr_torrent const* tor,
tr_block_index_t block,
tr_piece_index_t* piece,
uint32_t* offset,
uint32_t* length); uint32_t* length);
void tr_torGetFileBlockRange(tr_torrent const* tor, tr_file_index_t const file, tr_block_index_t* first, void tr_torGetFileBlockRange(
tr_torrent const* tor,
tr_file_index_t const file,
tr_block_index_t* first,
tr_block_index_t* last); tr_block_index_t* last);
void tr_torGetPieceBlockRange(tr_torrent const* tor, tr_piece_index_t const piece, tr_block_index_t* first, void tr_torGetPieceBlockRange(
tr_torrent const* tor,
tr_piece_index_t const piece,
tr_block_index_t* first,
tr_block_index_t* last); tr_block_index_t* last);
void tr_torrentInitFilePriority(tr_torrent* tor, tr_file_index_t fileIndex, tr_priority_t priority); void tr_torrentInitFilePriority(tr_torrent* tor, tr_file_index_t fileIndex, tr_priority_t priority);
@ -105,8 +115,7 @@ typedef enum
TR_VERIFY_NONE, TR_VERIFY_NONE,
TR_VERIFY_WAIT, TR_VERIFY_WAIT,
TR_VERIFY_NOW TR_VERIFY_NOW
} } tr_verify_state;
tr_verify_state;
void tr_torrentSetVerifyState(tr_torrent* tor, tr_verify_state state); void tr_torrentSetVerifyState(tr_torrent* tor, tr_verify_state state);
@ -223,7 +232,7 @@ struct tr_torrent
void* idle_limit_hit_func_user_data; void* idle_limit_hit_func_user_data;
void* queue_started_user_data; void* queue_started_user_data;
void (* queue_started_callback)(tr_torrent*, void* queue_started_user_data); void (*queue_started_callback)(tr_torrent*, void* queue_started_user_data);
bool isRunning; bool isRunning;
bool isStopping; bool isStopping;

Some files were not shown because too many files have changed in this diff Show More