Switch to clang-format for code formatting, include Mac client
This commit is contained in:
parent
409f59889b
commit
db3d40d0ed
|
@ -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
|
64
cli/cli.c
64
cli/cli.c
|
@ -45,14 +45,14 @@
|
|||
#define MEM_T_STR "TiB"
|
||||
|
||||
#define DISK_K 1000
|
||||
#define DISK_B_STR "B"
|
||||
#define DISK_B_STR "B"
|
||||
#define DISK_K_STR "kB"
|
||||
#define DISK_M_STR "MB"
|
||||
#define DISK_G_STR "GB"
|
||||
#define DISK_T_STR "TB"
|
||||
|
||||
#define SPEED_K 1000
|
||||
#define SPEED_B_STR "B/s"
|
||||
#define SPEED_B_STR "B/s"
|
||||
#define SPEED_K_STR "kB/s"
|
||||
#define SPEED_M_STR "MB/s"
|
||||
#define SPEED_G_STR "GB/s"
|
||||
|
@ -73,11 +73,10 @@ static sig_atomic_t manualUpdate = false;
|
|||
|
||||
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', "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 },
|
||||
{ 910, "encryption-required", "Encrypt all peer connections", "er", 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 },
|
||||
{ '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>" },
|
||||
{ '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 },
|
||||
{ 'v', "verify", "Verify the specified torrent", "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)
|
||||
{
|
||||
return "A fast and easy BitTorrent client\n"
|
||||
// clang-format off
|
||||
return
|
||||
"A fast and easy BitTorrent client\n"
|
||||
"\n"
|
||||
"Usage: " MY_READABLE_NAME " [options] <file|url|magnet>";
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
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 void onTorrentFileDownloaded(tr_session* session, bool did_connect, bool did_timeout, long response_code,
|
||||
void const* response, size_t response_byte_count, void* ctor)
|
||||
static void onTorrentFileDownloaded(
|
||||
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(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)
|
||||
{
|
||||
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));
|
||||
}
|
||||
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_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_truncd(100 * st->percentDone, 1), st->peersSendingToUs, st->peersConnected, dnStr, st->peersGettingFromUs, upStr,
|
||||
tr_snprintf(
|
||||
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);
|
||||
}
|
||||
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_strlratio(ratioStr, st->ratio, sizeof(ratioStr));
|
||||
|
||||
tr_snprintf(buf, buflen, "Seeding, uploading to %d of %d peer(s), %s [%s]", st->peersGettingFromUs, st->peersConnected,
|
||||
upStr, ratioStr);
|
||||
tr_snprintf(
|
||||
buf,
|
||||
buflen,
|
||||
"Seeding, uploading to %d of %d peer(s), %s [%s]",
|
||||
st->peersGettingFromUs,
|
||||
st->peersConnected,
|
||||
upStr,
|
||||
ratioStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -262,8 +288,7 @@ int tr_main(int argc, char* argv[])
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (tr_variantDictFindStr(&settings, TR_KEY_download_dir, &str, NULL) &&
|
||||
!tr_sys_path_exists(str, NULL))
|
||||
if (tr_variantDictFindStr(&settings, TR_KEY_download_dir, &str, NULL) && !tr_sys_path_exists(str, NULL))
|
||||
{
|
||||
tr_error* error = NULL;
|
||||
|
||||
|
@ -337,12 +362,11 @@ int tr_main(int argc, char* argv[])
|
|||
{
|
||||
char line[LINEWIDTH];
|
||||
tr_stat const* st;
|
||||
char const* messageName[] =
|
||||
{
|
||||
char const* messageName[] = {
|
||||
NULL,
|
||||
"Tracker gave a warning:",
|
||||
"Tracker gave an error:",
|
||||
"Error:"
|
||||
"Error:",
|
||||
};
|
||||
|
||||
tr_wait_msec(200);
|
||||
|
@ -377,7 +401,7 @@ int tr_main(int argc, char* argv[])
|
|||
}
|
||||
|
||||
getStatusStr(st, line, sizeof(line));
|
||||
printf("\r%-*s", LINEWIDTH, line);
|
||||
printf("\r%-*s", TR_ARG_TUPLE(LINEWIDTH, line));
|
||||
|
||||
if (messageName[st->error])
|
||||
{
|
||||
|
|
|
@ -3,70 +3,69 @@
|
|||
# Usage: ./code_style.sh
|
||||
# Usage: ./code_style.sh --check
|
||||
|
||||
set -o noglob
|
||||
|
||||
if [[ "x$1" == *"check"* ]]; then
|
||||
echo "checking code format"
|
||||
else
|
||||
fix=1
|
||||
fi
|
||||
|
||||
root="$(git rev-parse --show-toplevel)"
|
||||
if [ -n "${root}" ]; then
|
||||
cd "${root}" || exit 1
|
||||
fi
|
||||
root="$(dirname "$0")"
|
||||
root="$(cd "${root}" && pwd)"
|
||||
cd "${root}" || exit 1
|
||||
|
||||
skipfiles=(
|
||||
libtransmission/ConvertUTF\.[ch]
|
||||
libtransmission/jsonsl\.[ch]
|
||||
libtransmission/wildmat\.c
|
||||
cfile_includes=(
|
||||
'*.c'
|
||||
'*.cc'
|
||||
'*.h'
|
||||
'*.m'
|
||||
)
|
||||
cfile_candidates=(
|
||||
cli/*\.[ch]
|
||||
daemon/*\.[ch]
|
||||
gtk/*\.[ch]
|
||||
libtransmission/*\.[ch]
|
||||
qt/*\.cc
|
||||
qt/*\.h
|
||||
tests/*/*\.cc
|
||||
tests/*/*\.h
|
||||
utils/*\.[ch]
|
||||
cfile_excludes=(
|
||||
'libtransmission/ConvertUTF.*'
|
||||
'libtransmission/jsonsl.*'
|
||||
'libtransmission/wildmat.*'
|
||||
'macosx/Sparkle.framework/*'
|
||||
'macosx/VDKQueue/*'
|
||||
'third-party/*'
|
||||
'web/*'
|
||||
)
|
||||
for file in "${cfile_candidates[@]}"; do
|
||||
if [[ ! " ${skipfiles[*]} " =~ ${file} ]]; then
|
||||
cfiles+=("${file}");
|
||||
fi
|
||||
done
|
||||
|
||||
get_find_path_args() {
|
||||
local args=$(printf " -o -path ./%s" "$@")
|
||||
echo "${args:4}"
|
||||
}
|
||||
|
||||
find_cfiles() {
|
||||
find . \( $(get_find_path_args "${cfile_includes[@]}") \) ! \( $(get_find_path_args "${cfile_excludes[@]}") \) "$@"
|
||||
}
|
||||
|
||||
# format C/C++
|
||||
cores=$(($(nproc) + 1))
|
||||
if [ -n "$fix" ]; then
|
||||
printf "%s\0" "${cfiles[@]}" | xargs -0 -P$cores -I FILE uncrustify -c uncrustify.cfg --no-backup -q FILE
|
||||
else
|
||||
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
|
||||
clang_format_args="$([ -n "$fix" ] && echo '-i' || echo '--dry-run --Werror')"
|
||||
if ! find_cfiles -exec clang-format $clang_format_args '{}' '+'; then
|
||||
[ -n "$fix" ] || echo 'C/C++ code needs formatting'
|
||||
exitcode=1
|
||||
fi
|
||||
|
||||
# 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
|
||||
echo "$matches"
|
||||
exitcode=1
|
||||
fi
|
||||
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
|
||||
|
||||
# format JS
|
||||
cd "${root}/web" || exit 1
|
||||
if [ -n "$fix" ]; then
|
||||
cd "${root}/web" && yarn --silent install && yarn --silent 'lint:fix'
|
||||
elif ! yarn -s install; then
|
||||
echo 'JS code could not be checked -- "yarn install" failed'
|
||||
yarn_args='--silent --no-progress --non-interactive'
|
||||
yarn_lint_args="$([ -n "$fix" ] && echo 'lint:fix' || echo 'lint')"
|
||||
if ! yarn $yarn_args install; then
|
||||
[ -n "$fix" ] || echo 'JS code could not be checked -- "yarn install" failed'
|
||||
exitcode=1
|
||||
elif ! yarn --silent lint; then
|
||||
echo 'JS code needs formatting'
|
||||
elif ! yarn $yarn_args $yarn_lint_args; then
|
||||
[ -n "$fix" ] || echo 'JS code needs formatting'
|
||||
exitcode=1
|
||||
fi
|
||||
|
||||
|
|
|
@ -61,13 +61,12 @@ static void do_log_system_error(char const* file, int line, tr_log_level level,
|
|||
do \
|
||||
{ \
|
||||
DWORD const local_code = (code); \
|
||||
\
|
||||
\
|
||||
if (tr_logLevelIsActive((level))) \
|
||||
{ \
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
SERVICE_STATUS status;
|
||||
status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
|
||||
status.dwCurrentState = new_state;
|
||||
status.dwControlsAccepted = new_state != SERVICE_RUNNING ? 0 : SERVICE_ACCEPT_PRESHUTDOWN | SERVICE_ACCEPT_SHUTDOWN |
|
||||
SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PARAMCHANGE;
|
||||
status.dwControlsAccepted = new_state != SERVICE_RUNNING ?
|
||||
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.dwServiceSpecificExitCode = service_specific_exit_code;
|
||||
status.dwCheckPoint = check_point;
|
||||
|
@ -244,10 +248,9 @@ bool dtr_daemon(dtr_callbacks const* cb, void* cb_arg, bool foreground, int* exi
|
|||
}
|
||||
else
|
||||
{
|
||||
SERVICE_TABLE_ENTRY const service_table[] =
|
||||
{
|
||||
SERVICE_TABLE_ENTRY const service_table[] = {
|
||||
{ (LPWSTR)service_name, &service_main },
|
||||
{ NULL, NULL }
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
if (!StartServiceCtrlDispatcherW(service_table))
|
||||
|
|
|
@ -91,7 +91,9 @@ static struct event_base* ev_base = NULL;
|
|||
|
||||
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"
|
||||
"\n"
|
||||
MY_NAME " is a headless Transmission session\n"
|
||||
|
@ -99,10 +101,10 @@ static char const* getUsage(void)
|
|||
"or the web interface.\n"
|
||||
"\n"
|
||||
"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>" },
|
||||
{ 'b', "blocklist", "Enable 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>" },
|
||||
{ 'm', "portmap", "Enable portmapping via NAT-PMP or UPnP", "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,
|
||||
"<limit>" },
|
||||
{ 'l', "peerlimit-torrent", "Maximum number of peers per torrent (Default: " TR_DEFAULT_PEER_LIMIT_TORRENT_STR ")", "l",
|
||||
true, "<limit>" },
|
||||
{ 'L',
|
||||
"peerlimit-global",
|
||||
"Maximum overall number of peers (Default: " TR_DEFAULT_PEER_LIMIT_GLOBAL_STR ")",
|
||||
"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 },
|
||||
{ 911, "encryption-preferred", "Prefer encrypted peer connections", "ep", 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-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>" },
|
||||
{ 953, "global-seedratio", "All torrents, unless overridden by a per-torrent setting, should seed until a specific ratio",
|
||||
"gsr", true, "ratio" },
|
||||
{ 954, "no-global-seedratio", "All torrents, unless overridden by a per-torrent setting, should seed regardless of ratio",
|
||||
"GSR", false, NULL },
|
||||
{ 953,
|
||||
"global-seedratio",
|
||||
"All torrents, unless overridden by a per-torrent setting, should seed until a specific ratio",
|
||||
"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>" },
|
||||
{ 0, NULL, NULL, NULL, false, NULL }
|
||||
};
|
||||
|
@ -156,8 +174,11 @@ static bool reopen_log_file(char const* filename)
|
|||
{
|
||||
tr_error* error = NULL;
|
||||
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,
|
||||
0666, &error);
|
||||
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,
|
||||
0666,
|
||||
&error);
|
||||
|
||||
if (new_log_file == TR_BAD_SYS_FILE)
|
||||
{
|
||||
|
@ -359,7 +380,10 @@ static void periodicUpdate(evutil_socket_t fd, short what, void* context)
|
|||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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 c;
|
||||
|
@ -668,7 +698,10 @@ static int daemon_start(void* raw_arg, bool foreground)
|
|||
if (!tr_str_is_empty(pid_filename))
|
||||
{
|
||||
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);
|
||||
|
||||
if (fp != TR_BAD_SYS_FILE)
|
||||
|
@ -872,8 +905,7 @@ int tr_main(int argc, char* argv[])
|
|||
return ret;
|
||||
}
|
||||
|
||||
dtr_callbacks const cb =
|
||||
{
|
||||
dtr_callbacks const cb = {
|
||||
.on_start = &daemon_start,
|
||||
.on_stop = &daemon_stop,
|
||||
.on_reconfigure = &daemon_reconfigure,
|
||||
|
|
|
@ -12,10 +12,9 @@ struct tr_error;
|
|||
|
||||
typedef struct dtr_callbacks
|
||||
{
|
||||
int (* on_start)(void* arg, bool foreground);
|
||||
void (* on_stop)(void* arg);
|
||||
void (* on_reconfigure)(void* arg);
|
||||
}
|
||||
dtr_callbacks;
|
||||
int (*on_start)(void* arg, bool foreground);
|
||||
void (*on_stop)(void* arg);
|
||||
void (*on_reconfigure)(void* arg);
|
||||
} dtr_callbacks;
|
||||
|
||||
bool dtr_daemon(dtr_callbacks const* cb, void* cb_arg, bool foreground, int* exit_code, struct tr_error** error);
|
||||
|
|
|
@ -4,7 +4,10 @@ services:
|
|||
code_style:
|
||||
build: docker/code_style
|
||||
volumes:
|
||||
- .:/src
|
||||
- ./code_style.sh:/code_style.sh:ro
|
||||
- ./format:/format:ro
|
||||
command: ["/bin/bash", "-c", "cd /src && ./code_style.sh --check"]
|
||||
- .:/src
|
||||
working_dir: /src
|
||||
command:
|
||||
- ./code_style.sh
|
||||
- --check
|
||||
environment:
|
||||
HOME: /tmp
|
||||
|
|
|
@ -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/
|
||||
|
|
|
@ -26,8 +26,7 @@ static void action_cb(GtkAction* a, gpointer 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-name", NULL, N_("Sort by _Name"), NULL, NULL, 1 },
|
||||
{ "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-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-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)
|
||||
|
@ -51,10 +50,9 @@ static void sort_changed_cb(GtkAction* action, GtkRadioAction* current, gpointer
|
|||
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-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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
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 },
|
||||
{ "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 },
|
||||
{ "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-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 },
|
||||
{ "torrent-menu", NULL, N_("_Torrent"), 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-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-now", "media-playback-start", N_("Start _Now"), "<shift><control>S", N_("Start torrent now"),
|
||||
G_CALLBACK(action_cb) },
|
||||
{ "torrent-start-now",
|
||||
"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) },
|
||||
{ "donate", NULL, N_("_Donate"), NULL, 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) },
|
||||
{ "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) },
|
||||
{ "show-torrent-properties", "document-properties", N_("_Properties"), "<alt>Return", N_("Torrent properties"), G_CALLBACK(
|
||||
action_cb) },
|
||||
{ "show-torrent-properties",
|
||||
"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) },
|
||||
{ "show-about-dialog", "help-about", N_("_About"), NULL, 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-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) },
|
||||
{ "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
|
||||
{
|
||||
char const* filename;
|
||||
char const* name;
|
||||
}
|
||||
BuiltinIconInfo;
|
||||
} BuiltinIconInfo;
|
||||
|
||||
static BuiltinIconInfo const my_fallback_icons[] =
|
||||
{
|
||||
{ "logo-48", WINDOW_ICON },
|
||||
{ "logo-24", TRAY_ICON },
|
||||
{ "logo-48", NOTIFICATION_ICON },
|
||||
{ "lock", "transmission-lock" },
|
||||
{ "utilities", "utilities" },
|
||||
{ "turtle-blue", "alt-speed-on" },
|
||||
{ "turtle-grey", "alt-speed-off" },
|
||||
{ "ratio", "ratio" }
|
||||
static BuiltinIconInfo const my_fallback_icons[] = {
|
||||
{ "logo-48", WINDOW_ICON }, //
|
||||
{ "logo-24", TRAY_ICON }, //
|
||||
{ "logo-48", NOTIFICATION_ICON }, //
|
||||
{ "lock", "transmission-lock" }, //
|
||||
{ "utilities", "utilities" }, //
|
||||
{ "turtle-blue", "alt-speed-on" }, //
|
||||
{ "turtle-grey", "alt-speed-off" }, //
|
||||
{ "ratio", "ratio" }, //
|
||||
};
|
||||
|
||||
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,
|
||||
G_CALLBACK(sort_changed_cb), NULL);
|
||||
gtk_action_group_add_radio_actions(
|
||||
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);
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
gtk_action_group_add_actions(action_group, entries, n_entries, callback_user_data);
|
||||
|
|
281
gtk/details.c
281
gtk/details.c
|
@ -477,9 +477,9 @@ static void onComboEnumChanged(GtkComboBox* combo_box, struct DetailsImpl* di)
|
|||
static GtkWidget* ratio_combo_new(void)
|
||||
{
|
||||
GtkWidget* w = gtr_combo_box_new_enum(
|
||||
_("Use global settings"), TR_RATIOLIMIT_GLOBAL,
|
||||
_("Seed regardless of ratio"), TR_RATIOLIMIT_UNLIMITED,
|
||||
_("Stop seeding at ratio:"), TR_RATIOLIMIT_SINGLE,
|
||||
TR_ARG_TUPLE(_("Use global settings"), TR_RATIOLIMIT_GLOBAL),
|
||||
TR_ARG_TUPLE(_("Seed regardless of ratio"), TR_RATIOLIMIT_UNLIMITED),
|
||||
TR_ARG_TUPLE(_("Stop seeding at ratio:"), TR_RATIOLIMIT_SINGLE),
|
||||
NULL);
|
||||
g_object_set_qdata(G_OBJECT(w), ARG_KEY, GINT_TO_POINTER(TR_KEY_seedRatioMode));
|
||||
return w;
|
||||
|
@ -488,9 +488,9 @@ static GtkWidget* ratio_combo_new(void)
|
|||
static GtkWidget* idle_combo_new(void)
|
||||
{
|
||||
GtkWidget* w = gtr_combo_box_new_enum(
|
||||
_("Use global settings"), TR_IDLELIMIT_GLOBAL,
|
||||
_("Seed regardless of activity"), TR_IDLELIMIT_UNLIMITED,
|
||||
_("Stop seeding if idle for N minutes:"), TR_IDLELIMIT_SINGLE,
|
||||
TR_ARG_TUPLE(_("Use global settings"), TR_IDLELIMIT_GLOBAL),
|
||||
TR_ARG_TUPLE(_("Seed regardless of activity"), TR_IDLELIMIT_UNLIMITED),
|
||||
TR_ARG_TUPLE(_("Stop seeding if idle for N minutes:"), TR_IDLELIMIT_SINGLE),
|
||||
NULL);
|
||||
g_object_set_qdata(G_OBJECT(w), ARG_KEY, GINT_TO_POINTER(TR_KEY_seedIdleMode));
|
||||
return w;
|
||||
|
@ -908,8 +908,13 @@ static void refreshInfo(struct DetailsImpl* di, tr_torrent** torrents, int n)
|
|||
{
|
||||
char piecebuf[128];
|
||||
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,
|
||||
pieces, piecebuf);
|
||||
g_snprintf(
|
||||
buf,
|
||||
sizeof(buf),
|
||||
ngettext("%1$s (%2$'d piece @ %3$s)", "%1$s (%2$'d pieces @ %3$s)", pieces),
|
||||
sizebuf,
|
||||
pieces,
|
||||
piecebuf);
|
||||
str = buf;
|
||||
}
|
||||
else
|
||||
|
@ -966,7 +971,13 @@ static void refreshInfo(struct DetailsImpl* di, tr_torrent** torrents, int n)
|
|||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1258,7 +1269,8 @@ static char const* getWebseedColumnNames(int column)
|
|||
|
||||
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_BOOLEAN, /* was-updated */
|
||||
G_TYPE_STRING, /* url */
|
||||
|
@ -1351,7 +1363,8 @@ static char const* getPeerColumnName(int column)
|
|||
|
||||
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_BOOLEAN, /* was-updated */
|
||||
G_TYPE_STRING, /* address */
|
||||
|
@ -1379,7 +1392,11 @@ static GtkListStore* peer_store_new(void)
|
|||
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)
|
||||
{
|
||||
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]);
|
||||
}
|
||||
|
||||
gtk_list_store_set(store, iter,
|
||||
PEER_COL_ADDRESS, peer->addr,
|
||||
PEER_COL_ADDRESS_COLLATED, collated_name,
|
||||
PEER_COL_CLIENT, client,
|
||||
PEER_COL_ENCRYPTION_STOCK_ID, peer->isEncrypted ? "transmission-lock" : NULL,
|
||||
PEER_COL_KEY, key,
|
||||
PEER_COL_TORRENT_NAME, torrentName,
|
||||
gtk_list_store_set(
|
||||
store,
|
||||
iter,
|
||||
TR_ARG_TUPLE(PEER_COL_ADDRESS, peer->addr),
|
||||
TR_ARG_TUPLE(PEER_COL_ADDRESS_COLLATED, collated_name),
|
||||
TR_ARG_TUPLE(PEER_COL_CLIENT, client),
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
gtk_list_store_set(store, iter,
|
||||
PEER_COL_PROGRESS, (int)(100.0 * peer->progress),
|
||||
PEER_COL_UPLOAD_REQUEST_COUNT_INT, peer->pendingReqsToClient,
|
||||
PEER_COL_UPLOAD_REQUEST_COUNT_STRING, up_count,
|
||||
PEER_COL_DOWNLOAD_REQUEST_COUNT_INT, peer->pendingReqsToPeer,
|
||||
PEER_COL_DOWNLOAD_REQUEST_COUNT_STRING, down_count,
|
||||
PEER_COL_DOWNLOAD_RATE_DOUBLE, peer->rateToClient_KBps,
|
||||
PEER_COL_DOWNLOAD_RATE_STRING, down_speed,
|
||||
PEER_COL_UPLOAD_RATE_DOUBLE, peer->rateToPeer_KBps,
|
||||
PEER_COL_UPLOAD_RATE_STRING, up_speed,
|
||||
PEER_COL_FLAGS, peer->flagStr,
|
||||
PEER_COL_WAS_UPDATED, TRUE,
|
||||
PEER_COL_BLOCKS_DOWNLOADED_COUNT_INT, (int)peer->blocksToClient,
|
||||
PEER_COL_BLOCKS_DOWNLOADED_COUNT_STRING, blocks_to_client,
|
||||
PEER_COL_BLOCKS_UPLOADED_COUNT_INT, (int)peer->blocksToPeer,
|
||||
PEER_COL_BLOCKS_UPLOADED_COUNT_STRING, blocks_to_peer,
|
||||
PEER_COL_REQS_CANCELLED_BY_CLIENT_COUNT_INT, (int)peer->cancelsToPeer,
|
||||
PEER_COL_REQS_CANCELLED_BY_CLIENT_COUNT_STRING, cancelled_by_client,
|
||||
PEER_COL_REQS_CANCELLED_BY_PEER_COUNT_INT, (int)peer->cancelsToClient,
|
||||
PEER_COL_REQS_CANCELLED_BY_PEER_COUNT_STRING, cancelled_by_peer,
|
||||
gtk_list_store_set(
|
||||
store,
|
||||
iter,
|
||||
TR_ARG_TUPLE(PEER_COL_PROGRESS, (int)(100.0 * peer->progress)),
|
||||
TR_ARG_TUPLE(PEER_COL_UPLOAD_REQUEST_COUNT_INT, peer->pendingReqsToClient),
|
||||
TR_ARG_TUPLE(PEER_COL_UPLOAD_REQUEST_COUNT_STRING, up_count),
|
||||
TR_ARG_TUPLE(PEER_COL_DOWNLOAD_REQUEST_COUNT_INT, peer->pendingReqsToPeer),
|
||||
TR_ARG_TUPLE(PEER_COL_DOWNLOAD_REQUEST_COUNT_STRING, down_count),
|
||||
TR_ARG_TUPLE(PEER_COL_DOWNLOAD_RATE_DOUBLE, peer->rateToClient_KBps),
|
||||
TR_ARG_TUPLE(PEER_COL_DOWNLOAD_RATE_STRING, down_speed),
|
||||
TR_ARG_TUPLE(PEER_COL_UPLOAD_RATE_DOUBLE, peer->rateToPeer_KBps),
|
||||
TR_ARG_TUPLE(PEER_COL_UPLOAD_RATE_STRING, up_speed),
|
||||
TR_ARG_TUPLE(PEER_COL_FLAGS, peer->flagStr),
|
||||
TR_ARG_TUPLE(PEER_COL_WAS_UPDATED, TRUE),
|
||||
TR_ARG_TUPLE(PEER_COL_BLOCKS_DOWNLOADED_COUNT_INT, (int)peer->blocksToClient),
|
||||
TR_ARG_TUPLE(PEER_COL_BLOCKS_DOWNLOADED_COUNT_STRING, blocks_to_client),
|
||||
TR_ARG_TUPLE(PEER_COL_BLOCKS_UPLOADED_COUNT_INT, (int)peer->blocksToPeer),
|
||||
TR_ARG_TUPLE(PEER_COL_BLOCKS_UPLOADED_COUNT_STRING, blocks_to_peer),
|
||||
TR_ARG_TUPLE(PEER_COL_REQS_CANCELLED_BY_CLIENT_COUNT_INT, (int)peer->cancelsToPeer),
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1510,8 +1531,7 @@ static void refreshPeerList(struct DetailsImpl* di, tr_torrent** torrents, int n
|
|||
do
|
||||
{
|
||||
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 */
|
||||
|
@ -1608,8 +1628,7 @@ static void refreshWebseedList(struct DetailsImpl* di, tr_torrent** torrents, in
|
|||
do
|
||||
{
|
||||
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 */
|
||||
|
@ -1630,10 +1649,7 @@ static void refreshWebseedList(struct DetailsImpl* di, tr_torrent** torrents, in
|
|||
{
|
||||
GtkTreePath* p;
|
||||
gtk_list_store_append(store, &iter);
|
||||
gtk_list_store_set(store, &iter,
|
||||
WEBSEED_COL_URL, url,
|
||||
WEBSEED_COL_KEY, key,
|
||||
-1);
|
||||
gtk_list_store_set(store, &iter, TR_ARG_TUPLE(WEBSEED_COL_URL, url), TR_ARG_TUPLE(WEBSEED_COL_KEY, key), -1);
|
||||
p = gtk_tree_model_get_path(model, &iter);
|
||||
g_hash_table_insert(hash, g_strdup(key), gtk_tree_row_reference_new(model, 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));
|
||||
}
|
||||
|
||||
gtk_list_store_set(store, &iter,
|
||||
WEBSEED_COL_DOWNLOAD_RATE_DOUBLE, speeds_KBps[j],
|
||||
WEBSEED_COL_DOWNLOAD_RATE_STRING, buf,
|
||||
WEBSEED_COL_WAS_UPDATED, TRUE,
|
||||
gtk_list_store_set(
|
||||
store,
|
||||
&iter,
|
||||
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);
|
||||
|
||||
gtk_tree_path_free(p);
|
||||
|
@ -1717,7 +1735,12 @@ static void refreshPeers(struct DetailsImpl* di, tr_torrent** torrents, int 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)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
|
@ -1732,10 +1755,12 @@ static gboolean onPeerViewQueryTooltip(GtkWidget* widget, gint x, gint y, gboole
|
|||
struct DetailsImpl* di = gdi;
|
||||
GString* gstr = di->gstr;
|
||||
|
||||
gtk_tree_model_get(model, &iter,
|
||||
PEER_COL_TORRENT_NAME, &name,
|
||||
PEER_COL_ADDRESS, &addr,
|
||||
PEER_COL_FLAGS, &flagstr,
|
||||
gtk_tree_model_get(
|
||||
model,
|
||||
&iter,
|
||||
TR_ARG_TUPLE(PEER_COL_TORRENT_NAME, &name),
|
||||
TR_ARG_TUPLE(PEER_COL_ADDRESS, &addr),
|
||||
TR_ARG_TUPLE(PEER_COL_FLAGS, &flagstr),
|
||||
-1);
|
||||
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* 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);
|
||||
ret = vbox;
|
||||
return ret;
|
||||
|
@ -2109,18 +2140,32 @@ static void appendAnnounceInfo(tr_tracker_stat const* const st, time_t const now
|
|||
|
||||
if (st->lastAnnounceSucceeded)
|
||||
{
|
||||
g_string_append_printf(gstr, _("Got a list of %1$s%2$'d peers%3$s %4$s ago"),
|
||||
success_markup_begin, st->lastAnnouncePeerCount, success_markup_end, timebuf);
|
||||
g_string_append_printf(
|
||||
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)
|
||||
{
|
||||
g_string_append_printf(gstr, _("Peer list request %1$stimed out%2$s %3$s ago; will retry"),
|
||||
timeout_markup_begin, timeout_markup_end, timebuf);
|
||||
g_string_append_printf(
|
||||
gstr,
|
||||
_("Peer list request %1$stimed out%2$s %3$s ago; will retry"),
|
||||
timeout_markup_begin,
|
||||
timeout_markup_end,
|
||||
timebuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_string_append_printf(gstr, _("Got an error %1$s\"%2$s\"%3$s %4$s ago"), err_markup_begin,
|
||||
st->lastAnnounceResult, err_markup_end, timebuf);
|
||||
g_string_append_printf(
|
||||
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)
|
||||
{
|
||||
g_string_append_printf(gstr, _("Tracker had %s%'d seeders and %'d leechers%s %s ago"), success_markup_begin,
|
||||
st->seederCount, st->leecherCount, success_markup_end, timebuf);
|
||||
g_string_append_printf(
|
||||
gstr,
|
||||
_("Tracker had %s%'d seeders and %'d leechers%s %s ago"),
|
||||
success_markup_begin,
|
||||
st->seederCount,
|
||||
st->leecherCount,
|
||||
success_markup_end,
|
||||
timebuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_string_append_printf(gstr, _("Got a scrape error \"%s%s%s\" %s ago"), err_markup_begin,
|
||||
st->lastScrapeResult, err_markup_end, timebuf);
|
||||
g_string_append_printf(
|
||||
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
|
||||
g_string_append(gstr, st->isBackup ? "<i>" : "<b>");
|
||||
char* const str = key != NULL ?
|
||||
g_markup_printf_escaped("%s - %s", st->host, key) :
|
||||
g_markup_printf_escaped("%s", st->host);
|
||||
char* const str = key != NULL ? g_markup_printf_escaped("%s - %s", st->host, key) : g_markup_printf_escaped("%s", st->host);
|
||||
g_string_append(gstr, str);
|
||||
g_free(str);
|
||||
g_string_append(gstr, st->isBackup ? "</i>" : "</b>");
|
||||
|
@ -2327,8 +2381,7 @@ static void refreshTracker(struct DetailsImpl* di, tr_torrent** torrents, int n)
|
|||
do
|
||||
{
|
||||
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 */
|
||||
|
@ -2348,10 +2401,13 @@ static void refreshTracker(struct DetailsImpl* di, tr_torrent** torrents, int n)
|
|||
|
||||
if (g_hash_table_lookup(hash, gstr->str) == NULL)
|
||||
{
|
||||
gtk_list_store_insert_with_values(store, &iter, -1,
|
||||
TRACKER_COL_TORRENT_ID, torrent_id,
|
||||
TRACKER_COL_TRACKER_ID, st->id,
|
||||
TRACKER_COL_KEY, gstr->str,
|
||||
gtk_list_store_insert_with_values(
|
||||
store,
|
||||
&iter,
|
||||
-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);
|
||||
|
||||
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 */
|
||||
g_string_truncate(gstr, 0);
|
||||
buildTrackerSummary(gstr, summary_name, st, showScrape);
|
||||
gtk_list_store_set(store, &iter,
|
||||
TRACKER_COL_TEXT, gstr->str,
|
||||
TRACKER_COL_IS_BACKUP, st->isBackup,
|
||||
TRACKER_COL_TRACKER_ID, st->id,
|
||||
TRACKER_COL_WAS_UPDATED, TRUE,
|
||||
gtk_list_store_set(
|
||||
store,
|
||||
&iter,
|
||||
TR_ARG_TUPLE(TRACKER_COL_TEXT, gstr->str),
|
||||
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);
|
||||
|
||||
/* cleanup */
|
||||
|
@ -2497,10 +2555,16 @@ static void on_edit_trackers_response(GtkDialog* dialog, int response, gpointer
|
|||
else
|
||||
{
|
||||
char const* text = _("List contains invalid URLs");
|
||||
GtkWidget* w = gtk_message_dialog_new(GTK_WINDOW(
|
||||
dialog), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s",
|
||||
GtkWidget* w = gtk_message_dialog_new(
|
||||
GTK_WINDOW(dialog),
|
||||
GTK_DIALOG_MODAL,
|
||||
GTK_MESSAGE_ERROR,
|
||||
GTK_BUTTONS_CLOSE,
|
||||
"%s",
|
||||
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."));
|
||||
gtk_dialog_run(GTK_DIALOG(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_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,
|
||||
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
||||
_("_Save"), GTK_RESPONSE_ACCEPT,
|
||||
d = gtk_dialog_new_with_buttons(
|
||||
gstr->str,
|
||||
win,
|
||||
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
TR_ARG_TUPLE(_("_Cancel"), GTK_RESPONSE_CANCEL),
|
||||
TR_ARG_TUPLE(_("_Save"), GTK_RESPONSE_ACCEPT),
|
||||
NULL);
|
||||
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"));
|
||||
|
||||
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"
|
||||
"To add another primary URL, add it after a blank line."));
|
||||
gtk_label_set_markup(
|
||||
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);
|
||||
g_object_set(l, "halign", GTK_ALIGN_START, "valign", GTK_ALIGN_CENTER, NULL);
|
||||
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_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,
|
||||
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
||||
_("_Add"), GTK_RESPONSE_ACCEPT,
|
||||
w = gtk_dialog_new_with_buttons(
|
||||
gstr->str,
|
||||
GTK_WINDOW(di->dialog),
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
TR_ARG_TUPLE(_("_Cancel"), GTK_RESPONSE_CANCEL),
|
||||
TR_ARG_TUPLE(_("_Add"), GTK_RESPONSE_ACCEPT),
|
||||
NULL);
|
||||
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* trackers;
|
||||
|
||||
gtk_tree_model_get(model, &iter,
|
||||
TRACKER_COL_TRACKER_ID, &tracker_id,
|
||||
TRACKER_COL_TORRENT_ID, &torrent_id,
|
||||
gtk_tree_model_get(
|
||||
model,
|
||||
&iter,
|
||||
TR_ARG_TUPLE(TRACKER_COL_TRACKER_ID, &tracker_id),
|
||||
TR_ARG_TUPLE(TRACKER_COL_TORRENT_ID, &torrent_id),
|
||||
-1);
|
||||
|
||||
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);
|
||||
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_STRING,
|
||||
G_TYPE_BOOLEAN,
|
||||
|
@ -2760,7 +2835,10 @@ static GtkWidget* tracker_page_new(struct DetailsImpl* di)
|
|||
G_TYPE_BOOLEAN,
|
||||
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);
|
||||
|
||||
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 */
|
||||
di->core = core;
|
||||
di->gstr = g_string_new(NULL);
|
||||
d = gtk_dialog_new_with_buttons(NULL, parent, 0,
|
||||
_("_Close"), GTK_RESPONSE_CLOSE,
|
||||
NULL);
|
||||
d = gtk_dialog_new_with_buttons(NULL, parent, 0, TR_ARG_TUPLE(_("_Close"), GTK_RESPONSE_CLOSE), NULL);
|
||||
di->dialog = d;
|
||||
gtk_window_set_role(GTK_WINDOW(d), "tr-info");
|
||||
|
||||
/* 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_height));
|
||||
g_signal_connect(d, "size-allocate", G_CALLBACK(on_details_window_size_allocated), NULL);
|
||||
|
|
|
@ -101,34 +101,45 @@ void gtr_confirm_remove(GtkWindow* parent, TrCore* core, GSList* torrent_ids, gb
|
|||
}
|
||||
else
|
||||
{
|
||||
g_string_printf(primary_text, ngettext("Delete this torrent's downloaded files?",
|
||||
"Delete these %d torrents' downloaded files?", count), count);
|
||||
g_string_printf(
|
||||
primary_text,
|
||||
ngettext("Delete this torrent's downloaded files?", "Delete these %d torrents' downloaded files?", count),
|
||||
count);
|
||||
}
|
||||
|
||||
secondary_text = g_string_new(NULL);
|
||||
|
||||
if (incomplete == 0 && connected == 0)
|
||||
{
|
||||
g_string_assign(secondary_text,
|
||||
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));
|
||||
g_string_assign(
|
||||
secondary_text,
|
||||
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)
|
||||
{
|
||||
g_string_assign(secondary_text, ngettext("This torrent has not finished downloading.",
|
||||
"These torrents have not finished downloading.", count));
|
||||
g_string_assign(
|
||||
secondary_text,
|
||||
ngettext("This torrent has not finished downloading.", "These torrents have not finished downloading.", count));
|
||||
}
|
||||
else if (count == connected)
|
||||
{
|
||||
g_string_assign(secondary_text, ngettext("This torrent is connected to peers.",
|
||||
"These torrents are connected to peers.", count));
|
||||
g_string_assign(
|
||||
secondary_text,
|
||||
ngettext("This torrent is connected to peers.", "These torrents are connected to peers.", count));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (connected != 0)
|
||||
{
|
||||
g_string_append(secondary_text, ngettext("One of these torrents is connected to peers.",
|
||||
"Some of these torrents are connected to peers.", connected));
|
||||
g_string_append(
|
||||
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)
|
||||
|
@ -138,22 +149,32 @@ void gtr_confirm_remove(GtkWindow* parent, TrCore* core, GSList* torrent_ids, gb
|
|||
|
||||
if (incomplete != 0)
|
||||
{
|
||||
g_string_assign(secondary_text, ngettext("One of these torrents has not finished downloading.",
|
||||
"Some of these torrents have not finished downloading.", incomplete));
|
||||
g_string_assign(
|
||||
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,
|
||||
"<big><b>%s</b></big>", primary_text->str);
|
||||
d = gtk_message_dialog_new_with_markup(
|
||||
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)
|
||||
{
|
||||
gtk_message_dialog_format_secondary_markup(GTK_MESSAGE_DIALOG(d), "%s", secondary_text->str);
|
||||
}
|
||||
|
||||
gtk_dialog_add_buttons(GTK_DIALOG(d),
|
||||
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
||||
delete_files ? _("_Delete") : _("_Remove"), GTK_RESPONSE_ACCEPT,
|
||||
gtk_dialog_add_buttons(
|
||||
GTK_DIALOG(d),
|
||||
TR_ARG_TUPLE(_("_Cancel"), GTK_RESPONSE_CANCEL),
|
||||
TR_ARG_TUPLE(delete_files ? _("_Delete") : _("_Remove"), GTK_RESPONSE_ACCEPT),
|
||||
NULL);
|
||||
gtk_dialog_set_default_response(GTK_DIALOG(d), GTK_RESPONSE_CANCEL);
|
||||
g_signal_connect(d, "response", G_CALLBACK(on_remove_dialog_response), dd);
|
||||
|
|
|
@ -118,8 +118,14 @@ static gboolean favicon_web_done_idle_cb(gpointer vfav)
|
|||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void favicon_web_done_cb(tr_session* session, bool did_connect, bool did_timeout, long code, void const* data,
|
||||
size_t len, void* vfav)
|
||||
static void favicon_web_done_cb(
|
||||
tr_session* session,
|
||||
bool did_connect,
|
||||
bool did_timeout,
|
||||
long code,
|
||||
void const* data,
|
||||
size_t len,
|
||||
void* vfav)
|
||||
{
|
||||
TR_UNUSED(session);
|
||||
TR_UNUSED(did_connect);
|
||||
|
|
165
gtk/file-list.c
165
gtk/file-list.c
|
@ -56,8 +56,7 @@ typedef struct
|
|||
GtkTreeStore* store; /* same object as model, but recast */
|
||||
int torrentId;
|
||||
guint timeout_tag;
|
||||
}
|
||||
FileData;
|
||||
} FileData;
|
||||
|
||||
static void clearData(FileData* data)
|
||||
{
|
||||
|
@ -105,13 +104,15 @@ static gboolean refreshFilesForeach(GtkTreeModel* model, GtkTreePath* path, GtkT
|
|||
int old_enabled;
|
||||
gboolean const is_file = !gtk_tree_model_iter_has_child(model, iter);
|
||||
|
||||
gtk_tree_model_get(model, iter,
|
||||
FC_ENABLED, &old_enabled,
|
||||
FC_PRIORITY, &old_priority,
|
||||
FC_INDEX, &index,
|
||||
FC_HAVE, &old_have,
|
||||
FC_SIZE, &size,
|
||||
FC_PROG, &old_prog,
|
||||
gtk_tree_model_get(
|
||||
model,
|
||||
iter,
|
||||
TR_ARG_TUPLE(FC_ENABLED, &old_enabled),
|
||||
TR_ARG_TUPLE(FC_PRIORITY, &old_priority),
|
||||
TR_ARG_TUPLE(FC_INDEX, &index),
|
||||
TR_ARG_TUPLE(FC_HAVE, &old_have),
|
||||
TR_ARG_TUPLE(FC_SIZE, &size),
|
||||
TR_ARG_TUPLE(FC_PROG, &old_prog),
|
||||
-1);
|
||||
|
||||
if (is_file)
|
||||
|
@ -131,19 +132,23 @@ static gboolean refreshFilesForeach(GtkTreeModel* model, GtkTreePath* path, GtkT
|
|||
* sorting until we finish walking the tree. */
|
||||
if (!refresh_data->resort_needed &&
|
||||
(((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;
|
||||
|
||||
gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(data->model),
|
||||
GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID, GTK_SORT_ASCENDING);
|
||||
gtk_tree_sortable_set_sort_column_id(
|
||||
GTK_TREE_SORTABLE(data->model),
|
||||
GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID,
|
||||
GTK_SORT_ASCENDING);
|
||||
}
|
||||
|
||||
gtk_tree_store_set(data->store, iter,
|
||||
FC_PRIORITY, priority,
|
||||
FC_ENABLED, enabled,
|
||||
FC_HAVE, have,
|
||||
FC_PROG, prog,
|
||||
gtk_tree_store_set(
|
||||
data->store,
|
||||
iter,
|
||||
TR_ARG_TUPLE(FC_PRIORITY, priority),
|
||||
TR_ARG_TUPLE(FC_ENABLED, enabled),
|
||||
TR_ARG_TUPLE(FC_HAVE, have),
|
||||
TR_ARG_TUPLE(FC_PROG, prog),
|
||||
-1);
|
||||
}
|
||||
}
|
||||
|
@ -168,11 +173,13 @@ static gboolean refreshFilesForeach(GtkTreeModel* model, GtkTreePath* path, GtkT
|
|||
int64_t child_have;
|
||||
int64_t child_size;
|
||||
|
||||
gtk_tree_model_get(model, &child,
|
||||
FC_SIZE, &child_size,
|
||||
FC_HAVE, &child_have,
|
||||
FC_PRIORITY, &child_priority,
|
||||
FC_ENABLED, &child_enabled,
|
||||
gtk_tree_model_get(
|
||||
model,
|
||||
&child,
|
||||
TR_ARG_TUPLE(FC_SIZE, &child_size),
|
||||
TR_ARG_TUPLE(FC_HAVE, &child_have),
|
||||
TR_ARG_TUPLE(FC_PRIORITY, &child_priority),
|
||||
TR_ARG_TUPLE(FC_ENABLED, &child_enabled),
|
||||
-1);
|
||||
|
||||
if ((child_enabled != FALSE) && (child_enabled != NOT_SET))
|
||||
|
@ -198,8 +205,7 @@ static gboolean refreshFilesForeach(GtkTreeModel* model, GtkTreePath* path, GtkT
|
|||
{
|
||||
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;
|
||||
|
@ -208,13 +214,15 @@ static gboolean refreshFilesForeach(GtkTreeModel* model, GtkTreePath* path, GtkT
|
|||
{
|
||||
char size_str[64];
|
||||
tr_strlsize(size_str, sub_size, sizeof(size_str));
|
||||
gtk_tree_store_set(data->store, iter,
|
||||
FC_SIZE, sub_size,
|
||||
FC_SIZE_STR, size_str,
|
||||
FC_HAVE, have,
|
||||
FC_PRIORITY, priority,
|
||||
FC_ENABLED, enabled,
|
||||
FC_PROG, prog,
|
||||
gtk_tree_store_set(
|
||||
data->store,
|
||||
iter,
|
||||
TR_ARG_TUPLE(FC_SIZE, sub_size),
|
||||
TR_ARG_TUPLE(FC_SIZE_STR, size_str),
|
||||
TR_ARG_TUPLE(FC_HAVE, have),
|
||||
TR_ARG_TUPLE(FC_PRIORITY, priority),
|
||||
TR_ARG_TUPLE(FC_ENABLED, enabled),
|
||||
TR_ARG_TUPLE(FC_PROG, prog),
|
||||
-1);
|
||||
}
|
||||
}
|
||||
|
@ -222,7 +230,10 @@ static gboolean refreshFilesForeach(GtkTreeModel* model, GtkTreePath* path, GtkT
|
|||
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)
|
||||
{
|
||||
GtkTreeIter child;
|
||||
|
@ -232,8 +243,7 @@ static void gtr_tree_model_foreach_postorder_subtree(GtkTreeModel* model, GtkTre
|
|||
do
|
||||
{
|
||||
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)
|
||||
|
@ -251,8 +261,7 @@ static void gtr_tree_model_foreach_postorder(GtkTreeModel* model, GtkTreeModelFo
|
|||
do
|
||||
{
|
||||
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));
|
||||
|
||||
gtk_tree_store_insert_with_values(build->store, &child_iter, build->iter, INT_MAX,
|
||||
FC_INDEX, child_data->index,
|
||||
FC_LABEL, child_data->name,
|
||||
FC_LABEL_ESC, name_esc,
|
||||
FC_SIZE, child_data->length,
|
||||
FC_SIZE_STR, size_str,
|
||||
FC_ICON, icon,
|
||||
FC_PRIORITY, priority,
|
||||
FC_ENABLED, enabled,
|
||||
gtk_tree_store_insert_with_values(
|
||||
build->store,
|
||||
&child_iter,
|
||||
build->iter,
|
||||
INT_MAX,
|
||||
TR_ARG_TUPLE(FC_INDEX, child_data->index),
|
||||
TR_ARG_TUPLE(FC_LABEL, child_data->name),
|
||||
TR_ARG_TUPLE(FC_LABEL_ESC, name_esc),
|
||||
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);
|
||||
|
||||
if (!isLeaf)
|
||||
|
@ -509,7 +522,8 @@ void gtr_file_list_set_torrent(GtkWidget* w, int torrentId)
|
|||
clearData(data);
|
||||
|
||||
/* 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 */
|
||||
G_TYPE_STRING, /* label */
|
||||
G_TYPE_STRING, /* label esc */
|
||||
|
@ -526,9 +540,7 @@ void gtr_file_list_set_torrent(GtkWidget* w, int torrentId)
|
|||
data->torrentId = torrentId;
|
||||
|
||||
/* populate the model */
|
||||
tr_torrent* const tor = torrentId > 0 ?
|
||||
gtr_core_find_torrent(data->core, torrentId) :
|
||||
NULL;
|
||||
tr_torrent* const tor = torrentId > 0 ? gtr_core_find_torrent(data->core, torrentId) : NULL;
|
||||
if (tor != NULL)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
static void renderPriority(GtkTreeViewColumn* column, GtkCellRenderer* renderer, GtkTreeModel* model, GtkTreeIter* iter,
|
||||
static void renderPriority(
|
||||
GtkTreeViewColumn* column,
|
||||
GtkCellRenderer* renderer,
|
||||
GtkTreeModel* model,
|
||||
GtkTreeIter* iter,
|
||||
gpointer data)
|
||||
{
|
||||
TR_UNUSED(column);
|
||||
|
@ -657,8 +677,7 @@ static char* buildFilename(tr_torrent const* tor, GtkTreeModel* model, GtkTreePa
|
|||
{
|
||||
child = parent;
|
||||
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);
|
||||
g_strfreev(tokens);
|
||||
|
@ -693,8 +712,7 @@ static gboolean onRowActivated(GtkTreeView* view, GtkTreePath* path, GtkTreeView
|
|||
char* tmp = g_path_get_dirname(filename);
|
||||
g_free(filename);
|
||||
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)))
|
||||
|
@ -772,7 +790,10 @@ static gboolean onViewPathToggled(GtkTreeView* view, GtkTreeViewColumn* col, Gtk
|
|||
/**
|
||||
* @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)
|
||||
{
|
||||
GtkTreeSelection* sel;
|
||||
|
@ -847,8 +868,13 @@ static int on_rename_done_idle(struct rename_data* data)
|
|||
}
|
||||
else
|
||||
{
|
||||
GtkWidget* w = gtk_message_dialog_new(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,
|
||||
GtkWidget* w = gtk_message_dialog_new(
|
||||
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));
|
||||
gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(w), "%s", _("Please correct the errors and try again."));
|
||||
gtk_dialog_run(GTK_DIALOG(w));
|
||||
|
@ -862,14 +888,21 @@ static int on_rename_done_idle(struct rename_data* data)
|
|||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void on_rename_done(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)
|
||||
static void on_rename_done(
|
||||
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;
|
||||
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)
|
||||
{
|
||||
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 */
|
||||
title = _("Size");
|
||||
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,
|
||||
"yalign", 0.5F, NULL);
|
||||
g_object_set(
|
||||
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);
|
||||
gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_GROW_ONLY);
|
||||
gtk_tree_view_column_set_sort_column_id(col, FC_SIZE);
|
||||
|
|
122
gtk/filter.c
122
gtk/filter.c
|
@ -173,8 +173,7 @@ static gboolean tracker_filter_model_update(gpointer gstore)
|
|||
g_free(keys);
|
||||
|
||||
++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);
|
||||
|
@ -242,11 +241,15 @@ static gboolean tracker_filter_model_update(gpointer gstore)
|
|||
char const* host = hosts->pdata[i];
|
||||
char* name = get_name_from_host(host);
|
||||
int const count = *(int*)g_hash_table_lookup(hosts_hash, host);
|
||||
gtk_tree_store_insert_with_values(store, &add, NULL, store_pos,
|
||||
TRACKER_FILTER_COL_HOST, host,
|
||||
TRACKER_FILTER_COL_NAME, name,
|
||||
TRACKER_FILTER_COL_COUNT, count,
|
||||
TRACKER_FILTER_COL_TYPE, TRACKER_FILTER_TYPE_HOST,
|
||||
gtk_tree_store_insert_with_values(
|
||||
store,
|
||||
&add,
|
||||
NULL,
|
||||
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);
|
||||
path = gtk_tree_model_get_path(model, &add);
|
||||
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)
|
||||
{
|
||||
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_INT,
|
||||
G_TYPE_INT,
|
||||
G_TYPE_STRING,
|
||||
GDK_TYPE_PIXBUF);
|
||||
|
||||
gtk_tree_store_insert_with_values(store, NULL, NULL, -1,
|
||||
TRACKER_FILTER_COL_NAME, _("All"),
|
||||
TRACKER_FILTER_COL_TYPE, TRACKER_FILTER_TYPE_ALL,
|
||||
gtk_tree_store_insert_with_values(
|
||||
store,
|
||||
NULL,
|
||||
NULL,
|
||||
-1,
|
||||
TR_ARG_TUPLE(TRACKER_FILTER_COL_NAME, _("All")),
|
||||
TR_ARG_TUPLE(TRACKER_FILTER_COL_TYPE, TRACKER_FILTER_TYPE_ALL),
|
||||
-1);
|
||||
gtk_tree_store_insert_with_values(store, NULL, NULL, -1,
|
||||
TRACKER_FILTER_COL_TYPE, TRACKER_FILTER_TYPE_SEPARATOR,
|
||||
gtk_tree_store_insert_with_values(
|
||||
store,
|
||||
NULL,
|
||||
NULL,
|
||||
-1,
|
||||
TR_ARG_TUPLE(TRACKER_FILTER_COL_TYPE, TRACKER_FILTER_TYPE_SEPARATOR),
|
||||
-1);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static void render_pixbuf_func(GtkCellLayout* cell_layout, GtkCellRenderer* cell_renderer, GtkTreeModel* tree_model,
|
||||
GtkTreeIter* iter, gpointer data)
|
||||
static void render_pixbuf_func(
|
||||
GtkCellLayout* cell_layout,
|
||||
GtkCellRenderer* cell_renderer,
|
||||
GtkTreeModel* tree_model,
|
||||
GtkTreeIter* iter,
|
||||
gpointer data)
|
||||
{
|
||||
TR_UNUSED(cell_layout);
|
||||
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);
|
||||
}
|
||||
|
||||
static void render_number_func(GtkCellLayout* cell_layout, GtkCellRenderer* cell_renderer, GtkTreeModel* tree_model,
|
||||
GtkTreeIter* iter, gpointer data)
|
||||
static void render_number_func(
|
||||
GtkCellLayout* cell_layout,
|
||||
GtkCellRenderer* cell_renderer,
|
||||
GtkTreeModel* tree_model,
|
||||
GtkTreeIter* iter,
|
||||
gpointer data)
|
||||
{
|
||||
TR_UNUSED(cell_layout);
|
||||
TR_UNUSED(data);
|
||||
|
@ -375,7 +395,12 @@ static GtkCellRenderer* number_renderer_new(void)
|
|||
{
|
||||
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);
|
||||
|
||||
return r;
|
||||
|
@ -560,13 +585,11 @@ static gboolean activity_filter_model_update(gpointer gstore)
|
|||
{
|
||||
++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);
|
||||
}
|
||||
while (gtk_tree_model_iter_next(model, &iter));
|
||||
} while (gtk_tree_model_iter_next(model, &iter));
|
||||
}
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
|
@ -580,9 +603,7 @@ static GtkTreeModel* activity_filter_model_new(GtkTreeModel* tmodel)
|
|||
char const* context;
|
||||
char const* name;
|
||||
char const* icon_name;
|
||||
}
|
||||
types[] =
|
||||
{
|
||||
} types[] = {
|
||||
{ ACTIVITY_FILTER_ALL, NULL, N_("All"), NULL },
|
||||
{ ACTIVITY_FILTER_SEPARATOR, NULL, NULL, NULL },
|
||||
{ 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_FINISHED, NULL, N_("Finished"), "media-playback-stop" },
|
||||
{ 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,
|
||||
G_TYPE_STRING,
|
||||
G_TYPE_INT,
|
||||
G_TYPE_INT,
|
||||
G_TYPE_STRING);
|
||||
GtkListStore* store = gtk_list_store_new(ACTIVITY_FILTER_N_COLS, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT, G_TYPE_STRING);
|
||||
|
||||
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);
|
||||
gtk_list_store_insert_with_values(store, NULL, -1,
|
||||
ACTIVITY_FILTER_COL_NAME, name,
|
||||
ACTIVITY_FILTER_COL_TYPE, types[i].type,
|
||||
ACTIVITY_FILTER_COL_ICON_NAME, types[i].icon_name,
|
||||
gtk_list_store_insert_with_values(
|
||||
store,
|
||||
NULL,
|
||||
-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);
|
||||
}
|
||||
|
||||
|
@ -615,8 +635,12 @@ static GtkTreeModel* activity_filter_model_new(GtkTreeModel* tmodel)
|
|||
return GTK_TREE_MODEL(store);
|
||||
}
|
||||
|
||||
static void render_activity_pixbuf_func(GtkCellLayout* cell_layout, GtkCellRenderer* cell_renderer, GtkTreeModel* tree_model,
|
||||
GtkTreeIter* iter, gpointer data)
|
||||
static void render_activity_pixbuf_func(
|
||||
GtkCellLayout* cell_layout,
|
||||
GtkCellRenderer* cell_renderer,
|
||||
GtkTreeModel* tree_model,
|
||||
GtkTreeIter* iter,
|
||||
gpointer data)
|
||||
{
|
||||
TR_UNUSED(cell_layout);
|
||||
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)
|
||||
{
|
||||
TR_UNUSED(tmodel);
|
||||
|
@ -686,14 +713,12 @@ static GtkWidget* activity_combo_box_new(GtkTreeModel* tmodel)
|
|||
|
||||
r = gtk_cell_renderer_pixbuf_new();
|
||||
gtk_cell_layout_pack_start(c_cell_layout, r, FALSE);
|
||||
gtk_cell_layout_set_attributes(c_cell_layout, r,
|
||||
"icon-name", ACTIVITY_FILTER_COL_ICON_NAME,
|
||||
NULL);
|
||||
gtk_cell_layout_set_attributes(c_cell_layout, r, TR_ARG_TUPLE("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);
|
||||
|
||||
r = gtk_cell_renderer_text_new();
|
||||
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();
|
||||
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))
|
||||
{
|
||||
gtk_tree_model_get(model, &iter,
|
||||
TRACKER_FILTER_COL_TYPE, &type,
|
||||
TRACKER_FILTER_COL_HOST, &host,
|
||||
gtk_tree_model_get(
|
||||
model,
|
||||
&iter,
|
||||
TR_ARG_TUPLE(TRACKER_FILTER_COL_TYPE, &type),
|
||||
TR_ARG_TUPLE(TRACKER_FILTER_COL_HOST, &host),
|
||||
-1);
|
||||
}
|
||||
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)
|
||||
{
|
||||
TR_UNUSED(tree_model);
|
||||
|
|
28
gtk/hig.c
28
gtk/hig.c
|
@ -7,6 +7,9 @@
|
|||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include <libtransmission/tr-macros.h>
|
||||
|
||||
#include "hig.h"
|
||||
|
||||
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))
|
||||
{
|
||||
g_object_set(w,
|
||||
"halign", GTK_ALIGN_START,
|
||||
"valign", GTK_ALIGN_CENTER,
|
||||
"use-markup", TRUE,
|
||||
g_object_set(
|
||||
w,
|
||||
TR_ARG_TUPLE("halign", GTK_ALIGN_START),
|
||||
TR_ARG_TUPLE("valign", GTK_ALIGN_CENTER),
|
||||
TR_ARG_TUPLE("use-markup", TRUE),
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
@ -100,10 +104,7 @@ static void hig_workarea_add_tall_control(GtkWidget* t, guint row, GtkWidget* co
|
|||
{
|
||||
if (GTK_IS_LABEL(control))
|
||||
{
|
||||
g_object_set(control,
|
||||
"halign", GTK_ALIGN_START,
|
||||
"valign", GTK_ALIGN_CENTER,
|
||||
NULL);
|
||||
g_object_set(control, TR_ARG_TUPLE("halign", GTK_ALIGN_START), TR_ARG_TUPLE("valign", GTK_ALIGN_CENTER), 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))
|
||||
{
|
||||
g_object_set(control,
|
||||
"halign", GTK_ALIGN_START,
|
||||
"valign", GTK_ALIGN_CENTER,
|
||||
NULL);
|
||||
g_object_set(control, TR_ARG_TUPLE("halign", GTK_ALIGN_START), TR_ARG_TUPLE("valign", GTK_ALIGN_CENTER), NULL);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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* l = gtk_label_new_with_mnemonic(mnemonic_string);
|
||||
|
|
18
gtk/hig.h
18
gtk/hig.h
|
@ -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);
|
||||
|
||||
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* 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);
|
||||
|
||||
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);
|
||||
|
||||
enum
|
||||
|
|
|
@ -34,8 +34,7 @@ typedef struct
|
|||
GtkIconTheme* icon_theme;
|
||||
int icon_size;
|
||||
GHashTable* cache;
|
||||
}
|
||||
IconCache;
|
||||
} IconCache;
|
||||
|
||||
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->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,
|
||||
icons->icon_size));
|
||||
g_hash_table_insert(icons->cache, (void*)VOID_PIXBUF_KEY, create_void_pixbuf(icons->icon_size, icons->icon_size));
|
||||
|
||||
return icons;
|
||||
}
|
||||
|
|
101
gtk/main.c
101
gtk/main.c
|
@ -455,8 +455,11 @@ static gboolean on_rpc_changed_idle(gpointer gdata)
|
|||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static tr_rpc_callback_status on_rpc_changed(tr_session* session G_GNUC_UNUSED, tr_rpc_callback_type type,
|
||||
struct tr_torrent* tor, void* gdata)
|
||||
static tr_rpc_callback_status on_rpc_changed(
|
||||
tr_session* session G_GNUC_UNUSED,
|
||||
tr_rpc_callback_type type,
|
||||
struct tr_torrent* tor,
|
||||
void* gdata)
|
||||
{
|
||||
struct cbdata* cbdata = gdata;
|
||||
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);
|
||||
|
||||
/* check & see if it's time to update the blocklist */
|
||||
if (gtr_pref_flag_get(TR_KEY_blocklist_enabled) &&
|
||||
gtr_pref_flag_get(TR_KEY_blocklist_updates_enabled))
|
||||
if (gtr_pref_flag_get(TR_KEY_blocklist_enabled) && gtr_pref_flag_get(TR_KEY_blocklist_updates_enabled))
|
||||
{
|
||||
int64_t const last_time = gtr_pref_int_get(TR_KEY_blocklist_date);
|
||||
int const SECONDS_IN_A_WEEK = 7 * 24 * 60 * 60;
|
||||
|
@ -623,8 +625,7 @@ int main(int argc, char** argv)
|
|||
GError* error = NULL;
|
||||
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 },
|
||||
{ "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 },
|
||||
|
@ -687,7 +688,9 @@ int main(int argc, char** argv)
|
|||
|
||||
/* init the application for the specified config dir */
|
||||
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);
|
||||
app = gtk_application_new(application_id, G_APPLICATION_HANDLES_OPEN);
|
||||
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))
|
||||
{
|
||||
GtkWidget* w = gtk_message_dialog_new(GTK_WINDOW(wind), 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."));
|
||||
GtkWidget* w = gtk_message_dialog_new(
|
||||
GTK_WINDOW(wind),
|
||||
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), _("I _Agree"), 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)
|
||||
{
|
||||
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));
|
||||
gtk_window_move(window, (int)gtr_pref_int_get(TR_KEY_main_window_x),
|
||||
(int)gtr_pref_int_get(TR_KEY_main_window_y));
|
||||
gtk_window_move(window, (int)gtr_pref_int_get(TR_KEY_main_window_x), (int)gtr_pref_int_get(TR_KEY_main_window_y));
|
||||
}
|
||||
|
||||
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,
|
||||
GtkSelectionData const* selection_data, guint info, guint time_, gpointer gdata)
|
||||
static void on_drag_data_received(
|
||||
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(x);
|
||||
|
@ -1000,8 +1016,11 @@ static void on_app_exit(gpointer vdata)
|
|||
c = GTK_WIDGET(cbdata->wind);
|
||||
gtk_container_remove(GTK_CONTAINER(c), gtk_bin_get_child(GTK_BIN(c)));
|
||||
|
||||
p =
|
||||
g_object_new(GTK_TYPE_GRID, "column-spacing", GUI_PAD_BIG, "halign", GTK_ALIGN_CENTER, "valign", GTK_ALIGN_CENTER,
|
||||
p = g_object_new(
|
||||
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);
|
||||
gtk_container_add(GTK_CONTAINER(c), p);
|
||||
|
||||
|
@ -1066,14 +1085,21 @@ static void flush_torrent_errors(struct cbdata* cbdata)
|
|||
{
|
||||
if (cbdata->error_list != NULL)
|
||||
{
|
||||
show_torrent_errors(cbdata->wind, ngettext("Couldn't add corrupt torrent", "Couldn't add corrupt torrents",
|
||||
g_slist_length(cbdata->error_list)), &cbdata->error_list);
|
||||
show_torrent_errors(
|
||||
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)
|
||||
{
|
||||
show_torrent_errors(cbdata->wind, ngettext("Couldn't add duplicate torrent", "Couldn't add duplicate torrents",
|
||||
g_slist_length(cbdata->duplicates_list)), &cbdata->duplicates_list);
|
||||
show_torrent_errors(
|
||||
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)
|
||||
{
|
||||
char const* uri = "https://transmissionbt.com/";
|
||||
char const* authors[] =
|
||||
{
|
||||
char const* authors[] = {
|
||||
"Charles Kerr (Backend; GTK+)",
|
||||
"Mitchell Livingston (Backend; OS X)",
|
||||
"Mike Gelfand",
|
||||
NULL
|
||||
NULL,
|
||||
};
|
||||
|
||||
gtk_show_about_dialog(parent,
|
||||
"authors", authors,
|
||||
"comments", _("A fast and easy BitTorrent client"),
|
||||
"copyright", _("Copyright (c) The Transmission Project"),
|
||||
"logo-icon-name", MY_CONFIG_NAME,
|
||||
"name", g_get_application_name(),
|
||||
gtk_show_about_dialog(
|
||||
parent,
|
||||
TR_ARG_TUPLE("authors", authors),
|
||||
TR_ARG_TUPLE("comments", _("A fast and easy BitTorrent client")),
|
||||
TR_ARG_TUPLE("copyright", _("Copyright (c) The Transmission Project")),
|
||||
TR_ARG_TUPLE("logo-icon-name", MY_CONFIG_NAME),
|
||||
TR_ARG_TUPLE("name", g_get_application_name()),
|
||||
/* Translators: translate "translator-credits" as your name
|
||||
to have it appear in the credits in the "About"
|
||||
dialog */
|
||||
"translator-credits", _("translator-credits"),
|
||||
"version", LONG_VERSION_STRING,
|
||||
"website", uri,
|
||||
"website-label", uri,
|
||||
TR_ARG_TUPLE("translator-credits", _("translator-credits")),
|
||||
TR_ARG_TUPLE("version", LONG_VERSION_STRING),
|
||||
TR_ARG_TUPLE("website", uri),
|
||||
TR_ARG_TUPLE("website-label", uri),
|
||||
#ifdef SHOW_LICENSE
|
||||
"license", LICENSE,
|
||||
"wrap-license", TRUE,
|
||||
TR_ARG_TUPLE("license", LICENSE),
|
||||
TR_ARG_TUPLE("wrap-license", TRUE),
|
||||
#endif
|
||||
NULL);
|
||||
}
|
||||
|
@ -1605,7 +1631,8 @@ void gtr_actions_handler(char const* action_name, gpointer user_data)
|
|||
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-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 ||
|
||||
|
|
|
@ -41,8 +41,7 @@ typedef struct
|
|||
GtkTextBuffer* announce_text_buffer;
|
||||
TrCore* core;
|
||||
tr_metainfo_builder* builder;
|
||||
}
|
||||
MakeMetaUI;
|
||||
} MakeMetaUI;
|
||||
|
||||
static void freeMetaUI(gpointer p)
|
||||
{
|
||||
|
@ -163,7 +162,7 @@ static void onProgressDialogResponse(GtkDialog* d, int response, gpointer data)
|
|||
case GTK_RESPONSE_ACCEPT:
|
||||
addTorrent(ui);
|
||||
|
||||
/* fall-through */
|
||||
/* fall-through */
|
||||
|
||||
case GTK_RESPONSE_CLOSE:
|
||||
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* fr;
|
||||
|
||||
d = gtk_dialog_new_with_buttons(_("New Torrent"), GTK_WINDOW(parent), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
||||
_("_Close"), GTK_RESPONSE_CLOSE,
|
||||
_("_Add"), GTK_RESPONSE_ACCEPT,
|
||||
d = gtk_dialog_new_with_buttons(
|
||||
_("New Torrent"),
|
||||
GTK_WINDOW(parent),
|
||||
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);
|
||||
ui->progress_dialog = d;
|
||||
g_signal_connect(d, "response", G_CALLBACK(onProgressDialogResponse), ui);
|
||||
|
@ -312,13 +314,19 @@ static void updatePiecesLabel(MakeMetaUI* ui)
|
|||
{
|
||||
char buf[128];
|
||||
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);
|
||||
g_string_append(gstr, "; ");
|
||||
|
||||
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),
|
||||
builder->pieceCount, buf);
|
||||
g_string_append_printf(
|
||||
gstr,
|
||||
ngettext("%1$'d Piece @ %2$s", "%1$'d Pieces @ %2$s", builder->pieceCount),
|
||||
builder->pieceCount,
|
||||
buf);
|
||||
}
|
||||
|
||||
g_string_append(gstr, "</i>");
|
||||
|
@ -386,8 +394,15 @@ static char const* getDefaultSavePath(void)
|
|||
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,
|
||||
GtkSelectionData const* selection_data, guint info, guint time_, gpointer user_data)
|
||||
static void on_drag_data_received(
|
||||
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(x);
|
||||
|
@ -441,9 +456,12 @@ GtkWidget* gtr_torrent_creation_dialog_new(GtkWindow* parent, TrCore* core)
|
|||
|
||||
ui->core = core;
|
||||
|
||||
d = gtk_dialog_new_with_buttons(_("New Torrent"), parent, GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
_("_Close"), GTK_RESPONSE_CLOSE,
|
||||
_("_New"), GTK_RESPONSE_ACCEPT,
|
||||
d = gtk_dialog_new_with_buttons(
|
||||
_("New Torrent"),
|
||||
parent,
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
TR_ARG_TUPLE(_("_Close"), GTK_RESPONSE_CLOSE),
|
||||
TR_ARG_TUPLE(_("_New"), GTK_RESPONSE_ACCEPT),
|
||||
NULL);
|
||||
ui->dialog = d;
|
||||
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);
|
||||
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:"));
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(l), TRUE);
|
||||
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_box_pack_start(GTK_BOX(v), fr, TRUE, TRUE, 0);
|
||||
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"
|
||||
"To add another primary URL, add it after a blank line."));
|
||||
gtk_label_set_markup(
|
||||
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);
|
||||
g_object_set(l, "halign", GTK_ALIGN_START, "valign", GTK_ALIGN_CENTER, NULL);
|
||||
gtk_box_pack_start(GTK_BOX(v), l, FALSE, FALSE, 0);
|
||||
|
|
90
gtk/msgwin.c
90
gtk/msgwin.c
|
@ -135,8 +135,8 @@ static void doSave(GtkWindow* parent, struct MsgData* data, char const* filename
|
|||
|
||||
if (fp == NULL)
|
||||
{
|
||||
GtkWidget* w = gtk_message_dialog_new(parent, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, _("Couldn't save \"%s\""),
|
||||
filename);
|
||||
GtkWidget*
|
||||
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));
|
||||
g_signal_connect_swapped(w, "response", G_CALLBACK(gtk_widget_destroy), w);
|
||||
gtk_widget_show(w);
|
||||
|
@ -171,11 +171,15 @@ static void doSave(GtkWindow* parent, struct MsgData* data, char const* filename
|
|||
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 : "");
|
||||
g_free(date);
|
||||
}
|
||||
while (gtk_tree_model_iter_next(model, &iter));
|
||||
} while (gtk_tree_model_iter_next(model, &iter));
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
@ -197,9 +201,12 @@ static void onSaveDialogResponse(GtkWidget* d, int response, gpointer data)
|
|||
static void onSaveRequest(GtkWidget* w, gpointer data)
|
||||
{
|
||||
GtkWindow* window = GTK_WINDOW(gtk_widget_get_toplevel(w));
|
||||
GtkWidget* d = gtk_file_chooser_dialog_new(_("Save Log"), window, GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
||||
_("_Save"), GTK_RESPONSE_ACCEPT,
|
||||
GtkWidget* d = gtk_file_chooser_dialog_new(
|
||||
_("Save Log"),
|
||||
window,
|
||||
GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
TR_ARG_TUPLE(_("_Cancel"), GTK_RESPONSE_CANCEL),
|
||||
TR_ARG_TUPLE(_("_Save"), GTK_RESPONSE_ACCEPT),
|
||||
NULL);
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
gtk_list_store_insert_with_values(store, NULL, 0,
|
||||
COL_TR_MSG, i,
|
||||
COL_NAME, name,
|
||||
COL_MESSAGE, i->message,
|
||||
COL_SEQUENCE, ++sequence,
|
||||
gtk_list_store_insert_with_values(
|
||||
store,
|
||||
NULL,
|
||||
0,
|
||||
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);
|
||||
|
||||
/* 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)
|
||||
{
|
||||
GtkWidget* w = gtr_combo_box_new_enum(
|
||||
_("Error"), TR_LOG_ERROR,
|
||||
_("Information"), TR_LOG_INFO,
|
||||
_("Debug"), TR_LOG_DEBUG,
|
||||
TR_ARG_TUPLE(_("Error"), TR_LOG_ERROR),
|
||||
TR_ARG_TUPLE(_("Information"), TR_LOG_INFO),
|
||||
TR_ARG_TUPLE(_("Debug"), TR_LOG_DEBUG),
|
||||
NULL);
|
||||
gtr_combo_box_set_active_enum(GTK_COMBO_BOX(w), gtr_pref_int_get(TR_KEY_message_level));
|
||||
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);
|
||||
|
||||
item = gtk_tool_button_new(NULL, NULL);
|
||||
g_object_set(item,
|
||||
"icon-name", "document-save-as",
|
||||
"is-important", TRUE,
|
||||
"label", _("Save _As"),
|
||||
"use-underline", TRUE,
|
||||
g_object_set(
|
||||
item,
|
||||
TR_ARG_TUPLE("icon-name", "document-save-as"),
|
||||
TR_ARG_TUPLE("is-important", TRUE),
|
||||
TR_ARG_TUPLE("label", _("Save _As")),
|
||||
TR_ARG_TUPLE("use-underline", TRUE),
|
||||
NULL);
|
||||
g_signal_connect(item, "clicked", G_CALLBACK(onSaveRequest), data);
|
||||
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
|
||||
|
||||
item = gtk_tool_button_new(NULL, NULL);
|
||||
g_object_set(item,
|
||||
"icon-name", "edit-clear",
|
||||
"is-important", TRUE,
|
||||
"label", _("Clear"),
|
||||
"use-underline", TRUE,
|
||||
g_object_set(
|
||||
item,
|
||||
TR_ARG_TUPLE("icon-name", "edit-clear"),
|
||||
TR_ARG_TUPLE("is-important", TRUE),
|
||||
TR_ARG_TUPLE("label", _("Clear")),
|
||||
TR_ARG_TUPLE("use-underline", TRUE),
|
||||
NULL);
|
||||
g_signal_connect(item, "clicked", G_CALLBACK(onClearRequest), data);
|
||||
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);
|
||||
|
||||
item = gtk_toggle_tool_button_new();
|
||||
g_object_set(G_OBJECT(item),
|
||||
"icon-name", "media-playback-pause",
|
||||
"is-important", TRUE,
|
||||
"label", _("P_ause"),
|
||||
"use-underline", TRUE,
|
||||
g_object_set(
|
||||
G_OBJECT(item),
|
||||
TR_ARG_TUPLE("icon-name", "media-playback-pause"),
|
||||
TR_ARG_TUPLE("is-important", TRUE),
|
||||
TR_ARG_TUPLE("label", _("P_ause")),
|
||||
TR_ARG_TUPLE("use-underline", TRUE),
|
||||
NULL);
|
||||
g_signal_connect(item, "toggled", G_CALLBACK(onPauseToggled), data);
|
||||
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
|
||||
|
@ -522,7 +543,8 @@ GtkWidget* gtr_message_log_window_new(GtkWindow* parent, TrCore* core)
|
|||
*** messages
|
||||
**/
|
||||
|
||||
data->store = gtk_list_store_new(N_COLUMNS,
|
||||
data->store = gtk_list_store_new(
|
||||
N_COLUMNS,
|
||||
G_TYPE_UINT, /* sequence */
|
||||
G_TYPE_POINTER, /* category */
|
||||
G_TYPE_POINTER, /* message */
|
||||
|
|
67
gtk/notify.c
67
gtk/notify.c
|
@ -26,8 +26,7 @@ typedef struct TrNotification
|
|||
{
|
||||
TrCore* core;
|
||||
int torrent_id;
|
||||
}
|
||||
TrNotification;
|
||||
} TrNotification;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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_dbus_proxy_call(proxy, "GetCapabilities", g_variant_new("()"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
|
||||
get_capabilities_callback, NULL);
|
||||
g_dbus_proxy_call(
|
||||
proxy,
|
||||
"GetCapabilities",
|
||||
g_variant_new("()"),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
NULL,
|
||||
get_capabilities_callback,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void gtr_notify_init(void)
|
||||
{
|
||||
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,
|
||||
NOTIFICATIONS_DBUS_CORE_OBJECT, NOTIFICATIONS_DBUS_CORE_INTERFACE, NULL, dbus_proxy_ready_callback, NULL);
|
||||
g_dbus_proxy_new_for_bus(
|
||||
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)
|
||||
|
@ -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))
|
||||
{
|
||||
char** argv = gtr_pref_strv_get(TR_KEY_torrent_complete_sound_command);
|
||||
g_spawn_async(NULL /*cwd*/,
|
||||
g_spawn_async(
|
||||
NULL /*cwd*/,
|
||||
argv,
|
||||
NULL /*envp*/,
|
||||
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_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",
|
||||
_("Torrent Complete"), tr_torrentName(tor), &actions_builder, &hints_builder, -1), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
|
||||
notify_callback, n);
|
||||
g_dbus_proxy_call(
|
||||
proxy,
|
||||
"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)
|
||||
|
@ -244,6 +278,13 @@ void gtr_notify_torrent_added(char const* name)
|
|||
}
|
||||
|
||||
n = g_new0(TrNotification, 1);
|
||||
g_dbus_proxy_call(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);
|
||||
g_dbus_proxy_call(
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -281,9 +281,12 @@ GtkWidget* gtr_torrent_options_dialog_new(GtkWindow* parent, TrCore* core, tr_ct
|
|||
GSList* list;
|
||||
|
||||
/* make the dialog */
|
||||
d = gtk_dialog_new_with_buttons(_("Torrent Options"), parent, GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
||||
_("_Open"), GTK_RESPONSE_ACCEPT,
|
||||
d = gtk_dialog_new_with_buttons(
|
||||
_("Torrent Options"),
|
||||
parent,
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
TR_ARG_TUPLE(_("_Cancel"), GTK_RESPONSE_CANCEL),
|
||||
TR_ARG_TUPLE(_("_Open"), GTK_RESPONSE_ACCEPT),
|
||||
NULL);
|
||||
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;
|
||||
char const* folder;
|
||||
|
||||
w = gtk_file_chooser_dialog_new(_("Open a Torrent"), parent, GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
||||
_("_Open"), GTK_RESPONSE_ACCEPT,
|
||||
w = gtk_file_chooser_dialog_new(
|
||||
_("Open a Torrent"),
|
||||
parent,
|
||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
TR_ARG_TUPLE(_("_Cancel"), GTK_RESPONSE_CANCEL),
|
||||
TR_ARG_TUPLE(_("_Open"), GTK_RESPONSE_ACCEPT),
|
||||
NULL);
|
||||
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(w), TRUE);
|
||||
addTorrentFilters(GTK_FILE_CHOOSER(w));
|
||||
|
@ -519,9 +525,12 @@ GtkWidget* gtr_torrent_open_from_url_dialog_new(GtkWindow* parent, TrCore* core)
|
|||
GtkWidget* t;
|
||||
GtkWidget* w;
|
||||
|
||||
w = gtk_dialog_new_with_buttons(_("Open URL"), parent, GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
||||
_("_Open"), GTK_RESPONSE_ACCEPT,
|
||||
w = gtk_dialog_new_with_buttons(
|
||||
_("Open URL"),
|
||||
parent,
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
TR_ARG_TUPLE(_("_Cancel"), GTK_RESPONSE_CANCEL),
|
||||
TR_ARG_TUPLE(_("_Open"), GTK_RESPONSE_ACCEPT),
|
||||
NULL);
|
||||
g_signal_connect(w, "response", G_CALLBACK(onOpenURLResponse), core);
|
||||
|
||||
|
|
|
@ -72,8 +72,13 @@ static gboolean onTimer(gpointer gdata)
|
|||
if (done == TR_LOC_ERROR)
|
||||
{
|
||||
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,
|
||||
"%s", _("Couldn't move torrent"));
|
||||
GtkWidget* w = gtk_message_dialog_new(
|
||||
GTK_WINDOW(data->message_dialog),
|
||||
flags,
|
||||
GTK_MESSAGE_ERROR,
|
||||
GTK_BUTTONS_CLOSE,
|
||||
"%s",
|
||||
_("Couldn't move torrent"));
|
||||
gtk_dialog_run(GTK_DIALOG(w));
|
||||
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);
|
||||
|
||||
/* 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,
|
||||
GTK_BUTTONS_CLOSE, NULL);
|
||||
w = gtk_message_dialog_new(
|
||||
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_dialog_set_response_sensitive(GTK_DIALOG(w), GTK_RESPONSE_CLOSE, FALSE);
|
||||
gtk_widget_show(w);
|
||||
|
@ -138,9 +147,12 @@ GtkWidget* gtr_relocate_dialog_new(GtkWindow* parent, TrCore* core, GSList* torr
|
|||
GtkWidget* t;
|
||||
struct relocate_dialog_data* data;
|
||||
|
||||
d = gtk_dialog_new_with_buttons(_("Set Torrent Location"), parent, GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
|
||||
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
||||
_("_Apply"), GTK_RESPONSE_APPLY,
|
||||
d = gtk_dialog_new_with_buttons(
|
||||
_("Set Torrent Location"),
|
||||
parent,
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
|
||||
TR_ARG_TUPLE(_("_Cancel"), GTK_RESPONSE_CANCEL),
|
||||
TR_ARG_TUPLE(_("_Apply"), GTK_RESPONSE_APPLY),
|
||||
NULL);
|
||||
gtk_dialog_set_default_response(GTK_DIALOG(d), GTK_RESPONSE_CANCEL);
|
||||
g_signal_connect(d, "response", G_CALLBACK(onResponse), NULL);
|
||||
|
|
19
gtk/stats.c
19
gtk/stats.c
|
@ -90,13 +90,15 @@ static void dialogResponse(GtkDialog* dialog, gint response, gpointer gdata)
|
|||
if (response == TR_RESPONSE_RESET)
|
||||
{
|
||||
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.");
|
||||
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);
|
||||
gtk_dialog_add_buttons(GTK_DIALOG(w),
|
||||
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
||||
_("_Reset"), TR_RESPONSE_RESET,
|
||||
gtk_dialog_add_buttons(
|
||||
GTK_DIALOG(w),
|
||||
TR_ARG_TUPLE(_("_Cancel"), GTK_RESPONSE_CANCEL),
|
||||
TR_ARG_TUPLE(_("_Reset"), TR_RESPONSE_RESET),
|
||||
NULL);
|
||||
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;
|
||||
struct stat_ui* ui = g_new0(struct stat_ui, 1);
|
||||
|
||||
d = gtk_dialog_new_with_buttons(_("Statistics"), parent, GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
_("_Reset"), TR_RESPONSE_RESET,
|
||||
_("_Close"), GTK_RESPONSE_CLOSE,
|
||||
d = gtk_dialog_new_with_buttons(
|
||||
_("Statistics"),
|
||||
parent,
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
TR_ARG_TUPLE(_("_Reset"), TR_RESPONSE_RESET),
|
||||
TR_ARG_TUPLE(_("_Close"), GTK_RESPONSE_CLOSE),
|
||||
NULL);
|
||||
gtk_dialog_set_default_response(GTK_DIALOG(d), GTK_RESPONSE_CLOSE);
|
||||
t = hig_workarea_create();
|
||||
|
|
|
@ -52,7 +52,8 @@ static void getProgressString(GString* gstr, tr_torrent const* tor, tr_info cons
|
|||
|
||||
if (!isDone) /* downloading */
|
||||
{
|
||||
g_string_append_printf(gstr,
|
||||
g_string_append_printf(
|
||||
gstr,
|
||||
/* %1$s is how much we've got,
|
||||
%2$s is how much we'll have when done,
|
||||
%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)
|
||||
{
|
||||
g_string_append_printf(gstr,
|
||||
g_string_append_printf(
|
||||
gstr,
|
||||
/* %1$s is how much we've got,
|
||||
%2$s is the torrent's total size,
|
||||
%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
|
||||
{
|
||||
g_string_append_printf(gstr,
|
||||
g_string_append_printf(
|
||||
gstr,
|
||||
/* %1$s is how much we've got,
|
||||
%2$s is the torrent's total size,
|
||||
%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)
|
||||
{
|
||||
g_string_append_printf(gstr,
|
||||
g_string_append_printf(
|
||||
gstr,
|
||||
/* %1$s is the torrent's total size,
|
||||
%2$s is how much we've uploaded,
|
||||
%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 */
|
||||
{
|
||||
g_string_append_printf(gstr,
|
||||
g_string_append_printf(
|
||||
gstr,
|
||||
/* %1$s is the torrent's total size,
|
||||
%2$s is how much we've uploaded,
|
||||
%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,
|
||||
double downloadSpeed_KBps, char* buf, size_t buflen)
|
||||
static char* getShortTransferString(
|
||||
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 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));
|
||||
|
||||
/* 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));
|
||||
}
|
||||
else if (haveUp)
|
||||
|
@ -182,7 +198,11 @@ static char* getShortTransferString(tr_torrent const* tor, tr_stat const* st, do
|
|||
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)
|
||||
{
|
||||
switch (st->activity)
|
||||
|
@ -204,8 +224,7 @@ static void getShortStatusString(GString* gstr, tr_torrent const* tor, tr_stat c
|
|||
break;
|
||||
|
||||
case TR_STATUS_CHECK:
|
||||
g_string_append_printf(gstr, _("Verifying local data (%.1f%% tested)"),
|
||||
tr_truncd(st->recheckProgress * 100.0, 1));
|
||||
g_string_append_printf(gstr, _("Verifying local data (%.1f%% tested)"), tr_truncd(st->recheckProgress * 100.0, 1));
|
||||
break;
|
||||
|
||||
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)
|
||||
{
|
||||
if (st->error != 0)
|
||||
{
|
||||
char const* fmt[] =
|
||||
{
|
||||
char const* fmt[] = {
|
||||
NULL,
|
||||
N_("Tracker gave a warning: \"%s\""),
|
||||
N_("Tracker gave an error: \"%s\""),
|
||||
N_("Error: %s")
|
||||
N_("Error: %s"),
|
||||
};
|
||||
|
||||
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))
|
||||
{
|
||||
/* 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,
|
||||
ngettext("peer", "peers", st->peersConnected), (int)(100.0 * st->metadataPercentComplete));
|
||||
g_string_append_printf(
|
||||
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)
|
||||
{
|
||||
/* 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,
|
||||
st->peersConnected, ngettext("peer", "peers", st->peersConnected), st->webseedsSendingToUs,
|
||||
g_string_append_printf(
|
||||
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));
|
||||
}
|
||||
else if (st->webseedsSendingToUs != 0)
|
||||
{
|
||||
/* 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));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Downloading from 2 of 3 peer (s) */
|
||||
g_string_append_printf(gstr, _("Downloading from %1$'d of %2$'d %3$s"), st->peersSendingToUs,
|
||||
st->peersConnected, ngettext("peer", "peers", st->peersConnected));
|
||||
g_string_append_printf(
|
||||
gstr,
|
||||
_("Downloading from %1$'d of %2$'d %3$s"),
|
||||
st->peersSendingToUs,
|
||||
st->peersConnected,
|
||||
ngettext("peer", "peers", st->peersConnected));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case TR_STATUS_SEED:
|
||||
g_string_append_printf(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);
|
||||
g_string_append_printf(
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -330,8 +374,7 @@ typedef struct TorrentCellRendererPrivate
|
|||
double download_speed_KBps;
|
||||
|
||||
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)
|
||||
{
|
||||
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 */
|
||||
g_object_set(p->icon_renderer, "pixbuf", icon, NULL);
|
||||
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);
|
||||
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);
|
||||
|
@ -477,8 +528,14 @@ static void get_size_full(TorrentCellRenderer* cell, GtkWidget* widget, gint* wi
|
|||
g_object_unref(icon);
|
||||
}
|
||||
|
||||
static void torrent_cell_renderer_get_size(GtkCellRenderer* cell, GtkWidget* widget, GdkRectangle const* cell_area,
|
||||
gint* x_offset, gint* y_offset, gint* width, gint* height)
|
||||
static void torrent_cell_renderer_get_size(
|
||||
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);
|
||||
|
||||
|
@ -563,14 +620,23 @@ static double get_percent_done(tr_torrent const* tor, tr_stat const* st, bool* s
|
|||
|
||||
typedef cairo_t GtrDrawable;
|
||||
|
||||
static void gtr_cell_renderer_render(GtkCellRenderer* renderer, GtrDrawable* drawable, GtkWidget* widget,
|
||||
GdkRectangle const* area, GtkCellRendererState flags)
|
||||
static void gtr_cell_renderer_render(
|
||||
GtkCellRenderer* renderer,
|
||||
GtrDrawable* drawable,
|
||||
GtkWidget* widget,
|
||||
GdkRectangle const* area,
|
||||
GtkCellRendererState flags)
|
||||
{
|
||||
gtk_cell_renderer_render(renderer, drawable, widget, area, area, flags);
|
||||
}
|
||||
|
||||
static void render_compact(TorrentCellRenderer* cell, GtrDrawable* window, GtkWidget* widget,
|
||||
GdkRectangle const* background_area, GdkRectangle const* cell_area, GtkCellRendererState flags)
|
||||
static void render_compact(
|
||||
TorrentCellRenderer* cell,
|
||||
GtrDrawable* window,
|
||||
GtkWidget* widget,
|
||||
GdkRectangle const* background_area,
|
||||
GdkRectangle const* cell_area,
|
||||
GtkCellRendererState flags)
|
||||
{
|
||||
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);
|
||||
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);
|
||||
g_object_set(p->text_renderer, "text", gstr_stat->str, "scale", SMALL_SCALE, "ellipsize", PANGO_ELLIPSIZE_END,
|
||||
FOREGROUND_COLOR_KEY, &text_color, NULL);
|
||||
g_object_set(
|
||||
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);
|
||||
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);
|
||||
|
@ -646,8 +717,13 @@ static void render_compact(TorrentCellRenderer* cell, GtrDrawable* window, GtkWi
|
|||
g_object_unref(icon);
|
||||
}
|
||||
|
||||
static void render_full(TorrentCellRenderer* cell, GtrDrawable* window, GtkWidget* widget, GdkRectangle const* background_area,
|
||||
GdkRectangle const* cell_area, GtkCellRendererState flags)
|
||||
static void render_full(
|
||||
TorrentCellRenderer* cell,
|
||||
GtrDrawable* window,
|
||||
GtkWidget* widget,
|
||||
GdkRectangle const* background_area,
|
||||
GdkRectangle const* cell_area,
|
||||
GtkCellRendererState flags)
|
||||
{
|
||||
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);
|
||||
icon_area.width = size.width;
|
||||
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);
|
||||
gtr_cell_renderer_get_preferred_size(p->text_renderer, widget, NULL, &size);
|
||||
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);
|
||||
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",
|
||||
PANGO_ELLIPSIZE_END, "weight", PANGO_WEIGHT_BOLD, NULL);
|
||||
g_object_set(
|
||||
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);
|
||||
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);
|
||||
|
@ -759,8 +846,12 @@ static void render_full(TorrentCellRenderer* cell, GtrDrawable* window, GtkWidge
|
|||
g_object_unref(icon);
|
||||
}
|
||||
|
||||
static void torrent_cell_renderer_render(GtkCellRenderer* cell, GtrDrawable* window, GtkWidget* widget,
|
||||
GdkRectangle const* background_area, GdkRectangle const* cell_area,
|
||||
static void torrent_cell_renderer_render(
|
||||
GtkCellRenderer* cell,
|
||||
GtrDrawable* window,
|
||||
GtkWidget* widget,
|
||||
GdkRectangle const* background_area,
|
||||
GdkRectangle const* cell_area,
|
||||
GtkCellRendererState flags)
|
||||
{
|
||||
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->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_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_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_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_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));
|
||||
}
|
||||
|
||||
|
|
239
gtk/tr-core.c
239
gtk/tr-core.c
|
@ -79,8 +79,7 @@ typedef struct TrCorePrivate
|
|||
GtkTreeModel* sorted_model;
|
||||
tr_session* session;
|
||||
GStringChunk* string_chunk;
|
||||
}
|
||||
TrCorePrivate;
|
||||
} TrCorePrivate;
|
||||
|
||||
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->finalize = core_finalize;
|
||||
|
||||
signals[ADD_ERROR_SIGNAL] = g_signal_new("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_ERROR_SIGNAL] = g_signal_new(
|
||||
"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,
|
||||
add_prompt), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER);
|
||||
signals[ADD_PROMPT_SIGNAL] = g_signal_new(
|
||||
"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,
|
||||
g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
|
||||
signals[BUSY_SIGNAL] = g_signal_new(
|
||||
"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,
|
||||
blocklist_updated), NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
|
||||
signals[BLOCKLIST_SIGNAL] = g_signal_new(
|
||||
"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),
|
||||
NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
|
||||
signals[PORT_SIGNAL] = g_signal_new(
|
||||
"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,
|
||||
prefs_changed), NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
|
||||
signals[PREFS_SIGNAL] = g_signal_new(
|
||||
"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)
|
||||
|
@ -147,8 +201,7 @@ static void tr_core_init(TrCore* core)
|
|||
|
||||
/* column types for the model used to store torrent information */
|
||||
/* 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, /* tr_torrent* */
|
||||
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 */
|
||||
static void on_file_changed_in_watchdir(GFileMonitor const* monitor, GFile* file, GFile const* other_type,
|
||||
GFileMonitorEvent event_type, gpointer core)
|
||||
static void on_file_changed_in_watchdir(
|
||||
GFileMonitor const* monitor,
|
||||
GFile* file,
|
||||
GFile const* other_type,
|
||||
GFileMonitorEvent event_type,
|
||||
gpointer core)
|
||||
{
|
||||
TR_UNUSED(monitor);
|
||||
TR_UNUSED(other_type);
|
||||
|
@ -1009,8 +1066,7 @@ static gboolean find_row_from_torrent_id(GtkTreeModel* model, int id, GtkTreeIte
|
|||
int row_id;
|
||||
gtk_tree_model_get(model, &iter, MC_TORRENT_ID, &row_id, -1);
|
||||
match = id == row_id;
|
||||
}
|
||||
while (!match && gtk_tree_model_iter_next(model, &iter));
|
||||
} while (!match && gtk_tree_model_iter_next(model, &iter));
|
||||
}
|
||||
|
||||
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);
|
||||
GtkListStore* store = GTK_LIST_STORE(core_raw_model(core));
|
||||
|
||||
gtk_list_store_insert_with_values(store, &unused, 0,
|
||||
MC_NAME_COLLATED, collated,
|
||||
MC_TORRENT, tor,
|
||||
MC_TORRENT_ID, tr_torrentId(tor),
|
||||
MC_SPEED_UP, st->pieceUploadSpeed_KBps,
|
||||
MC_SPEED_DOWN, st->pieceDownloadSpeed_KBps,
|
||||
MC_ACTIVE_PEERS_UP, st->peersGettingFromUs,
|
||||
MC_ACTIVE_PEERS_DOWN, st->peersSendingToUs + st->webseedsSendingToUs,
|
||||
MC_RECHECK_PROGRESS, st->recheckProgress,
|
||||
MC_ACTIVE, is_torrent_active(st),
|
||||
MC_ACTIVITY, st->activity,
|
||||
MC_FINISHED, st->finished,
|
||||
MC_PRIORITY, tr_torrentGetPriority(tor),
|
||||
MC_QUEUE_POSITION, st->queuePosition,
|
||||
MC_TRACKERS, trackers_hash,
|
||||
gtk_list_store_insert_with_values(
|
||||
store,
|
||||
&unused,
|
||||
0,
|
||||
TR_ARG_TUPLE(MC_NAME_COLLATED, collated),
|
||||
TR_ARG_TUPLE(MC_TORRENT, tor),
|
||||
TR_ARG_TUPLE(MC_TORRENT_ID, tr_torrentId(tor)),
|
||||
TR_ARG_TUPLE(MC_SPEED_UP, st->pieceUploadSpeed_KBps),
|
||||
TR_ARG_TUPLE(MC_SPEED_DOWN, st->pieceDownloadSpeed_KBps),
|
||||
TR_ARG_TUPLE(MC_ACTIVE_PEERS_UP, st->peersGettingFromUs),
|
||||
TR_ARG_TUPLE(MC_ACTIVE_PEERS_DOWN, st->peersSendingToUs + st->webseedsSendingToUs),
|
||||
TR_ARG_TUPLE(MC_RECHECK_PROGRESS, st->recheckProgress),
|
||||
TR_ARG_TUPLE(MC_ACTIVE, is_torrent_active(st)),
|
||||
TR_ARG_TUPLE(MC_ACTIVITY, st->activity),
|
||||
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);
|
||||
|
||||
if (do_notify)
|
||||
|
@ -1324,8 +1383,8 @@ static bool add_file(TrCore* core, GFile* file, gboolean do_start, gboolean do_p
|
|||
handled = true;
|
||||
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") ||
|
||||
g_file_has_uri_scheme(file, "ftp"))
|
||||
else if (
|
||||
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;
|
||||
|
||||
|
@ -1501,21 +1560,23 @@ static void update_foreach(GtkTreeModel* model, GtkTreeIter* iter)
|
|||
tr_torrent* tor;
|
||||
|
||||
/* get the old states */
|
||||
gtk_tree_model_get(model, iter,
|
||||
MC_TORRENT, &tor,
|
||||
MC_ACTIVE, &oldActive,
|
||||
MC_ACTIVE_PEER_COUNT, &oldActivePeerCount,
|
||||
MC_ACTIVE_PEERS_UP, &oldUploadPeerCount,
|
||||
MC_ACTIVE_PEERS_DOWN, &oldDownloadPeerCount,
|
||||
MC_ERROR, &oldError,
|
||||
MC_ACTIVITY, &oldActivity,
|
||||
MC_FINISHED, &oldFinished,
|
||||
MC_PRIORITY, &oldPriority,
|
||||
MC_QUEUE_POSITION, &oldQueuePosition,
|
||||
MC_TRACKERS, &oldTrackers,
|
||||
MC_SPEED_UP, &oldUpSpeed,
|
||||
MC_RECHECK_PROGRESS, &oldRecheckProgress,
|
||||
MC_SPEED_DOWN, &oldDownSpeed,
|
||||
gtk_tree_model_get(
|
||||
model,
|
||||
iter,
|
||||
TR_ARG_TUPLE(MC_TORRENT, &tor),
|
||||
TR_ARG_TUPLE(MC_ACTIVE, &oldActive),
|
||||
TR_ARG_TUPLE(MC_ACTIVE_PEER_COUNT, &oldActivePeerCount),
|
||||
TR_ARG_TUPLE(MC_ACTIVE_PEERS_UP, &oldUploadPeerCount),
|
||||
TR_ARG_TUPLE(MC_ACTIVE_PEERS_DOWN, &oldDownloadPeerCount),
|
||||
TR_ARG_TUPLE(MC_ERROR, &oldError),
|
||||
TR_ARG_TUPLE(MC_ACTIVITY, &oldActivity),
|
||||
TR_ARG_TUPLE(MC_FINISHED, &oldFinished),
|
||||
TR_ARG_TUPLE(MC_PRIORITY, &oldPriority),
|
||||
TR_ARG_TUPLE(MC_QUEUE_POSITION, &oldQueuePosition),
|
||||
TR_ARG_TUPLE(MC_TRACKERS, &oldTrackers),
|
||||
TR_ARG_TUPLE(MC_SPEED_UP, &oldUpSpeed),
|
||||
TR_ARG_TUPLE(MC_RECHECK_PROGRESS, &oldRecheckProgress),
|
||||
TR_ARG_TUPLE(MC_SPEED_DOWN, &oldDownSpeed),
|
||||
-1);
|
||||
|
||||
/* 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(newRecheckProgress, oldRecheckProgress, 2) != 0)
|
||||
{
|
||||
gtk_list_store_set(GTK_LIST_STORE(model), iter,
|
||||
MC_ACTIVE, newActive,
|
||||
MC_ACTIVE_PEER_COUNT, newActivePeerCount,
|
||||
MC_ACTIVE_PEERS_UP, newUploadPeerCount,
|
||||
MC_ACTIVE_PEERS_DOWN, newDownloadPeerCount,
|
||||
MC_ERROR, newError,
|
||||
MC_ACTIVITY, newActivity,
|
||||
MC_FINISHED, newFinished,
|
||||
MC_PRIORITY, newPriority,
|
||||
MC_QUEUE_POSITION, newQueuePosition,
|
||||
MC_TRACKERS, newTrackers,
|
||||
MC_SPEED_UP, newUpSpeed,
|
||||
MC_SPEED_DOWN, newDownSpeed,
|
||||
MC_RECHECK_PROGRESS, newRecheckProgress,
|
||||
gtk_list_store_set(
|
||||
GTK_LIST_STORE(model),
|
||||
iter,
|
||||
TR_ARG_TUPLE(MC_ACTIVE, newActive),
|
||||
TR_ARG_TUPLE(MC_ACTIVE_PEER_COUNT, newActivePeerCount),
|
||||
TR_ARG_TUPLE(MC_ACTIVE_PEERS_UP, newUploadPeerCount),
|
||||
TR_ARG_TUPLE(MC_ACTIVE_PEERS_DOWN, newDownloadPeerCount),
|
||||
TR_ARG_TUPLE(MC_ERROR, newError),
|
||||
TR_ARG_TUPLE(MC_ACTIVITY, newActivity),
|
||||
TR_ARG_TUPLE(MC_FINISHED, newFinished),
|
||||
TR_ARG_TUPLE(MC_PRIORITY, newPriority),
|
||||
TR_ARG_TUPLE(MC_QUEUE_POSITION, newQueuePosition),
|
||||
TR_ARG_TUPLE(MC_TRACKERS, newTrackers),
|
||||
TR_ARG_TUPLE(MC_SPEED_UP, newUpSpeed),
|
||||
TR_ARG_TUPLE(MC_SPEED_DOWN, newDownSpeed),
|
||||
TR_ARG_TUPLE(MC_RECHECK_PROGRESS, newRecheckProgress),
|
||||
-1);
|
||||
}
|
||||
}
|
||||
|
@ -1574,8 +1637,7 @@ void gtr_core_update(TrCore* core)
|
|||
do
|
||||
{
|
||||
update_foreach(model, &iter);
|
||||
}
|
||||
while (gtk_tree_model_iter_next(model, &iter));
|
||||
} while (gtk_tree_model_iter_next(model, &iter));
|
||||
}
|
||||
|
||||
/* update hibernation */
|
||||
|
@ -1603,9 +1665,18 @@ static gboolean gtr_inhibit_hibernation(guint* cookie)
|
|||
|
||||
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,
|
||||
SESSION_MANAGER_INTERFACE, "Inhibit", g_variant_new("(susu)", application, toplevel_xid, reason, flags), NULL,
|
||||
G_DBUS_CALL_FLAGS_NONE, 1000, NULL, &err);
|
||||
response = g_dbus_connection_call_sync(
|
||||
connection,
|
||||
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)
|
||||
{
|
||||
|
@ -1647,8 +1718,17 @@ static void gtr_uninhibit_hibernation(guint inhibit_cookie)
|
|||
|
||||
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,
|
||||
SESSION_MANAGER_INTERFACE, "Uninhibit", g_variant_new("(u)", inhibit_cookie), NULL, G_DBUS_CALL_FLAGS_NONE, 1000, NULL,
|
||||
response = g_dbus_connection_call_sync(
|
||||
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);
|
||||
|
||||
/* logging */
|
||||
|
@ -1759,7 +1839,7 @@ void gtr_core_set_pref_double(TrCore* self, tr_quark const key, double newval)
|
|||
|
||||
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
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
|
@ -1956,8 +2040,7 @@ size_t gtr_core_get_active_torrent_count(TrCore* core)
|
|||
{
|
||||
++activeCount;
|
||||
}
|
||||
}
|
||||
while (gtk_tree_model_iter_next(model, &iter));
|
||||
} while (gtk_tree_model_iter_next(model, &iter));
|
||||
}
|
||||
|
||||
return activeCount;
|
||||
|
|
|
@ -40,8 +40,7 @@ typedef struct _TrCore
|
|||
|
||||
/*< private >*/
|
||||
struct TrCorePrivate* priv;
|
||||
}
|
||||
TrCore;
|
||||
} TrCore;
|
||||
|
||||
enum tr_core_err
|
||||
{
|
||||
|
@ -54,15 +53,14 @@ typedef struct _TrCoreClass
|
|||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (* add_error)(TrCore*, enum tr_core_err, char const* name);
|
||||
void (* add_prompt)(TrCore*, gpointer ctor);
|
||||
void (* blocklist_updated)(TrCore*, int ruleCount);
|
||||
void (* busy)(TrCore*, gboolean is_busy);
|
||||
void (* prefs_changed)(TrCore*, tr_quark const key);
|
||||
void (* port_tested)(TrCore*, gboolean is_open);
|
||||
void (* quit)(TrCore*);
|
||||
}
|
||||
TrCoreClass;
|
||||
void (*add_error)(TrCore*, enum tr_core_err, char const* name);
|
||||
void (*add_prompt)(TrCore*, gpointer ctor);
|
||||
void (*blocklist_updated)(TrCore*, int ruleCount);
|
||||
void (*busy)(TrCore*, gboolean is_busy);
|
||||
void (*prefs_changed)(TrCore*, tr_quark const key);
|
||||
void (*port_tested)(TrCore*, gboolean is_open);
|
||||
void (*quit)(TrCore*);
|
||||
} TrCoreClass;
|
||||
|
||||
GType tr_core_get_type(void) G_GNUC_CONST;
|
||||
|
||||
|
|
|
@ -463,8 +463,13 @@ static void onBlocklistUpdate(GtkButton* w, gpointer gdata)
|
|||
{
|
||||
GtkWidget* d;
|
||||
struct blocklist_data* data = gdata;
|
||||
d = gtk_message_dialog_new(GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(w))), GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, "%s", _("Update Blocklist"));
|
||||
d = gtk_message_dialog_new(
|
||||
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_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(d), "%s", _("Getting new blocklist…"));
|
||||
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)
|
||||
{
|
||||
GtkWidget* w = gtr_combo_box_new_enum(_("Allow encryption"), TR_CLEAR_PREFERRED, _("Prefer encryption"),
|
||||
TR_ENCRYPTION_PREFERRED, _("Require encryption"), TR_ENCRYPTION_REQUIRED, NULL);
|
||||
GtkWidget* w = gtr_combo_box_new_enum(
|
||||
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));
|
||||
g_object_set_data(G_OBJECT(w), PREF_KEY, GINT_TO_POINTER(key));
|
||||
g_signal_connect(w, "changed", G_CALLBACK(onIntComboChanged), core);
|
||||
|
@ -572,9 +580,7 @@ enum
|
|||
static GtkTreeModel* whitelist_tree_model_new(char const* whitelist)
|
||||
{
|
||||
char** rules;
|
||||
GtkListStore* store = gtk_list_store_new(N_COLS,
|
||||
G_TYPE_STRING,
|
||||
G_TYPE_STRING);
|
||||
GtkListStore* store = gtk_list_store_new(N_COLS, G_TYPE_STRING, G_TYPE_STRING);
|
||||
|
||||
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, ",");
|
||||
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 */
|
||||
|
@ -832,8 +837,7 @@ static GtkWidget* remotePage(GObject* core)
|
|||
v = page->view = GTK_TREE_VIEW(w);
|
||||
gtk_widget_set_tooltip_text(w, _("IP addresses may use wildcards, such as 192.168.*.*"));
|
||||
sel = gtk_tree_view_get_selection(v);
|
||||
g_signal_connect(sel, "changed",
|
||||
G_CALLBACK(onWhitelistSelectionChanged), page);
|
||||
g_signal_connect(sel, "changed", G_CALLBACK(onWhitelistSelectionChanged), page);
|
||||
g_object_unref(G_OBJECT(m));
|
||||
gtk_tree_view_set_headers_visible(v, TRUE);
|
||||
w = gtk_frame_new(NULL);
|
||||
|
@ -851,7 +855,12 @@ static GtkWidget* remotePage(GObject* core)
|
|||
|
||||
s = _("Addresses:");
|
||||
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);
|
||||
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)
|
||||
{
|
||||
GtkWidget* w = gtr_combo_box_new_enum(
|
||||
_("Every Day"), TR_SCHED_ALL,
|
||||
_("Weekdays"), TR_SCHED_WEEKDAY,
|
||||
_("Weekends"), TR_SCHED_WEEKEND,
|
||||
_("Sunday"), TR_SCHED_SUN,
|
||||
_("Monday"), TR_SCHED_MON,
|
||||
_("Tuesday"), TR_SCHED_TUES,
|
||||
_("Wednesday"), TR_SCHED_WED,
|
||||
_("Thursday"), TR_SCHED_THURS,
|
||||
_("Friday"), TR_SCHED_FRI,
|
||||
_("Saturday"), TR_SCHED_SAT,
|
||||
TR_ARG_TUPLE(_("Every Day"), TR_SCHED_ALL),
|
||||
TR_ARG_TUPLE(_("Weekdays"), TR_SCHED_WEEKDAY),
|
||||
TR_ARG_TUPLE(_("Weekends"), TR_SCHED_WEEKEND),
|
||||
TR_ARG_TUPLE(_("Sunday"), TR_SCHED_SUN),
|
||||
TR_ARG_TUPLE(_("Monday"), TR_SCHED_MON),
|
||||
TR_ARG_TUPLE(_("Tuesday"), TR_SCHED_TUES),
|
||||
TR_ARG_TUPLE(_("Wednesday"), TR_SCHED_WED),
|
||||
TR_ARG_TUPLE(_("Thursday"), TR_SCHED_THURS),
|
||||
TR_ARG_TUPLE(_("Friday"), TR_SCHED_FRI),
|
||||
TR_ARG_TUPLE(_("Saturday"), TR_SCHED_SAT),
|
||||
NULL);
|
||||
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));
|
||||
|
@ -1266,9 +1275,12 @@ GtkWidget* gtr_prefs_dialog_new(GtkWindow* parent, GObject* 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);
|
||||
|
||||
d = gtk_dialog_new_with_buttons(_("Transmission Preferences"), parent, GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
_("_Help"), GTK_RESPONSE_HELP,
|
||||
_("_Close"), GTK_RESPONSE_CLOSE,
|
||||
d = gtk_dialog_new_with_buttons(
|
||||
_("Transmission Preferences"),
|
||||
parent,
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
TR_ARG_TUPLE(_("_Help"), GTK_RESPONSE_HELP),
|
||||
TR_ARG_TUPLE(_("_Close"), GTK_RESPONSE_CLOSE),
|
||||
NULL);
|
||||
g_object_weak_ref(G_OBJECT(d), on_prefs_dialog_destroyed, data);
|
||||
gtk_window_set_role(GTK_WINDOW(d), "transmission-preferences-dialog");
|
||||
|
|
|
@ -61,12 +61,11 @@ typedef struct
|
|||
GtkTreeModel* filter_model;
|
||||
TrCore* core;
|
||||
gulong pref_handler_id;
|
||||
}
|
||||
PrivateData;
|
||||
} PrivateData;
|
||||
|
||||
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());
|
||||
}
|
||||
|
@ -98,7 +97,11 @@ static void view_row_activated(GtkTreeView* tree_view, GtkTreePath* path, GtkTre
|
|||
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)
|
||||
{
|
||||
TR_UNUSED(column);
|
||||
|
@ -133,8 +136,12 @@ static GtkWidget* makeview(PrivateData* p)
|
|||
|
||||
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,
|
||||
"sizing", GTK_TREE_VIEW_COLUMN_FIXED, NULL));
|
||||
p->column = col = GTK_TREE_VIEW_COLUMN(g_object_new(
|
||||
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();
|
||||
gtk_tree_view_column_pack_start(col, r, FALSE);
|
||||
|
@ -234,13 +241,11 @@ static struct
|
|||
{
|
||||
char const* val;
|
||||
char const* i18n;
|
||||
}
|
||||
stats_modes[] =
|
||||
{
|
||||
} stats_modes[] = {
|
||||
{ "total-ratio", N_("Total Ratio") },
|
||||
{ "session-ratio", N_("Session Ratio") },
|
||||
{ "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)
|
||||
|
@ -264,9 +269,8 @@ static void syncAltSpeedButton(PrivateData* p)
|
|||
char d[32];
|
||||
tr_formatter_speed_KBps(d, gtr_pref_int_get(TR_KEY_alt_speed_down), sizeof(d));
|
||||
|
||||
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 enable Alternative Speed Limits\n (%1$s down, %2$s up)"), d, u);
|
||||
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 enable Alternative Speed Limits\n (%1$s down, %2$s up)"), d, u);
|
||||
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), b);
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
#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);
|
||||
#else
|
||||
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;}";
|
||||
css_provider = gtk_css_provider_new();
|
||||
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);
|
||||
|
||||
/* window's main container */
|
||||
|
@ -835,18 +850,19 @@ static void updateSpeeds(PrivateData* p)
|
|||
int dc;
|
||||
double us;
|
||||
double ds;
|
||||
gtk_tree_model_get(model, &iter,
|
||||
MC_SPEED_UP, &us,
|
||||
MC_SPEED_DOWN, &ds,
|
||||
MC_ACTIVE_PEERS_UP, &uc,
|
||||
MC_ACTIVE_PEERS_DOWN, &dc,
|
||||
gtk_tree_model_get(
|
||||
model,
|
||||
&iter,
|
||||
TR_ARG_TUPLE(MC_SPEED_UP, &us),
|
||||
TR_ARG_TUPLE(MC_SPEED_DOWN, &ds),
|
||||
TR_ARG_TUPLE(MC_ACTIVE_PEERS_UP, &uc),
|
||||
TR_ARG_TUPLE(MC_ACTIVE_PEERS_DOWN, &dc),
|
||||
-1);
|
||||
upSpeed += us;
|
||||
upCount += uc;
|
||||
downSpeed += ds;
|
||||
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));
|
||||
|
|
41
gtk/util.c
41
gtk/util.c
|
@ -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)
|
||||
{
|
||||
return str != NULL && (g_str_has_prefix(str, "ftp://") || g_str_has_prefix(str, "http://") ||
|
||||
g_str_has_prefix(str, "https://"));
|
||||
return str != NULL &&
|
||||
(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)
|
||||
|
@ -256,7 +256,9 @@ void gtr_add_torrent_error_dialog(GtkWidget* child, int err, tr_torrent* duplica
|
|||
}
|
||||
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));
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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"));
|
||||
gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(w), "%s", secondary);
|
||||
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);
|
||||
}
|
||||
|
||||
typedef void (* PopupFunc)(GtkWidget*, GdkEventButton*);
|
||||
typedef void (*PopupFunc)(GtkWidget*, GdkEventButton*);
|
||||
|
||||
/* pop up the context menu if a user right-clicks.
|
||||
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)
|
||||
{
|
||||
uri = g_strdup_printf("https://transmissionbt.com/help/gtk/%d.%dx",
|
||||
MAJOR_VERSION, MINOR_VERSION / 10);
|
||||
uri = g_strdup_printf("https://transmissionbt.com/help/gtk/%d.%dx", MAJOR_VERSION, MINOR_VERSION / 10);
|
||||
}
|
||||
|
||||
return uri;
|
||||
|
@ -484,8 +490,7 @@ GtkWidget* gtr_combo_box_new_enum(char const* text_1, ...)
|
|||
int const val = va_arg(vl, int);
|
||||
gtk_list_store_insert_with_values(store, NULL, INT_MAX, 0, val, 1, text, -1);
|
||||
text = va_arg(vl, char const*);
|
||||
}
|
||||
while (text != NULL);
|
||||
} while (text != NULL);
|
||||
|
||||
va_end(vl);
|
||||
}
|
||||
|
@ -516,9 +521,9 @@ int gtr_combo_box_get_active_enum(GtkComboBox* combo_box)
|
|||
GtkWidget* gtr_priority_combo_new(void)
|
||||
{
|
||||
return gtr_combo_box_new_enum(
|
||||
_("High"), TR_PRI_HIGH,
|
||||
_("Normal"), TR_PRI_NORMAL,
|
||||
_("Low"), TR_PRI_LOW,
|
||||
TR_ARG_TUPLE(_("High"), TR_PRI_HIGH),
|
||||
TR_ARG_TUPLE(_("Normal"), TR_PRI_NORMAL),
|
||||
TR_ARG_TUPLE(_("Low"), TR_PRI_LOW),
|
||||
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)
|
||||
{
|
||||
g_string_append_printf(gstr, "\n \n");
|
||||
g_string_append_printf(gstr, _("This magnet link appears to be intended for something other than BitTorrent. "
|
||||
"BitTorrent magnet links have a section containing \"%s\"."), xt);
|
||||
g_string_append_printf(
|
||||
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);
|
||||
|
@ -613,10 +621,9 @@ void gtr_unrecognized_url_dialog(GtkWidget* parent, char const* url)
|
|||
|
||||
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_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)
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <gtk/gtk.h>
|
||||
|
||||
#include <libtransmission/transmission.h>
|
||||
#include <libtransmission/tr-macros.h>
|
||||
|
||||
extern int const mem_K;
|
||||
extern char const* mem_K_str;
|
||||
|
@ -39,15 +40,15 @@ extern char const* speed_T_str;
|
|||
#else
|
||||
|
||||
#define TR_DEFINE_QUARK(QN, q_n) \
|
||||
GQuark q_n ## _quark(void) \
|
||||
GQuark q_n##_quark(void) \
|
||||
{ \
|
||||
static GQuark q; \
|
||||
\
|
||||
\
|
||||
if (G_UNLIKELY(q == 0)) \
|
||||
{ \
|
||||
q = g_quark_from_static_string(#QN); \
|
||||
} \
|
||||
\
|
||||
\
|
||||
return q; \
|
||||
}
|
||||
|
||||
|
|
|
@ -46,8 +46,7 @@ typedef struct
|
|||
|
||||
/* how many hashes to use in the info_hash field */
|
||||
int info_hash_count;
|
||||
}
|
||||
tr_scrape_request;
|
||||
} tr_scrape_request;
|
||||
|
||||
struct tr_scrape_response_row
|
||||
{
|
||||
|
@ -92,15 +91,20 @@ typedef struct
|
|||
/* minimum interval (in seconds) allowed between scrapes.
|
||||
* this is an unofficial extension that some trackers won't support. */
|
||||
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 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);
|
||||
|
||||
/***
|
||||
|
@ -113,8 +117,7 @@ typedef enum
|
|||
TR_ANNOUNCE_EVENT_COMPLETED,
|
||||
TR_ANNOUNCE_EVENT_STARTED,
|
||||
TR_ANNOUNCE_EVENT_STOPPED
|
||||
}
|
||||
tr_announce_event;
|
||||
} 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 */
|
||||
char log_name[128];
|
||||
}
|
||||
tr_announce_request;
|
||||
} tr_announce_request;
|
||||
|
||||
struct tr_pex;
|
||||
|
||||
|
@ -214,15 +216,20 @@ typedef struct
|
|||
/* key generated by and returned from an http tracker.
|
||||
* if this is provided, subsequent http announces must include this. */
|
||||
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 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 tr_tracker_udp_start_shutdown(tr_session* session);
|
||||
|
|
|
@ -36,9 +36,7 @@
|
|||
|
||||
static char const* get_event_string(tr_announce_request const* req)
|
||||
{
|
||||
return req->partial_seed && (req->event != TR_ANNOUNCE_EVENT_STOPPED) ?
|
||||
"paused" :
|
||||
tr_announce_event_get_string(req->event);
|
||||
return req->partial_seed && (req->event != TR_ANNOUNCE_EVENT_STOPPED) ? "paused" : tr_announce_event_get_string(req->event);
|
||||
}
|
||||
|
||||
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_add_printf(buf,
|
||||
evbuffer_add_printf(
|
||||
buf,
|
||||
"%s"
|
||||
"%c"
|
||||
"info_hash=%s"
|
||||
"&peer_id=%*.*s"
|
||||
"&port=%d"
|
||||
"&uploaded=%" PRIu64
|
||||
"&downloaded=%" PRIu64
|
||||
"&uploaded=%" PRIu64 //
|
||||
"&downloaded=%" PRIu64 //
|
||||
"&left=%" PRIu64
|
||||
"&numwant=%d"
|
||||
"&key=%x"
|
||||
|
@ -68,7 +67,7 @@ static char* announce_url_new(tr_session const* session, tr_announce_request con
|
|||
req->url,
|
||||
strchr(req->url, '?') != NULL ? '&' : '?',
|
||||
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->up,
|
||||
req->down,
|
||||
|
@ -199,8 +198,14 @@ static void on_announce_done_eventthread(void* vdata)
|
|||
tr_free(data);
|
||||
}
|
||||
|
||||
static void on_announce_done(tr_session* session, bool did_connect, bool did_timeout, long response_code, void const* msg,
|
||||
size_t msglen, void* vdata)
|
||||
static void on_announce_done(
|
||||
tr_session* session,
|
||||
bool did_connect,
|
||||
bool did_timeout,
|
||||
long response_code,
|
||||
void const* msg,
|
||||
size_t msglen,
|
||||
void* vdata)
|
||||
{
|
||||
tr_announce_response* response;
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct announce_data* d;
|
||||
|
@ -367,8 +375,14 @@ static void on_scrape_done_eventthread(void* vdata)
|
|||
tr_free(data);
|
||||
}
|
||||
|
||||
static void on_scrape_done(tr_session* session, bool did_connect, bool did_timeout, long response_code, void const* msg,
|
||||
size_t msglen, void* vdata)
|
||||
static void on_scrape_done(
|
||||
tr_session* session,
|
||||
bool did_connect,
|
||||
bool did_timeout,
|
||||
long response_code,
|
||||
void const* msg,
|
||||
size_t msglen,
|
||||
void* vdata)
|
||||
{
|
||||
tr_scrape_response* response;
|
||||
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);
|
||||
}
|
||||
|
||||
if (tr_variantDictFindDict(&top, TR_KEY_flags,
|
||||
&flags) && tr_variantDictFindInt(flags, TR_KEY_min_request_interval, &intVal))
|
||||
if (tr_variantDictFindDict(&top, TR_KEY_flags, &flags) &&
|
||||
tr_variantDictFindInt(flags, TR_KEY_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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct scrape_data* d;
|
||||
|
|
|
@ -117,8 +117,7 @@ typedef enum
|
|||
TAU_ACTION_ANNOUNCE = 1,
|
||||
TAU_ACTION_SCRAPE = 2,
|
||||
TAU_ACTION_ERROR = 3
|
||||
}
|
||||
tau_action_t;
|
||||
} tau_action_t;
|
||||
|
||||
static bool is_tau_response_message(tau_action_t action, size_t msglen)
|
||||
{
|
||||
|
@ -170,7 +169,9 @@ struct tau_scrape_request
|
|||
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)
|
||||
{
|
||||
struct evbuffer* buf;
|
||||
|
@ -305,8 +306,7 @@ typedef enum
|
|||
TAU_ANNOUNCE_EVENT_COMPLETED = 1,
|
||||
TAU_ANNOUNCE_EVENT_STARTED = 2,
|
||||
TAU_ANNOUNCE_EVENT_STOPPED = 3
|
||||
}
|
||||
tau_announce_event;
|
||||
} tau_announce_event;
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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->leechers = 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);
|
||||
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_protocol = IPPROTO_UDP;
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
dbgmsg(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,
|
||||
dbgmsg(
|
||||
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);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct tr_announcer_udp* tau = announcer_udp_get(session);
|
||||
|
|
|
@ -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)); \
|
||||
tr_logAddDeep(__FILE__, __LINE__, name, __VA_ARGS__); \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
} while (0)
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -176,8 +175,7 @@ typedef struct tr_announcer
|
|||
int slotsAvailable;
|
||||
int key;
|
||||
time_t tauUpkeepAt;
|
||||
}
|
||||
tr_announcer;
|
||||
} tr_announcer;
|
||||
|
||||
static struct tr_scrape_info* tr_announcerGetScrapeInfo(struct tr_announcer* announcer, char const* url)
|
||||
{
|
||||
|
@ -262,8 +260,7 @@ typedef struct
|
|||
int consecutiveFailures;
|
||||
|
||||
uint32_t id;
|
||||
}
|
||||
tr_tracker;
|
||||
} tr_tracker;
|
||||
|
||||
/* format: host+':'+ port */
|
||||
static char* getKey(char const* url)
|
||||
|
@ -353,8 +350,7 @@ typedef struct tr_tier
|
|||
|
||||
char lastAnnounceStr[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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
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 : "?");
|
||||
}
|
||||
|
||||
|
@ -444,8 +444,7 @@ typedef struct tr_torrent_tiers
|
|||
|
||||
tr_tracker_callback callback;
|
||||
void* callbackData;
|
||||
}
|
||||
tr_torrent_tiers;
|
||||
} tr_torrent_tiers;
|
||||
|
||||
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
|
||||
***/
|
||||
|
||||
static tr_tracker_event const TRACKER_EVENT_INIT =
|
||||
{
|
||||
static tr_tracker_event const TRACKER_EVENT_INIT = {
|
||||
.messageType = TR_TRACKER_WARNING,
|
||||
.text = NULL,
|
||||
.tracker = NULL,
|
||||
.pex = NULL,
|
||||
.pexCount = 0,
|
||||
.seedProbability = 0
|
||||
.seedProbability = 0,
|
||||
};
|
||||
|
||||
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_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;
|
||||
|
||||
dbgmsg(tier,
|
||||
dbgmsg(
|
||||
tier,
|
||||
"Got announce response: "
|
||||
"connected:%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 */
|
||||
if (scrape_fields >= 3 || (scrape_fields >= 1 && tracker->scrape_info == NULL))
|
||||
{
|
||||
tr_logAddTorDbg(tier->tor, "Announce response contained scrape info; "
|
||||
"rescheduling next scrape to %d seconds from now.", tier->scrapeIntervalSec);
|
||||
tr_logAddTorDbg(
|
||||
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->lastScrapeTime = now;
|
||||
tier->lastScrapeSucceeded = true;
|
||||
|
@ -1273,7 +1278,10 @@ static void announce_request_free(tr_announce_request* 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)
|
||||
{
|
||||
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?
|
||||
Add your patch here and open a PR */
|
||||
static char const* const too_long_errors[] =
|
||||
{
|
||||
static char const* const too_long_errors[] = {
|
||||
"Bad Request",
|
||||
"GET string too long",
|
||||
"Request-URI Too Long"
|
||||
"Request-URI Too Long",
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
if (tracker != NULL &&
|
||||
tracker->scrape_info != NULL &&
|
||||
tr_strcmp0(scrape, tracker->scrape_info->url) == 0)
|
||||
if (tracker != NULL && tracker->scrape_info != NULL && tr_strcmp0(scrape, tracker->scrape_info->url) == 0)
|
||||
{
|
||||
return &tt->tiers[i];
|
||||
}
|
||||
|
@ -1424,7 +1429,8 @@ static void on_scrape_done(tr_scrape_response const* response, void* vsession)
|
|||
|
||||
if (tier != NULL)
|
||||
{
|
||||
dbgmsg(tier,
|
||||
dbgmsg(
|
||||
tier,
|
||||
"scraped url:%s -- "
|
||||
"did_connect:%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)
|
||||
{
|
||||
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;
|
||||
|
||||
/* 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]);
|
||||
|
||||
/* secondary key: announcements that have been waiting longer go first */
|
||||
|
|
|
@ -27,8 +27,7 @@ typedef enum
|
|||
TR_TRACKER_ERROR,
|
||||
TR_TRACKER_ERROR_CLEAR,
|
||||
TR_TRACKER_PEERS
|
||||
}
|
||||
TrackerEventType;
|
||||
} TrackerEventType;
|
||||
|
||||
struct tr_pex;
|
||||
|
||||
|
@ -48,10 +47,9 @@ typedef struct
|
|||
|
||||
/* [0...100] for probability a peer is a seed. calculated by the leecher/seeder ratio */
|
||||
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
|
||||
|
|
|
@ -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_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)
|
||||
{
|
||||
fprintf(stderr, "%p consumed %5zu bytes of %5s data... was %6zu, now %6zu left\n", b, byteCount,
|
||||
isPieceData ? "piece" : "raw", oldBytesLeft, band->bytesLeft);
|
||||
fprintf(
|
||||
stderr,
|
||||
"%p consumed %5zu bytes of %5s data... was %6zu, now %6zu left\n",
|
||||
b,
|
||||
byteCount,
|
||||
isPieceData ? "piece" : "raw",
|
||||
oldBytesLeft,
|
||||
band->bytesLeft);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -44,8 +44,7 @@ struct bratecontrol
|
|||
{
|
||||
uint64_t date;
|
||||
uint64_t size;
|
||||
}
|
||||
transfers[HISTORY_SIZE];
|
||||
} transfers[HISTORY_SIZE];
|
||||
uint64_t cache_time;
|
||||
unsigned int cache_val;
|
||||
};
|
||||
|
@ -114,8 +113,7 @@ typedef struct tr_bandwidth
|
|||
tr_session* session;
|
||||
tr_ptrArray children; /* struct tr_bandwidth */
|
||||
struct tr_peerIo* peer;
|
||||
}
|
||||
tr_bandwidth;
|
||||
} tr_bandwidth;
|
||||
|
||||
/**
|
||||
***
|
||||
|
|
|
@ -13,38 +13,36 @@
|
|||
#include "tr-assert.h"
|
||||
#include "utils.h" /* tr_new0() */
|
||||
|
||||
tr_bitfield const TR_BITFIELD_INIT =
|
||||
{
|
||||
tr_bitfield const TR_BITFIELD_INIT = {
|
||||
.bits = NULL,
|
||||
.alloc_count = 0,
|
||||
.bit_count = 0,
|
||||
.true_count = 0,
|
||||
.have_all_hint = false,
|
||||
.have_none_hint = false
|
||||
.have_none_hint = false,
|
||||
};
|
||||
|
||||
/****
|
||||
*****
|
||||
****/
|
||||
|
||||
static int8_t const trueBitCount[256] =
|
||||
{
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
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
|
||||
static int8_t const trueBitCount[256] = {
|
||||
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, //
|
||||
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, //
|
||||
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, //
|
||||
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, //
|
||||
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, //
|
||||
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, //
|
||||
};
|
||||
|
||||
static size_t countArray(tr_bitfield const* b)
|
||||
|
|
|
@ -31,8 +31,7 @@ typedef struct tr_bitfield
|
|||
This occurs when a magnet link's peers send have all / have none */
|
||||
bool have_all_hint;
|
||||
bool have_none_hint;
|
||||
}
|
||||
tr_bitfield;
|
||||
} tr_bitfield;
|
||||
|
||||
/***
|
||||
****
|
||||
|
|
|
@ -235,12 +235,16 @@ static bool parseLine1(char const* line, struct tr_ipv4_range* range)
|
|||
|
||||
++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;
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
|
@ -249,7 +253,7 @@ static bool parseLine1(char const* line, struct tr_ipv4_range* range)
|
|||
|
||||
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))
|
||||
{
|
||||
|
@ -273,13 +277,17 @@ static bool parseLine2(char const* line, struct tr_ipv4_range* range)
|
|||
char str[32];
|
||||
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],
|
||||
&unk) != 9)
|
||||
if (sscanf(
|
||||
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;
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
|
@ -288,7 +296,7 @@ static bool parseLine2(char const* line, struct tr_ipv4_range* range)
|
|||
|
||||
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))
|
||||
{
|
||||
|
@ -311,7 +319,7 @@ static bool parseLine3(char const* line, struct tr_ipv4_range* range)
|
|||
uint32_t ip_u;
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
int err = 0;
|
||||
|
|
|
@ -36,10 +36,20 @@ int tr_cacheSetLimit(tr_cache* cache, int64_t max_bytes);
|
|||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
int tr_cachePrefetchBlock(tr_cache* cache, tr_torrent* torrent, tr_piece_index_t piece, uint32_t offset, uint32_t len);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
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]));
|
||||
}
|
||||
|
||||
|
@ -210,34 +217,69 @@ char* tr_clientForId(char* buf, size_t buflen, void const* id_in)
|
|||
}
|
||||
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') ? "+" : "");
|
||||
}
|
||||
}
|
||||
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]));
|
||||
}
|
||||
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]));
|
||||
}
|
||||
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]));
|
||||
}
|
||||
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),
|
||||
strint(id + 5, 1), getMnemonicEnd(id[6]));
|
||||
tr_snprintf(
|
||||
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)
|
||||
{
|
||||
tr_snprintf(buf, buflen, "\xc2\xb5Torrent Web %d.%d.%d%s", strint(id + 3, 1), strint(id + 4, 1), strint(id + 5,
|
||||
1), getMnemonicEnd(id[6]));
|
||||
tr_snprintf(
|
||||
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)
|
||||
|
@ -655,23 +697,47 @@ char* tr_clientForId(char* buf, size_t buflen, void const* id_in)
|
|||
{
|
||||
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]));
|
||||
}
|
||||
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]));
|
||||
}
|
||||
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),
|
||||
strint(id + 5, 2), getMnemonicEnd(id[7]));
|
||||
tr_snprintf(
|
||||
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)
|
||||
{
|
||||
tr_snprintf(buf, buflen, "\xc2\xb5Torrent Web %d.%d.%d%s", strint(id + 3, 1), strint(id + 4, 1), strint(id + 5,
|
||||
2), getMnemonicEnd(id[7]));
|
||||
tr_snprintf(
|
||||
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))
|
||||
|
|
|
@ -40,8 +40,7 @@ typedef struct tr_completion
|
|||
|
||||
/* number of bytes we want or have now. [0..sizeWhenDone] */
|
||||
uint64_t sizeNow;
|
||||
}
|
||||
tr_completion;
|
||||
} tr_completion;
|
||||
|
||||
/**
|
||||
*** Life Cycle
|
||||
|
|
|
@ -6,11 +6,10 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#if defined(CYASSL_IS_WOLFSSL)
|
||||
#define API_HEADER(x) <wolfssl/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
|
||||
#else
|
||||
#define API_HEADER(x) <cyassl/x>
|
||||
|
@ -25,7 +24,6 @@
|
|||
#include API_HEADER_CRYPT(random.h)
|
||||
#include API_HEADER_CRYPT(sha.h)
|
||||
#include API_HEADER(version.h)
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#include "transmission.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)
|
||||
{
|
||||
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);
|
||||
|
||||
if (!check_result(API(DhGenerateKeyPair)(&handle->dh, get_rng(), handle->private_key, &my_private_key_length, public_key,
|
||||
&my_public_key_length)))
|
||||
if (!check_result(API(DhGenerateKeyPair)(
|
||||
&handle->dh,
|
||||
get_rng(),
|
||||
handle->private_key,
|
||||
&my_private_key_length,
|
||||
public_key,
|
||||
&my_public_key_length)))
|
||||
{
|
||||
tr_lockUnlock(rng_lock);
|
||||
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);
|
||||
|
||||
if (check_result(API(DhAgree)(&handle->dh, ret->key, &my_secret_key_length, handle->private_key, handle->private_key_length,
|
||||
other_public_key, other_public_key_length)))
|
||||
if (check_result(API(DhAgree)(
|
||||
&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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
bool tr_dh_secret_derive(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)
|
||||
bool tr_dh_secret_derive(
|
||||
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(hash != NULL);
|
||||
|
||||
struct tr_dh_secret* handle = raw_handle;
|
||||
|
||||
return tr_sha1(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);
|
||||
return tr_sha1(
|
||||
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)
|
||||
|
|
|
@ -297,7 +297,10 @@ static inline void DH_get0_key(DH const* dh, BIGNUM const** pub_key, BIGNUM cons
|
|||
|
||||
#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)
|
||||
{
|
||||
TR_ASSERT(prime_num != NULL);
|
||||
|
|
|
@ -6,17 +6,15 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#if defined(POLARSSL_IS_MBEDTLS)
|
||||
#define API_HEADER(x) <mbedtls/x>
|
||||
#define API(x) mbedtls_ ## x
|
||||
#define API(x) mbedtls_##x
|
||||
#define API_VERSION_NUMBER MBEDTLS_VERSION_NUMBER
|
||||
#else
|
||||
#define API_HEADER(x) <polarssl/x>
|
||||
#define API(x) x
|
||||
#define API_VERSION_NUMBER POLARSSL_VERSION_NUMBER
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#include API_HEADER(arc4.h)
|
||||
#include API_HEADER(base64.h)
|
||||
|
@ -43,10 +41,10 @@
|
|||
|
||||
#define MY_NAME "tr_crypto_utils"
|
||||
|
||||
typedef API (ctr_drbg_context) api_ctr_drbg_context;
|
||||
typedef API (sha1_context) api_sha1_context;
|
||||
typedef API (arc4_context) api_arc4_context;
|
||||
typedef API (dhm_context) api_dhm_context;
|
||||
typedef API(ctr_drbg_context) api_ctr_drbg_context;
|
||||
typedef API(sha1_context) api_sha1_context;
|
||||
typedef API(arc4_context) api_arc4_context;
|
||||
typedef API(dhm_context) api_dhm_context;
|
||||
|
||||
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)
|
||||
{
|
||||
TR_ASSERT(prime_num != NULL);
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
* 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,
|
||||
size_t append_data_size, uint8_t* hash);
|
||||
bool tr_dh_secret_derive(
|
||||
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.
|
||||
|
|
|
@ -21,16 +21,15 @@
|
|||
#define PRIME_LEN 96
|
||||
#define DH_PRIVKEY_LEN 20
|
||||
|
||||
static uint8_t const dh_P[PRIME_LEN] =
|
||||
{
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
|
||||
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
|
||||
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
|
||||
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
|
||||
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
|
||||
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
|
||||
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
|
||||
0xA6, 0x3A, 0x36, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x05, 0x63,
|
||||
static uint8_t const dh_P[PRIME_LEN] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, //
|
||||
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, //
|
||||
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, //
|
||||
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, //
|
||||
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, //
|
||||
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, //
|
||||
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, //
|
||||
0xA6, 0x3A, 0x36, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x05, 0x63, //
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
bool tr_cryptoSecretKeySha1(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)
|
||||
bool tr_cryptoSecretKeySha1(
|
||||
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->mySecret != NULL);
|
||||
|
|
|
@ -43,8 +43,7 @@ typedef struct
|
|||
uint8_t torrentHash[SHA_DIGEST_LENGTH];
|
||||
bool isIncoming;
|
||||
bool torrentHashIsSet;
|
||||
}
|
||||
tr_crypto;
|
||||
} tr_crypto;
|
||||
|
||||
/** @brief construct a new tr_crypto object */
|
||||
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);
|
||||
|
||||
bool tr_cryptoSecretKeySha1(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);
|
||||
bool tr_cryptoSecretKeySha1(
|
||||
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);
|
||||
|
||||
/* @} */
|
||||
|
||||
|
|
|
@ -26,8 +26,7 @@ typedef struct tr_error
|
|||
int code;
|
||||
/** @brief Error message */
|
||||
char* message;
|
||||
}
|
||||
tr_error;
|
||||
} tr_error;
|
||||
|
||||
/**
|
||||
* @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] ... Format arguments.
|
||||
*/
|
||||
void tr_error_propagate_prefixed(tr_error** new_error, tr_error** old_error, char const* prefix_format, ...) TR_GNUC_PRINTF(3,
|
||||
4);
|
||||
void tr_error_propagate_prefixed(tr_error** new_error, tr_error** old_error, char const* prefix_format, ...)
|
||||
TR_GNUC_PRINTF(3, 4);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
|
|
@ -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,
|
||||
* 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)
|
||||
{
|
||||
int flags;
|
||||
|
@ -214,8 +218,12 @@ static int cached_file_open(struct tr_cached_file* o, char const* filename, bool
|
|||
|
||||
if (!success)
|
||||
{
|
||||
tr_logAddError(_("Couldn't preallocate file \"%1$s\" (%2$s, size: %3$" PRIu64 "): %4$s"),
|
||||
filename, type, file_size, error->message);
|
||||
tr_logAddError(
|
||||
_("Couldn't preallocate file \"%1$s\" (%2$s, size: %3$" PRIu64 "): %4$s"),
|
||||
filename,
|
||||
type,
|
||||
file_size,
|
||||
error->message);
|
||||
goto FAIL;
|
||||
}
|
||||
|
||||
|
@ -263,13 +271,12 @@ struct tr_fileset
|
|||
|
||||
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,
|
||||
.fd = TR_BAD_SYS_FILE,
|
||||
.torrent_id = 0,
|
||||
.file_index = 0,
|
||||
.used_at = 0
|
||||
.used_at = 0,
|
||||
};
|
||||
|
||||
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 */
|
||||
tr_sys_file_t tr_fdFileCheckout(tr_session* session, int torrent_id, tr_file_index_t i, char const* filename, bool writable,
|
||||
tr_preallocation_mode allocation, uint64_t file_size)
|
||||
tr_sys_file_t tr_fdFileCheckout(
|
||||
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_cached_file* o = fileset_lookup(set, torrent_id, i);
|
||||
|
|
|
@ -40,8 +40,14 @@
|
|||
*
|
||||
* @see tr_fdFileClose
|
||||
*/
|
||||
tr_sys_file_t tr_fdFileCheckout(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_fdFileCheckout(
|
||||
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);
|
||||
|
||||
|
|
|
@ -30,23 +30,23 @@
|
|||
|
||||
/* OS-specific file copy (copy_file_range, sendfile64, or copyfile). */
|
||||
#if defined(__linux__)
|
||||
# include <linux/version.h>
|
||||
#include <linux/version.h>
|
||||
/* 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)
|
||||
# define USE_COPY_FILE_RANGE
|
||||
# elif defined(HAVE_SENDFILE64)
|
||||
# include <sys/sendfile.h>
|
||||
# define USE_SENDFILE64
|
||||
# endif
|
||||
#if defined(HAVE_COPY_FILE_RANGE) && LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
|
||||
#define USE_COPY_FILE_RANGE
|
||||
#elif defined(HAVE_SENDFILE64)
|
||||
#include <sys/sendfile.h>
|
||||
#define USE_SENDFILE64
|
||||
#endif
|
||||
#elif defined(__APPLE__) && defined(HAVE_COPYFILE)
|
||||
# include <copyfile.h>
|
||||
# ifndef COPYFILE_CLONE /* macos < 10.12 */
|
||||
# define COPYFILE_CLONE 0
|
||||
# endif
|
||||
# define USE_COPYFILE
|
||||
#include <copyfile.h>
|
||||
#ifndef COPYFILE_CLONE /* macos < 10.12 */
|
||||
#define COPYFILE_CLONE 0
|
||||
#endif
|
||||
#define USE_COPYFILE
|
||||
#elif defined(HAVE_COPY_FILE_RANGE)
|
||||
/* Presently this is only FreeBSD 13+. */
|
||||
# define USE_COPY_FILE_RANGE
|
||||
#define USE_COPY_FILE_RANGE
|
||||
#endif /* __linux__ */
|
||||
|
||||
#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 |=
|
||||
((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_APPEND) != 0 ? O_APPEND : 0) |
|
||||
((flags & TR_SYS_FILE_TRUNCATE) != 0 ? O_TRUNC : 0) |
|
||||
((flags & TR_SYS_FILE_SEQUENTIAL) != 0 ? O_SEQUENTIAL : 0) |
|
||||
native_flags |= //
|
||||
((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_APPEND) != 0 ? O_APPEND : 0) | //
|
||||
((flags & TR_SYS_FILE_TRUNCATE) != 0 ? O_TRUNC : 0) | //
|
||||
((flags & TR_SYS_FILE_SEQUENTIAL) != 0 ? O_SEQUENTIAL : 0) | //
|
||||
O_BINARY | O_LARGEFILE | O_CLOEXEC;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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_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;
|
||||
}
|
||||
|
||||
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_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)
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
struct radvisory const radv =
|
||||
{
|
||||
struct radvisory const radv = {
|
||||
.ra_offset = offset,
|
||||
.ra_count = size
|
||||
.ra_count = size,
|
||||
};
|
||||
|
||||
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((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) +
|
||||
!!(operation & TR_SYS_FILE_LOCK_UN) == 1);
|
||||
TR_ASSERT(
|
||||
!!(operation & TR_SYS_FILE_LOCK_SH) + !!(operation & TR_SYS_FILE_LOCK_EX) + !!(operation & TR_SYS_FILE_LOCK_UN) == 1);
|
||||
|
||||
bool ret;
|
||||
|
||||
|
@ -1138,8 +1148,7 @@ bool tr_sys_file_lock(tr_sys_file_t handle, int operation, tr_error** error)
|
|||
do
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
@ -1173,8 +1182,7 @@ bool tr_sys_file_lock(tr_sys_file_t handle, int operation, tr_error** error)
|
|||
do
|
||||
{
|
||||
ret = flock(handle, native_operation) != -1;
|
||||
}
|
||||
while (!ret && errno == EINTR);
|
||||
} while (!ret && errno == EINTR);
|
||||
|
||||
#else
|
||||
|
||||
|
@ -1216,8 +1224,7 @@ char* tr_sys_dir_get_current(tr_error** error)
|
|||
|
||||
ret = getcwd(tmp, size);
|
||||
size += 2048;
|
||||
}
|
||||
while (ret == NULL && errno == ERANGE);
|
||||
} while (ret == NULL && errno == ERANGE);
|
||||
|
||||
if (ret == NULL)
|
||||
{
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include "utils.h"
|
||||
|
||||
#ifndef MAXSIZE_T
|
||||
#define MAXSIZE_T ((SIZE_T)~((SIZE_T)0))
|
||||
#define MAXSIZE_T ((SIZE_T) ~((SIZE_T)0))
|
||||
#endif
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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_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);
|
||||
|
||||
/* `-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 :
|
||||
TR_N_ELEMENTS(native_local_path_prefix));
|
||||
int const extra_chars_before = is_relative ?
|
||||
0 :
|
||||
(is_unc ? TR_N_ELEMENTS(native_unc_path_prefix) - 2 : TR_N_ELEMENTS(native_local_path_prefix));
|
||||
|
||||
/* 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;
|
||||
|
||||
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);
|
||||
|
||||
|
@ -235,7 +240,13 @@ static tr_sys_file_t open_file(char const* path, DWORD access, DWORD disposition
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -294,8 +305,11 @@ static bool create_dir(char const* path, int flags, int permissions, bool okay_i
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void create_temp_path(char* path_template, void (* callback)(char const* path, void* param,
|
||||
tr_error** error), void* callback_param, tr_error** error)
|
||||
static void create_temp_path(
|
||||
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(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)
|
||||
{
|
||||
stat_to_sys_path_info(attributes.dwFileAttributes, attributes.nFileSizeLow, attributes.nFileSizeHigh,
|
||||
&attributes.ftLastWriteTime, info);
|
||||
stat_to_sys_path_info(
|
||||
attributes.dwFileAttributes,
|
||||
attributes.nFileSizeLow,
|
||||
attributes.nFileSizeHigh,
|
||||
&attributes.ftLastWriteTime,
|
||||
info);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -543,8 +561,14 @@ char* tr_sys_path_resolve(char const* path, tr_error** error)
|
|||
goto fail;
|
||||
}
|
||||
|
||||
handle = CreateFileW(wide_path, FILE_READ_EA, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
handle = CreateFileW(
|
||||
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)
|
||||
{
|
||||
|
@ -961,8 +985,12 @@ bool tr_sys_file_get_info(tr_sys_file_t handle, tr_sys_path_info* info, tr_error
|
|||
|
||||
if (ret)
|
||||
{
|
||||
stat_to_sys_path_info(attributes.dwFileAttributes, attributes.nFileSizeLow, attributes.nFileSizeHigh,
|
||||
&attributes.ftLastWriteTime, info);
|
||||
stat_to_sys_path_info(
|
||||
attributes.dwFileAttributes,
|
||||
attributes.nFileSizeLow,
|
||||
attributes.nFileSizeHigh,
|
||||
&attributes.ftLastWriteTime,
|
||||
info);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1035,7 +1063,12 @@ bool tr_sys_file_read(tr_sys_file_t handle, void* buffer, uint64_t size, uint64_
|
|||
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_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;
|
||||
}
|
||||
|
||||
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_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((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) +
|
||||
!!(operation & TR_SYS_FILE_LOCK_UN) == 1);
|
||||
TR_ASSERT(
|
||||
!!(operation & TR_SYS_FILE_LOCK_SH) + !!(operation & TR_SYS_FILE_LOCK_EX) + !!(operation & TR_SYS_FILE_LOCK_UN) == 1);
|
||||
|
||||
bool ret;
|
||||
OVERLAPPED overlapped = { .Pointer = 0, .hEvent = NULL };
|
||||
|
|
|
@ -57,8 +57,7 @@ typedef enum
|
|||
TR_STD_SYS_FILE_IN,
|
||||
TR_STD_SYS_FILE_OUT,
|
||||
TR_STD_SYS_FILE_ERR
|
||||
}
|
||||
tr_std_sys_file_t;
|
||||
} tr_std_sys_file_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
@ -69,16 +68,14 @@ typedef enum
|
|||
TR_SYS_FILE_APPEND = (1 << 4),
|
||||
TR_SYS_FILE_TRUNCATE = (1 << 5),
|
||||
TR_SYS_FILE_SEQUENTIAL = (1 << 6)
|
||||
}
|
||||
tr_sys_file_open_flags_t;
|
||||
} tr_sys_file_open_flags_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TR_SEEK_SET,
|
||||
TR_SEEK_CUR,
|
||||
TR_SEEK_END
|
||||
}
|
||||
tr_seek_origin_t;
|
||||
} tr_seek_origin_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
@ -86,49 +83,42 @@ typedef enum
|
|||
TR_SYS_FILE_LOCK_EX = (1 << 1),
|
||||
TR_SYS_FILE_LOCK_NB = (1 << 2),
|
||||
TR_SYS_FILE_LOCK_UN = (1 << 3)
|
||||
}
|
||||
tr_sys_file_lock_flags_t;
|
||||
} tr_sys_file_lock_flags_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TR_SYS_PATH_NO_FOLLOW = (1 << 0)
|
||||
}
|
||||
tr_sys_path_get_info_flags_t;
|
||||
} tr_sys_path_get_info_flags_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TR_SYS_FILE_ADVICE_WILL_NEED,
|
||||
TR_SYS_FILE_ADVICE_DONT_NEED
|
||||
}
|
||||
tr_sys_file_advice_t;
|
||||
} tr_sys_file_advice_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TR_SYS_FILE_PREALLOC_SPARSE = (1 << 0)
|
||||
}
|
||||
tr_sys_file_preallocate_flags_t;
|
||||
} tr_sys_file_preallocate_flags_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TR_SYS_DIR_CREATE_PARENTS = (1 << 0)
|
||||
}
|
||||
tr_sys_dir_create_flags_t;
|
||||
} tr_sys_dir_create_flags_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TR_SYS_PATH_IS_FILE,
|
||||
TR_SYS_PATH_IS_DIRECTORY,
|
||||
TR_SYS_PATH_IS_OTHER
|
||||
}
|
||||
tr_sys_path_type_t;
|
||||
} tr_sys_path_type_t;
|
||||
|
||||
typedef struct tr_sys_path_info
|
||||
{
|
||||
tr_sys_path_type_t type;
|
||||
uint64_t size;
|
||||
time_t last_modified_at;
|
||||
}
|
||||
tr_sys_path_info;
|
||||
} tr_sys_path_info;
|
||||
|
||||
/**
|
||||
* @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).
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
|
@ -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).
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
|
@ -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).
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
|
@ -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).
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
|
@ -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).
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
|
|
|
@ -103,8 +103,7 @@ typedef enum
|
|||
AWAITING_PAD_D,
|
||||
/* */
|
||||
N_STATES
|
||||
}
|
||||
handshake_state_t;
|
||||
} handshake_state_t;
|
||||
|
||||
struct tr_handshake
|
||||
{
|
||||
|
@ -132,16 +131,16 @@ struct tr_handshake
|
|||
**/
|
||||
|
||||
#define dbgmsg(handshake, ...) \
|
||||
do { \
|
||||
do \
|
||||
{ \
|
||||
char addrstr[TR_ADDRSTRLEN]; \
|
||||
tr_peerIoGetAddrStr(handshake->io, addrstr, sizeof(addrstr)); \
|
||||
tr_logAddDeepNamed(addrstr, __VA_ARGS__); \
|
||||
} while(0)
|
||||
} while (0)
|
||||
|
||||
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 peer id", /* AWAITING_PEER_ID */
|
||||
"awaiting ya", /* AWAITING_YA */
|
||||
|
@ -215,8 +214,7 @@ typedef enum
|
|||
HANDSHAKE_ENCRYPTION_WRONG,
|
||||
HANDSHAKE_BAD_TORRENT,
|
||||
HANDSHAKE_PEER_IS_SELF,
|
||||
}
|
||||
handshake_parse_err_t;
|
||||
} handshake_parse_err_t;
|
||||
|
||||
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 */
|
||||
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);
|
||||
|
||||
|
@ -1093,8 +1091,13 @@ static ReadState canRead(struct tr_peerIo* io, void* arg, size_t* piece)
|
|||
static bool fireDoneFunc(tr_handshake* handshake, bool isConnected)
|
||||
{
|
||||
uint8_t const* peer_id = (isConnected && handshake->havePeerID) ? tr_peerIoGetPeersId(handshake->io) : NULL;
|
||||
bool const success = (*handshake->doneCB)(handshake, handshake->io, handshake->haveReadAnythingFromPeer, isConnected,
|
||||
peer_id, handshake->doneUserData);
|
||||
bool const success = (*handshake->doneCB)(
|
||||
handshake,
|
||||
handshake->io,
|
||||
handshake->haveReadAnythingFromPeer,
|
||||
isConnected,
|
||||
peer_id,
|
||||
handshake->doneUserData);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
|
|
@ -25,11 +25,19 @@ struct tr_peerIo;
|
|||
typedef struct tr_handshake tr_handshake;
|
||||
|
||||
/* returns true on success, false on error */
|
||||
typedef bool (* handshakeDoneCB)(struct tr_handshake* handshake, struct tr_peerIo* io, bool readAnythingFromPeer,
|
||||
bool isConnected, uint8_t const* peerId, void* userData);
|
||||
typedef bool (*handshakeDoneCB)(
|
||||
struct tr_handshake* handshake,
|
||||
struct tr_peerIo* io,
|
||||
bool readAnythingFromPeer,
|
||||
bool isConnected,
|
||||
uint8_t const* peerId,
|
||||
void* userData);
|
||||
|
||||
/** @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);
|
||||
|
||||
tr_address const* tr_handshakeGetAddr(struct tr_handshake const* handshake, tr_port* port);
|
||||
|
|
|
@ -42,10 +42,8 @@ typedef struct tr_recentHistory
|
|||
{
|
||||
unsigned int n;
|
||||
time_t date;
|
||||
}
|
||||
slices[TR_RECENT_HISTORY_PERIOD_SEC];
|
||||
}
|
||||
tr_recentHistory;
|
||||
} slices[TR_RECENT_HISTORY_PERIOD_SEC];
|
||||
} tr_recentHistory;
|
||||
|
||||
/**
|
||||
* @brief add a counter to the recent history object.
|
||||
|
|
|
@ -37,8 +37,14 @@ enum
|
|||
};
|
||||
|
||||
/* 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,
|
||||
void* buf, size_t buflen)
|
||||
static int readOrWriteBytes(
|
||||
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;
|
||||
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 */
|
||||
base = tr_torrentGetCurrentDir(tor);
|
||||
subpath = tr_sessionIsIncompleteFileNamingEnabled(tor->session) ? tr_torrentBuildPartial(tor, fileIndex) :
|
||||
tr_strdup(file->name);
|
||||
tr_strdup(file->name);
|
||||
}
|
||||
|
||||
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);
|
||||
int const prealloc = (file->dnd || !doWrite) ? TR_PREALLOCATE_NONE : tor->session->preallocationMode;
|
||||
|
||||
if ((fd = tr_fdFileCheckout(session, tor->uniqueId, fileIndex, filename, doWrite, prealloc,
|
||||
file->length)) == TR_BAD_SYS_FILE)
|
||||
if ((fd = tr_fdFileCheckout(session, tor->uniqueId, fileIndex, filename, doWrite, prealloc, file->length)) ==
|
||||
TR_BAD_SYS_FILE)
|
||||
{
|
||||
err = errno;
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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 */
|
||||
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)
|
||||
{
|
||||
int err = 0;
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
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);
|
||||
|
||||
/* @} */
|
||||
|
|
|
@ -11,11 +11,10 @@
|
|||
#include "platform.h"
|
||||
#include "utils.h"
|
||||
|
||||
static tr_list const TR_LIST_CLEAR =
|
||||
{
|
||||
static tr_list const TR_LIST_CLEAR = {
|
||||
.data = NULL,
|
||||
.next = NULL,
|
||||
.prev = NULL
|
||||
.prev = NULL,
|
||||
};
|
||||
|
||||
static tr_list* recycled_nodes = NULL;
|
||||
|
|
|
@ -25,11 +25,10 @@ typedef struct tr_list
|
|||
void* data;
|
||||
struct tr_list* next;
|
||||
struct tr_list* prev;
|
||||
}
|
||||
tr_list;
|
||||
} tr_list;
|
||||
|
||||
typedef tr_voidptr_compare_func TrListCompareFunc;
|
||||
typedef void (* TrListForeachFunc)(void*);
|
||||
typedef void (*TrListForeachFunc)(void*);
|
||||
|
||||
/**
|
||||
* @brief return the number of items in the list
|
||||
|
|
|
@ -25,7 +25,7 @@ static inline bool tr_logLevelIsActive(tr_log_level 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);
|
||||
|
||||
#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__); \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
} while (0)
|
||||
|
||||
#define tr_logAddNamedError(name, ...) tr_logAddNamed(TR_LOG_ERROR, 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 */
|
||||
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);
|
||||
|
||||
#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__); \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
} while (0)
|
||||
|
||||
/** @brief set the buffer with the current time formatted for deep logging. */
|
||||
char* tr_logGetTimeStr(char* buf, size_t buflen) TR_GNUC_NONNULL(1);
|
||||
|
|
|
@ -24,8 +24,7 @@
|
|||
/* this base32 code converted from code by Robert Kaye and Gordon Mohr
|
||||
* 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* '8', '9', ':', ';', '<', '=', '>', '?' */
|
||||
0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G' */
|
||||
|
|
|
@ -29,8 +29,7 @@ typedef struct tr_magnet_info
|
|||
|
||||
int webseedCount;
|
||||
char** webseeds;
|
||||
}
|
||||
tr_magnet_info;
|
||||
} tr_magnet_info;
|
||||
|
||||
tr_magnet_info* tr_magnetParse(char const* uri);
|
||||
|
||||
|
|
|
@ -349,7 +349,10 @@ static uint8_t* getHashInfo(tr_metainfo_builder* b)
|
|||
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)
|
||||
{
|
||||
size_t offset;
|
||||
|
@ -491,8 +494,7 @@ static void tr_realMakeMetaInfo(tr_metainfo_builder* builder)
|
|||
}
|
||||
|
||||
/* save the file */
|
||||
if ((builder->result == TR_MAKEMETA_OK) &&
|
||||
(!builder->abortFlag) &&
|
||||
if ((builder->result == TR_MAKEMETA_OK) && (!builder->abortFlag) &&
|
||||
(tr_variantToFile(&top, TR_VARIANT_FMT_BENC, builder->outputFile) != 0))
|
||||
{
|
||||
builder->my_errno = errno;
|
||||
|
@ -565,8 +567,13 @@ static void makeMetaWorkerFunc(void* user_data)
|
|||
workerThread = NULL;
|
||||
}
|
||||
|
||||
void tr_makeMetaInfo(tr_metainfo_builder* builder, char const* outputFile, tr_tracker_info const* trackers, int trackerCount,
|
||||
char const* comment, bool isPrivate)
|
||||
void tr_makeMetaInfo(
|
||||
tr_metainfo_builder* builder,
|
||||
char const* outputFile,
|
||||
tr_tracker_info const* trackers,
|
||||
int trackerCount,
|
||||
char const* comment,
|
||||
bool isPrivate)
|
||||
{
|
||||
tr_lock* lock;
|
||||
|
||||
|
|
|
@ -17,8 +17,7 @@ typedef struct tr_metainfo_builder_file
|
|||
{
|
||||
char* filename;
|
||||
uint64_t size;
|
||||
}
|
||||
tr_metainfo_builder_file;
|
||||
} tr_metainfo_builder_file;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
@ -27,8 +26,7 @@ typedef enum
|
|||
TR_MAKEMETA_CANCELLED,
|
||||
TR_MAKEMETA_IO_READ, /* 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
|
||||
{
|
||||
|
@ -82,8 +80,7 @@ typedef struct tr_metainfo_builder
|
|||
**/
|
||||
|
||||
struct tr_metainfo_builder* nextBuilder;
|
||||
}
|
||||
tr_metainfo_builder;
|
||||
} tr_metainfo_builder;
|
||||
|
||||
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
|
||||
*/
|
||||
void tr_makeMetaInfo(tr_metainfo_builder* builder, char const* outputFile, tr_tracker_info const* trackers, int trackerCount,
|
||||
char const* comment, bool isPrivate);
|
||||
void tr_makeMetaInfo(
|
||||
tr_metainfo_builder* builder,
|
||||
char const* outputFile,
|
||||
tr_tracker_info const* trackers,
|
||||
int trackerCount,
|
||||
char const* comment,
|
||||
bool isPrivate);
|
||||
|
||||
TR_END_DECLS
|
||||
|
|
|
@ -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 */
|
||||
char const* const reserved_chars = "<>:\"/\\|?*";
|
||||
char const* const reserved_names[] =
|
||||
{
|
||||
"CON", "PRN", "AUX", "NUL",
|
||||
"COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
|
||||
"LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9"
|
||||
char const* const reserved_names[] = {
|
||||
"CON", "PRN", "AUX", "NUL", //
|
||||
"COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", //
|
||||
"LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9", //
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (!tr_variantDictFindList(file, TR_KEY_path_utf_8, &path) &&
|
||||
!tr_variantDictFindList(file, TR_KEY_path, &path))
|
||||
if (!tr_variantDictFindList(file, TR_KEY_path_utf_8, &path) && !tr_variantDictFindList(file, TR_KEY_path, &path))
|
||||
{
|
||||
result = "path";
|
||||
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] != '/')
|
||||
{
|
||||
ret = tr_strdup_printf("%*.*s/", (int)len, (int)len, url);
|
||||
ret = tr_strdup_printf("%*.*s/", TR_ARG_TUPLE((int)len, (int)len, url));
|
||||
}
|
||||
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)
|
||||
{
|
||||
int64_t i;
|
||||
|
@ -661,8 +663,7 @@ static char const* tr_metainfoParseImpl(tr_session const* session, tr_info* inf,
|
|||
inf->dateCreated = i;
|
||||
|
||||
/* private */
|
||||
if (!tr_variantDictFindInt(infoDict, TR_KEY_private, &i) &&
|
||||
!tr_variantDictFindInt(meta, TR_KEY_private, &i))
|
||||
if (!tr_variantDictFindInt(infoDict, TR_KEY_private, &i) && !tr_variantDictFindInt(meta, TR_KEY_private, &i))
|
||||
{
|
||||
i = 0;
|
||||
}
|
||||
|
@ -705,8 +706,8 @@ static char const* tr_metainfoParseImpl(tr_session const* session, tr_info* inf,
|
|||
/* files */
|
||||
if (!isMagnet)
|
||||
{
|
||||
if ((str = parseFiles(inf, tr_variantDictFind(infoDict, TR_KEY_files), tr_variantDictFind(infoDict,
|
||||
TR_KEY_length))) != NULL)
|
||||
if ((str = parseFiles(inf, tr_variantDictFind(infoDict, TR_KEY_files), tr_variantDictFind(infoDict, TR_KEY_length))) !=
|
||||
NULL)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
@ -738,7 +739,11 @@ static char const* tr_metainfoParseImpl(tr_session const* session, tr_info* inf,
|
|||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
char* old_filename = getTorrentFilename(session, info, old_format);
|
||||
|
|
|
@ -24,14 +24,21 @@ enum tr_metainfo_basename_format
|
|||
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);
|
||||
|
||||
void tr_metainfoRemoveSaved(tr_session const* session, tr_info const* info);
|
||||
|
||||
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);
|
||||
|
||||
/** @brief Private function that's exposed here only for unit tests */
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
|
||||
#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" },
|
||||
{ "1km", "application/vnd.1000minds.decision-model+xml" },
|
||||
{ "3dml", "text/vnd.in3d.3dml" },
|
||||
|
|
|
@ -40,8 +40,7 @@ typedef enum
|
|||
TR_NATPMP_RECV_MAP,
|
||||
TR_NATPMP_SEND_UNMAP,
|
||||
TR_NATPMP_RECV_UNMAP
|
||||
}
|
||||
tr_natpmp_state;
|
||||
} tr_natpmp_state;
|
||||
|
||||
struct tr_natpmp
|
||||
{
|
||||
|
@ -74,7 +73,13 @@ static void logVal(char const* func, int ret)
|
|||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
@ -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) &&
|
||||
(nat->is_mapped) &&
|
||||
if ((nat->state == TR_NATPMP_IDLE || nat->state == TR_NATPMP_ERR) && (nat->is_mapped) &&
|
||||
(!is_enabled || nat->private_port != private_port))
|
||||
{
|
||||
nat->state = TR_NATPMP_SEND_UNMAP;
|
||||
|
|
|
@ -49,19 +49,17 @@
|
|||
#include "utils.h" /* tr_time(), tr_logAddDebug() */
|
||||
|
||||
#ifndef IN_MULTICAST
|
||||
#define IN_MULTICAST(a) (((a) & 0xf0000000) == 0xe0000000)
|
||||
#define IN_MULTICAST(a) (((a)&0xf0000000) == 0xe0000000)
|
||||
#endif
|
||||
|
||||
tr_address const tr_in6addr_any =
|
||||
{
|
||||
tr_address const tr_in6addr_any = {
|
||||
.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,
|
||||
.addr.addr4.s_addr = INADDR_ANY
|
||||
.addr.addr4.s_addr = INADDR_ANY,
|
||||
};
|
||||
|
||||
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 ?
|
||||
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));
|
||||
return a->type == TR_AF_INET ? 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));
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -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)
|
||||
{
|
||||
char err_buf[512];
|
||||
tr_logAddNamedInfo("Net", "Can't set congestion control algorithm '%s': %s", algorithm, tr_net_strerror(err_buf,
|
||||
sizeof(err_buf), sockerrno));
|
||||
tr_logAddNamedInfo(
|
||||
"Net",
|
||||
"Can't set congestion control algorithm '%s': %s",
|
||||
algorithm,
|
||||
tr_net_strerror(err_buf, sizeof(err_buf), sockerrno));
|
||||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
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_netClose(session, s);
|
||||
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)
|
||||
{
|
||||
tr_logAddError(_("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_logAddError(
|
||||
_("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);
|
||||
|
|
|
@ -83,8 +83,7 @@ typedef enum tr_address_type
|
|||
TR_AF_INET,
|
||||
TR_AF_INET6,
|
||||
NUM_TR_AF_INET_TYPES
|
||||
}
|
||||
tr_address_type;
|
||||
} tr_address_type;
|
||||
|
||||
typedef struct tr_address
|
||||
{
|
||||
|
@ -93,10 +92,8 @@ typedef struct tr_address
|
|||
{
|
||||
struct in6_addr addr6;
|
||||
struct in_addr addr4;
|
||||
}
|
||||
addr;
|
||||
}
|
||||
tr_address;
|
||||
} addr;
|
||||
} tr_address;
|
||||
|
||||
extern tr_address const tr_inaddr_any;
|
||||
extern tr_address const tr_in6addr_any;
|
||||
|
|
|
@ -52,8 +52,7 @@ typedef enum
|
|||
TR_PEER_CLIENT_GOT_HAVE_NONE,
|
||||
TR_PEER_PEER_GOT_PIECE_DATA,
|
||||
TR_PEER_ERROR
|
||||
}
|
||||
PeerEventType;
|
||||
} PeerEventType;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -65,20 +64,19 @@ typedef struct
|
|||
uint32_t length; /* for GOT_BLOCK + GOT_PIECE_DATA */
|
||||
int err; /* errno for GOT_ERROR */
|
||||
tr_port port; /* for GOT_PORT */
|
||||
}
|
||||
tr_peer_event;
|
||||
} tr_peer_event;
|
||||
|
||||
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 bool (* tr_peer_is_transferring_pieces_func)(struct tr_peer const* peer, uint64_t now, tr_direction direction,
|
||||
unsigned int* Bps);
|
||||
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, unsigned int* Bps);
|
||||
|
||||
struct tr_peer_virtual_funcs
|
||||
{
|
||||
|
@ -129,8 +127,7 @@ typedef struct tr_peer
|
|||
tr_recentHistory cancelsSentToPeer;
|
||||
|
||||
struct tr_peer_virtual_funcs const* funcs;
|
||||
}
|
||||
tr_peer;
|
||||
} tr_peer;
|
||||
|
||||
void tr_peerConstruct(struct tr_peer* peer, tr_torrent const* tor);
|
||||
|
||||
|
@ -151,8 +148,7 @@ typedef struct tr_swarm_stats
|
|||
int activeWebseedCount;
|
||||
int peerCount;
|
||||
int peerFromCount[TR_PEER_FROM__MAX];
|
||||
}
|
||||
tr_swarm_stats;
|
||||
} tr_swarm_stats;
|
||||
|
||||
extern tr_swarm_stats const TR_SWARM_STATS_INIT;
|
||||
|
||||
|
|
|
@ -71,11 +71,12 @@ static size_t guessPacketOverhead(size_t d)
|
|||
**/
|
||||
|
||||
#define dbgmsg(io, ...) \
|
||||
do { \
|
||||
do \
|
||||
{ \
|
||||
char addrstr[TR_ADDRSTRLEN]; \
|
||||
tr_peerIoGetAddrStr(io, addrstr, sizeof(addrstr)); \
|
||||
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 const TR_DATATYPE_INIT =
|
||||
{
|
||||
static struct tr_datatype const TR_DATATYPE_INIT = {
|
||||
.next = NULL,
|
||||
.length = 0,
|
||||
.isPieceData = false
|
||||
.isPieceData = false,
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
static struct UTPFunctionTable utp_function_table =
|
||||
{
|
||||
static struct UTPFunctionTable utp_function_table = {
|
||||
.on_read = utp_on_read,
|
||||
.on_write = utp_on_write,
|
||||
.get_rb_size = utp_get_rb_size,
|
||||
.on_state = utp_on_state_change,
|
||||
.on_error = utp_on_error,
|
||||
.on_overhead = utp_on_overhead
|
||||
.on_overhead = utp_on_overhead,
|
||||
};
|
||||
|
||||
/* Dummy UTP callbacks. */
|
||||
|
@ -638,20 +642,26 @@ static void dummy_on_overhead(void* closure, uint8_t /* bool */ send, size_t cou
|
|||
TR_UNUSED(type);
|
||||
}
|
||||
|
||||
static struct UTPFunctionTable dummy_utp_function_table =
|
||||
{
|
||||
static struct UTPFunctionTable dummy_utp_function_table = {
|
||||
.on_read = dummy_read,
|
||||
.on_write = dummy_write,
|
||||
.get_rb_size = dummy_get_rb_size,
|
||||
.on_state = dummy_on_state_change,
|
||||
.on_error = dummy_on_error,
|
||||
.on_overhead = dummy_on_overhead
|
||||
.on_overhead = dummy_on_overhead,
|
||||
};
|
||||
|
||||
#endif /* #ifdef WITH_UTP */
|
||||
|
||||
static tr_peerIo* tr_peerIoNew(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)
|
||||
static tr_peerIo* tr_peerIoNew(
|
||||
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->events != NULL);
|
||||
|
@ -719,7 +729,11 @@ static tr_peerIo* tr_peerIoNew(tr_session* session, tr_bandwidth* parent, tr_add
|
|||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
tr_peerIo* tr_peerIoNewOutgoing(tr_session* session, tr_bandwidth* parent, tr_address const* addr, tr_port port,
|
||||
uint8_t const* torrentHash, bool isSeed, bool utp)
|
||||
tr_peerIo* tr_peerIoNewOutgoing(
|
||||
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(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)
|
||||
{
|
||||
socket = tr_netOpenPeerSocket(session, addr, port, isSeed);
|
||||
dbgmsg(NULL, "tr_netOpenPeerSocket returned fd %" PRIdMAX, (intmax_t)(socket.type != TR_PEER_SOCKET_TYPE_NONE ?
|
||||
socket.handle.tcp : TR_BAD_SOCKET));
|
||||
dbgmsg(
|
||||
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)
|
||||
|
@ -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)(
|
||||
tr_crypto*, size_t, void const*, void*))
|
||||
static inline void processBuffer(
|
||||
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_iovec iovec;
|
||||
|
@ -1140,8 +1166,7 @@ static inline void processBuffer(tr_crypto* crypto, struct evbuffer* buffer, siz
|
|||
|
||||
TR_ASSERT(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);
|
||||
}
|
||||
|
@ -1343,7 +1368,12 @@ static int tr_peerIoTryRead(tr_peerIo* io, size_t howmuch)
|
|||
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));
|
||||
|
||||
io->gotError(io, what, io->userData);
|
||||
|
@ -1398,7 +1428,12 @@ static int tr_peerIoTryWrite(tr_peerIo* io, size_t howmuch)
|
|||
char errstr[512];
|
||||
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));
|
||||
|
||||
io->gotError(io, what, io->userData);
|
||||
|
|
|
@ -40,22 +40,20 @@ typedef enum
|
|||
READ_NOW,
|
||||
READ_LATER,
|
||||
READ_ERR
|
||||
}
|
||||
ReadState;
|
||||
} ReadState;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/* these match the values in MSE's crypto_select */
|
||||
PEER_ENCRYPTION_NONE = (1 << 0),
|
||||
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
|
||||
{
|
||||
|
@ -102,17 +100,26 @@ typedef struct tr_peerIo
|
|||
|
||||
struct event* event_read;
|
||||
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,
|
||||
uint8_t const* torrentHash, bool isSeed, bool utp);
|
||||
tr_peerIo* tr_peerIoNewOutgoing(
|
||||
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);
|
||||
|
||||
void tr_peerIoRefImpl(char const* file, int line, tr_peerIo* io);
|
||||
|
|
|
@ -82,23 +82,21 @@ enum
|
|||
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,
|
||||
.pieceIndex = 0,
|
||||
.bitfield = NULL,
|
||||
.offset = 0,
|
||||
.length = 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 },
|
||||
.activeWebseedCount = 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 addrstr[TR_ADDRSTRLEN];
|
||||
return atom != NULL ?
|
||||
tr_address_and_port_to_string(addrstr, sizeof(addrstr), &atom->addr, atom->port) :
|
||||
"[no atom]";
|
||||
return atom != NULL ? tr_address_and_port_to_string(addrstr, sizeof(addrstr), &atom->addr, atom->port) : "[no atom]";
|
||||
}
|
||||
|
||||
struct block_request
|
||||
|
@ -225,8 +221,7 @@ typedef struct tr_swarm
|
|||
* requests are considered 'fast' are allowed to request a block that's
|
||||
* already been requested from another (slower?) peer. */
|
||||
int endgame;
|
||||
}
|
||||
tr_swarm;
|
||||
} tr_swarm;
|
||||
|
||||
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... */
|
||||
{
|
||||
bool exact;
|
||||
int const pos = tr_lowerBound(&key, s->requests, s->requestCount, sizeof(struct block_request), compareReqByBlock,
|
||||
&exact);
|
||||
int const
|
||||
pos = tr_lowerBound(&key, s->requests, s->requestCount, sizeof(struct block_request), compareReqByBlock, &exact);
|
||||
TR_ASSERT(!exact);
|
||||
memmove(s->requests + pos + 1, s->requests + pos, sizeof(struct block_request) * (s->requestCount++ - pos));
|
||||
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)
|
||||
{
|
||||
if ((b->peer != NULL) &&
|
||||
(b->peer->pendingReqsToPeer > 0))
|
||||
if ((b->peer != NULL) && (b->peer->pendingReqsToPeer > 0))
|
||||
{
|
||||
--b->peer->pendingReqsToPeer;
|
||||
}
|
||||
|
@ -1335,7 +1329,12 @@ void tr_peerMgrRebuildRequests(tr_torrent* tor)
|
|||
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)
|
||||
{
|
||||
/* 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);
|
||||
|
||||
for (tr_block_index_t b = first; b <= last && (got < numwant || (get_intervals && setme[2 * got - 1] == b - 1));
|
||||
++b)
|
||||
++b)
|
||||
{
|
||||
int peerCount;
|
||||
tr_peer** peers;
|
||||
|
@ -1474,8 +1473,13 @@ void tr_peerMgrGetNextRequests(tr_torrent* tor, tr_peer* peer, int numwant, tr_b
|
|||
bool exact;
|
||||
|
||||
/* relative position! */
|
||||
int const newpos = tr_lowerBound(&s->pieces[i], &s->pieces[i + 1], s->pieceCount - (i + 1),
|
||||
sizeof(struct weighted_piece), comparePieceByWeight, &exact);
|
||||
int const newpos = tr_lowerBound(
|
||||
&s->pieces[i],
|
||||
&s->pieces[i + 1],
|
||||
s->pieceCount - (i + 1),
|
||||
sizeof(struct weighted_piece),
|
||||
comparePieceByWeight,
|
||||
&exact);
|
||||
|
||||
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 */
|
||||
peer->doPurge = true;
|
||||
tordbg(s, "setting %s doPurge flag because we got an ERANGE, EMSGSIZE, or ENOTCONN error", tr_atomAddrStr(
|
||||
peer->atom));
|
||||
tordbg(
|
||||
s,
|
||||
"setting %s doPurge flag because we got an ERANGE, EMSGSIZE, or ENOTCONN error",
|
||||
tr_atomAddrStr(peer->atom));
|
||||
}
|
||||
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,
|
||||
int8_t const seedProbability, uint8_t const from)
|
||||
static void ensureAtomExists(
|
||||
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(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. */
|
||||
static bool myHandshakeDoneCB(tr_handshake* handshake, tr_peerIo* io, bool readAnythingFromPeer, bool isConnected,
|
||||
uint8_t const* peer_id, void* vmanager)
|
||||
static bool myHandshakeDoneCB(
|
||||
tr_handshake* handshake,
|
||||
tr_peerIo* io,
|
||||
bool readAnythingFromPeer,
|
||||
bool isConnected,
|
||||
uint8_t const* peer_id,
|
||||
void* vmanager)
|
||||
{
|
||||
TR_ASSERT(io != NULL);
|
||||
|
||||
|
@ -2114,7 +2130,8 @@ static bool myHandshakeDoneCB(tr_handshake* handshake, tr_peerIo* io, bool readA
|
|||
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);
|
||||
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 n = compactLen / 6;
|
||||
|
@ -2231,7 +2252,11 @@ tr_pex* tr_peerMgrCompactToPex(void const* compact, size_t compactLen, uint8_t c
|
|||
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 n = compactLen / 18;
|
||||
|
@ -2271,7 +2296,11 @@ void tr_peerMgrGotBadPiece(tr_torrent* tor, tr_piece_index_t 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);
|
||||
addStrike(s, peer);
|
||||
}
|
||||
|
@ -2932,8 +2961,7 @@ typedef enum
|
|||
RECHOKE_STATE_GOOD,
|
||||
RECHOKE_STATE_UNTESTED,
|
||||
RECHOKE_STATE_BAD
|
||||
}
|
||||
tr_rechoke_state;
|
||||
} tr_rechoke_state;
|
||||
|
||||
struct tr_rechoke_info
|
||||
{
|
||||
|
@ -3018,7 +3046,10 @@ static void rechokeDownloads(tr_swarm* s)
|
|||
double const cancelRate = cancels / (double)(cancels + blocks);
|
||||
double const mult = 1 - MIN(cancelRate, 0.5);
|
||||
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);
|
||||
s->lastCancel = now;
|
||||
}
|
||||
|
@ -3032,8 +3063,11 @@ static void rechokeDownloads(tr_swarm* s)
|
|||
double const mult = MIN(timeSinceCancel, maxHistory) / (double)maxHistory;
|
||||
int const inc = maxIncrease * mult;
|
||||
maxPeers = s->maxPeers + inc;
|
||||
tordbg(s, "time since last cancel is %jd -- increasing the number of peers we're interested in by %d",
|
||||
(intmax_t)timeSinceCancel, inc);
|
||||
tordbg(
|
||||
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 */
|
||||
else if (tr_torrentIsPrivate(tor))
|
||||
{
|
||||
Bps = tr_peerGetPieceSpeed_Bps(atom->peer, now, TR_PEER_TO_CLIENT) + tr_peerGetPieceSpeed_Bps(atom->peer, now,
|
||||
TR_CLIENT_TO_PEER);
|
||||
Bps = tr_peerGetPieceSpeed_Bps(atom->peer, now, TR_PEER_TO_CLIENT) +
|
||||
tr_peerGetPieceSpeed_Bps(atom->peer, now, TR_CLIENT_TO_PEER);
|
||||
}
|
||||
/* downloading a public torrent */
|
||||
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 zero connections, strictness is 0% */
|
||||
float const strictness = peerCount >= relaxStrictnessIfFewerThanN ? 1.0 :
|
||||
peerCount / (float)relaxStrictnessIfFewerThanN;
|
||||
peerCount / (float)relaxStrictnessIfFewerThanN;
|
||||
int const lo = MIN_UPLOAD_IDLE_SECS;
|
||||
int const hi = MAX_UPLOAD_IDLE_SECS;
|
||||
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));
|
||||
|
||||
io = tr_peerIoNewOutgoing(mgr->session, &mgr->session->bandwidth, &atom->addr, atom->port, s->tor->info.hash,
|
||||
s->tor->completeness == TR_SEED, utp);
|
||||
io = tr_peerIoNewOutgoing(
|
||||
mgr->session,
|
||||
&mgr->session->bandwidth,
|
||||
&atom->addr,
|
||||
atom->port,
|
||||
s->tor->info.hash,
|
||||
s->tor->completeness == TR_SEED,
|
||||
utp);
|
||||
|
||||
if (io == NULL)
|
||||
{
|
||||
|
|
|
@ -54,8 +54,7 @@ typedef struct tr_pex
|
|||
tr_address addr;
|
||||
tr_port port; /* this field is in network byte order */
|
||||
uint8_t flags;
|
||||
}
|
||||
tr_pex;
|
||||
} tr_pex;
|
||||
|
||||
struct peer_atom;
|
||||
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_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 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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
/**
|
||||
|
@ -107,7 +119,11 @@ enum
|
|||
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);
|
||||
|
||||
void tr_peerMgrStartTorrent(tr_torrent* tor);
|
||||
|
|
|
@ -110,8 +110,7 @@ typedef enum
|
|||
ENCRYPTION_PREFERENCE_UNKNOWN,
|
||||
ENCRYPTION_PREFERENCE_YES,
|
||||
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* message;
|
||||
|
||||
evbuffer_add_printf(buf, "[%s] %s - %s [%s]: ",
|
||||
evbuffer_add_printf(
|
||||
buf,
|
||||
"[%s] %s - %s [%s]: ",
|
||||
tr_logGetTimeStr(timestr, sizeof(timestr)),
|
||||
tr_torrentName(msgs->torrent),
|
||||
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__); \
|
||||
} \
|
||||
} \
|
||||
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 */
|
||||
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
|
||||
{
|
||||
|
@ -1015,8 +1015,7 @@ static void parseLtepHandshake(tr_peerMsgs* msgs, uint32_t len, struct evbuffer*
|
|||
}
|
||||
|
||||
/* look for metainfo size (BEP 9) */
|
||||
if (tr_variantDictFindInt(&val, TR_KEY_metadata_size, &i) &&
|
||||
tr_torrentSetMetadataSizeHint(msgs->torrent, i))
|
||||
if (tr_variantDictFindInt(&val, TR_KEY_metadata_size, &i) && tr_torrentSetMetadataSizeHint(msgs->torrent, 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);
|
||||
}
|
||||
|
||||
if (tr_peerIoIsIncoming(msgs->io) &&
|
||||
tr_variantDictFindRaw(&val, TR_KEY_ipv4, &addr, &addr_len) &&
|
||||
addr_len == 4)
|
||||
if (tr_peerIoIsIncoming(msgs->io) && tr_variantDictFindRaw(&val, TR_KEY_ipv4, &addr, &addr_len) && addr_len == 4)
|
||||
{
|
||||
pex.addr.type = TR_AF_INET;
|
||||
memcpy(&pex.addr.addr.addr4, addr, 4);
|
||||
tr_peerMgrAddPex(msgs->torrent, TR_PEER_FROM_LTEP, &pex, seedProbability);
|
||||
}
|
||||
|
||||
if (tr_peerIoIsIncoming(msgs->io) &&
|
||||
tr_variantDictFindRaw(&val, TR_KEY_ipv6, &addr, &addr_len) &&
|
||||
addr_len == 16)
|
||||
if (tr_peerIoIsIncoming(msgs->io) && tr_variantDictFindRaw(&val, TR_KEY_ipv6, &addr, &addr_len) && addr_len == 16)
|
||||
{
|
||||
pex.addr.type = TR_AF_INET6;
|
||||
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);
|
||||
*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)));
|
||||
|
||||
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)
|
||||
{
|
||||
tr_removeElementFromArray(msgs->peerAskedFor, i, sizeof(struct peer_request),
|
||||
tr_removeElementFromArray(
|
||||
msgs->peerAskedFor,
|
||||
i,
|
||||
sizeof(struct peer_request),
|
||||
msgs->peer.pendingReqsToClient);
|
||||
--msgs->peer.pendingReqsToClient;
|
||||
break;
|
||||
|
@ -2104,8 +2108,13 @@ static size_t fillOutputBuffer(tr_peerMsgs* msgs, time_t now)
|
|||
evbuffer_add_uint32(out, req.offset);
|
||||
|
||||
evbuffer_reserve_space(out, req.length, iovec, 1);
|
||||
err = tr_cacheReadBlock(getSession(msgs)->cache, msgs->torrent, req.index, req.offset, req.length,
|
||||
iovec[0].iov_base) != 0;
|
||||
err = tr_cacheReadBlock(
|
||||
getSession(msgs)->cache,
|
||||
msgs->torrent,
|
||||
req.index,
|
||||
req.offset,
|
||||
req.length,
|
||||
iovec[0].iov_base) != 0;
|
||||
iovec[0].iov_len = req.length;
|
||||
evbuffer_commit_space(out, iovec, 1);
|
||||
|
||||
|
@ -2116,7 +2125,9 @@ static size_t fillOutputBuffer(tr_peerMsgs* msgs, time_t now)
|
|||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -2272,8 +2283,7 @@ typedef struct
|
|||
int addedCount;
|
||||
int droppedCount;
|
||||
int elementCount;
|
||||
}
|
||||
PexDiffs;
|
||||
} PexDiffs;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -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 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,
|
||||
size_t elementSize, tr_set_func in_a_cb, tr_set_func in_b_cb, tr_set_func in_both_cb, void* userData)
|
||||
static void tr_set_compare(
|
||||
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* b = vb;
|
||||
|
@ -2383,18 +2402,45 @@ static void sendPex(tr_peerMsgs* msgs)
|
|||
diffs.droppedCount = 0;
|
||||
diffs.elements = tr_new(tr_pex, newCount + msgs->pexCount);
|
||||
diffs.elementCount = 0;
|
||||
tr_set_compare(msgs->pex, msgs->pexCount, newPex, newCount, tr_pexCompare, sizeof(tr_pex), pexDroppedCb, pexAddedCb,
|
||||
pexElementCb, &diffs);
|
||||
tr_set_compare(
|
||||
msgs->pex,
|
||||
msgs->pexCount,
|
||||
newPex,
|
||||
newCount,
|
||||
tr_pexCompare,
|
||||
sizeof(tr_pex),
|
||||
pexDroppedCb,
|
||||
pexAddedCb,
|
||||
pexElementCb,
|
||||
&diffs);
|
||||
diffs6.added = tr_new(tr_pex, newCount6);
|
||||
diffs6.addedCount = 0;
|
||||
diffs6.dropped = tr_new(tr_pex, msgs->pexCount6);
|
||||
diffs6.droppedCount = 0;
|
||||
diffs6.elements = tr_new(tr_pex, newCount6 + msgs->pexCount6);
|
||||
diffs6.elementCount = 0;
|
||||
tr_set_compare(msgs->pex6, msgs->pexCount6, 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);
|
||||
tr_set_compare(
|
||||
msgs->pex6,
|
||||
msgs->pexCount6,
|
||||
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)
|
||||
{
|
||||
|
@ -2559,7 +2605,10 @@ static void pexPulse(evutil_socket_t fd, short what, void* vmsgs)
|
|||
**** 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 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,
|
||||
.is_transferring_pieces = peermsgs_is_transferring_pieces
|
||||
.is_transferring_pieces = peermsgs_is_transferring_pieces,
|
||||
};
|
||||
|
||||
/***
|
||||
|
|
|
@ -68,7 +68,11 @@ void tr_peerMsgsPulse(tr_peerMsgs* msgs);
|
|||
|
||||
void tr_peerMsgsCancel(tr_peerMsgs* msgs, tr_block_index_t block);
|
||||
|
||||
size_t tr_generateAllowedSet(tr_piece_index_t* setmePieces, size_t desiredSetSize, size_t pieceCount, 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);
|
||||
|
||||
/* @} */
|
||||
|
|
|
@ -326,8 +326,10 @@ static int64_t getquota(char const* device)
|
|||
int64_t spaceused;
|
||||
|
||||
#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)
|
||||
struct quotctl op;
|
||||
int fd = open(device, O_RDONLY);
|
||||
|
@ -341,55 +343,54 @@ static int64_t getquota(char const* device)
|
|||
op.uid = getuid();
|
||||
op.addr = (caddr_t)&dq;
|
||||
|
||||
if (ioctl(fd, Q_QUOTACTL, &op) == 0)
|
||||
if (ioctl(fd, Q_QUOTACTL, &op) != 0)
|
||||
{
|
||||
close(fd);
|
||||
#else
|
||||
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
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(__sun)
|
||||
close(fd);
|
||||
#else
|
||||
if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device, getuid(), (caddr_t)&dq) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* something went wrong */
|
||||
return -1;
|
||||
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
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -73,7 +73,7 @@ static bool tr_areThreadsEqual(tr_thread_id a, tr_thread_id b)
|
|||
/** @brief portability wrapper around OS-dependent threads */
|
||||
struct tr_thread
|
||||
{
|
||||
void (* func)(void*);
|
||||
void (*func)(void*);
|
||||
void* arg;
|
||||
tr_thread_id thread;
|
||||
|
||||
|
@ -113,7 +113,7 @@ static ThreadFuncReturnType ThreadFunc(void* _t)
|
|||
#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);
|
||||
|
||||
|
@ -529,11 +529,10 @@ char const* tr_getWebClientDir(tr_session const* session)
|
|||
/* Generally, Web interface should be stored in a Web subdir of
|
||||
* calling executable dir. */
|
||||
|
||||
static REFKNOWNFOLDERID known_folder_ids[] =
|
||||
{
|
||||
static REFKNOWNFOLDERID known_folder_ids[] = {
|
||||
&FOLDERID_LocalAppData,
|
||||
&FOLDERID_RoamingAppData,
|
||||
&FOLDERID_ProgramData
|
||||
&FOLDERID_ProgramData,
|
||||
};
|
||||
|
||||
for (size_t i = 0; s == NULL && i < TR_N_ELEMENTS(known_folder_ids); ++i)
|
||||
|
|
|
@ -50,7 +50,7 @@ char* tr_getSessionIdDir(void);
|
|||
typedef struct tr_thread tr_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'
|
||||
@param thread the thread being tested */
|
||||
|
|
|
@ -103,7 +103,10 @@ static void natPulse(tr_shared* s, bool do_check)
|
|||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,14 +28,16 @@ typedef struct tr_ptrArray
|
|||
void** items;
|
||||
int n_items;
|
||||
int n_alloc;
|
||||
}
|
||||
tr_ptrArray;
|
||||
} tr_ptrArray;
|
||||
|
||||
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;
|
||||
|
||||
|
|
|
@ -21,10 +21,12 @@ struct tr_key_struct
|
|||
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("activeTorrentCount"),
|
||||
Q("activity-date"),
|
||||
|
@ -412,7 +414,7 @@ static struct tr_key_struct const my_static[] =
|
|||
Q("watch-dir"),
|
||||
Q("watch-dir-enabled"),
|
||||
Q("webseeds"),
|
||||
Q("webseedsSendingToUs")
|
||||
Q("webseedsSendingToUs"),
|
||||
};
|
||||
|
||||
#undef Q
|
||||
|
|
|
@ -207,8 +207,13 @@ static uint64_t loadDND(tr_variant* dict, tr_torrent* tor)
|
|||
}
|
||||
else
|
||||
{
|
||||
tr_logAddTorDbg(tor, "Couldn't load DND flags. DND list (%p) has %zu" " children; torrent has %d files", (void*)list,
|
||||
tr_variantListSize(list), (int)n);
|
||||
tr_logAddTorDbg(
|
||||
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;
|
||||
|
@ -930,8 +935,8 @@ static uint64_t loadFromFile(tr_torrent* tor, uint64_t fieldsToLoad, bool* didRe
|
|||
fieldsLoaded |= TR_FR_TIME_DOWNLOADING;
|
||||
}
|
||||
|
||||
if ((fieldsToLoad & TR_FR_BANDWIDTH_PRIORITY) != 0 &&
|
||||
tr_variantDictFindInt(&top, TR_KEY_bandwidth_priority, &i) && tr_isPriority(i))
|
||||
if ((fieldsToLoad & TR_FR_BANDWIDTH_PRIORITY) != 0 && tr_variantDictFindInt(&top, TR_KEY_bandwidth_priority, &i) &&
|
||||
tr_isPriority(i))
|
||||
{
|
||||
tr_torrentSetPriority(tor, i);
|
||||
fieldsLoaded |= TR_FR_BANDWIDTH_PRIORITY;
|
||||
|
|
|
@ -272,9 +272,7 @@ static char const* mimetype_guess(char const* path)
|
|||
{
|
||||
char const* suffix;
|
||||
char const* mime_type;
|
||||
}
|
||||
const types[] =
|
||||
{
|
||||
} const types[] = {
|
||||
/* these are the ones we need for serving the web client's files... */
|
||||
{ "css", "text/css" },
|
||||
{ "gif", "image/gif" },
|
||||
|
@ -282,7 +280,7 @@ static char const* mimetype_guess(char const* path)
|
|||
{ "ico", "image/vnd.microsoft.icon" },
|
||||
{ "js", "application/javascript" },
|
||||
{ "png", "image/png" },
|
||||
{ "svg", "image/svg+xml" }
|
||||
{ "svg", "image/svg+xml" },
|
||||
};
|
||||
char const* dot = strrchr(path, '.');
|
||||
|
||||
|
@ -297,7 +295,10 @@ static char const* mimetype_guess(char const* path)
|
|||
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)
|
||||
{
|
||||
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))
|
||||
{
|
||||
send_simple_response(req, HTTP_NOTFOUND,
|
||||
send_simple_response(
|
||||
req,
|
||||
HTTP_NOTFOUND,
|
||||
"<p>Couldn't find Transmission's web interface files!</p>"
|
||||
"<p>Users: to tell Transmission where to look, "
|
||||
"set the TRANSMISSION_WEB_HOME environment "
|
||||
|
@ -467,7 +470,10 @@ static void handle_web_client(struct evhttp_request* req, struct tr_rpc_server*
|
|||
}
|
||||
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);
|
||||
serve_file(req, server, 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)
|
||||
{
|
||||
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));
|
||||
return;
|
||||
}
|
||||
|
@ -651,7 +660,9 @@ static void handle_request(struct evhttp_request* req, void* arg)
|
|||
|
||||
if (!isAddressAllowed(server, req->remote_host))
|
||||
{
|
||||
send_simple_response(req, 403,
|
||||
send_simple_response(
|
||||
req,
|
||||
403,
|
||||
"<p>Unauthorized IP Address.</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>"
|
||||
|
@ -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 ||
|
||||
!tr_ssha1_matches(server->password, pass)))
|
||||
if (server->isPasswordEnabled &&
|
||||
(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 "\"");
|
||||
if (server->isAntiBruteForceEnabled)
|
||||
|
@ -688,7 +699,8 @@ static void handle_request(struct evhttp_request* req, void* arg)
|
|||
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);
|
||||
send_simple_response(req, 401, 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> "
|
||||
"attacks.</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);
|
||||
send_simple_response(req, 409, tmp);
|
||||
tr_free(tmp);
|
||||
|
@ -839,7 +852,11 @@ static void startServer(void* vserver)
|
|||
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);
|
||||
}
|
||||
else
|
||||
|
@ -964,8 +981,10 @@ static void tr_rpcSetList(char const* whitelistStr, tr_list** list)
|
|||
|
||||
if (strcspn(token, "+-") < len)
|
||||
{
|
||||
tr_logAddNamedInfo(MY_NAME,
|
||||
"Adding address to whitelist: %s (And it has a '+' or '-'! Are you using an old ACL by mistake?)", token);
|
||||
tr_logAddNamedInfo(
|
||||
MY_NAME,
|
||||
"Adding address to whitelist: %s (And it has a '+' or '-'! Are you using an old ACL by mistake?)",
|
||||
token);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1302,7 +1321,11 @@ tr_rpc_server* tr_rpcInit(tr_session* session, tr_variant* settings)
|
|||
|
||||
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);
|
||||
tr_runInEventThread(session, startServer, s);
|
||||
|
||||
|
|
|
@ -53,8 +53,7 @@ typedef enum
|
|||
{
|
||||
TR_FORMAT_OBJECT = 0,
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
TR_UNUSED(args_out);
|
||||
|
@ -218,7 +220,10 @@ static char const* queueMoveTop(tr_session* session, tr_variant* args_in, tr_var
|
|||
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)
|
||||
{
|
||||
TR_UNUSED(args_out);
|
||||
|
@ -232,7 +237,10 @@ static char const* queueMoveUp(tr_session* session, tr_variant* args_in, tr_vari
|
|||
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)
|
||||
{
|
||||
TR_UNUSED(args_out);
|
||||
|
@ -246,7 +254,10 @@ static char const* queueMoveDown(tr_session* session, tr_variant* args_in, tr_va
|
|||
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)
|
||||
{
|
||||
TR_UNUSED(args_out);
|
||||
|
@ -268,7 +279,10 @@ static int compareTorrentByQueuePosition(void const* va, void const* vb)
|
|||
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)
|
||||
{
|
||||
TR_UNUSED(args_out);
|
||||
|
@ -296,7 +310,10 @@ static char const* torrentStart(tr_session* session, tr_variant* args_in, tr_var
|
|||
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)
|
||||
{
|
||||
TR_UNUSED(args_out);
|
||||
|
@ -324,7 +341,10 @@ static char const* torrentStartNow(tr_session* session, tr_variant* args_in, tr_
|
|||
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)
|
||||
{
|
||||
TR_UNUSED(args_out);
|
||||
|
@ -350,7 +370,10 @@ static char const* torrentStop(tr_session* session, tr_variant* args_in, tr_vari
|
|||
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)
|
||||
{
|
||||
TR_UNUSED(args_out);
|
||||
|
@ -385,7 +408,10 @@ static char const* torrentRemove(tr_session* session, tr_variant* args_in, tr_va
|
|||
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)
|
||||
{
|
||||
TR_UNUSED(args_out);
|
||||
|
@ -411,7 +437,10 @@ static char const* torrentReannounce(tr_session* session, tr_variant* args_in, t
|
|||
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)
|
||||
{
|
||||
TR_UNUSED(args_out);
|
||||
|
@ -572,7 +601,11 @@ static void addPeers(tr_torrent* tor, tr_variant* list)
|
|||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
tr_variant* child = format == TR_FORMAT_TABLE ?
|
||||
tr_variantListAdd(entry) :
|
||||
tr_variantDictAdd(entry, fields[i]);
|
||||
tr_variant* child = format == TR_FORMAT_TABLE ? tr_variantListAdd(entry) : tr_variantDictAdd(entry, 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)
|
||||
{
|
||||
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 id;
|
||||
|
||||
if (tr_variantDictFindInt(d, TR_KEY_date, &date) &&
|
||||
date >= now - interval &&
|
||||
if (tr_variantDictFindInt(d, TR_KEY_date, &date) && date >= now - interval &&
|
||||
tr_variantDictFindInt(d, TR_KEY_id, &id))
|
||||
{
|
||||
tr_variantListAddInt(removed_out, id);
|
||||
|
@ -1297,8 +1330,8 @@ static char const* replaceTrackers(tr_torrent* tor, tr_variant* urls)
|
|||
char const* newval;
|
||||
|
||||
if (tr_variantGetInt(tr_variantListChild(urls, i), &pos) &&
|
||||
tr_variantGetStr(tr_variantListChild(urls, i + 1), &newval, &len) &&
|
||||
tr_urlIsValidTracker(newval) && pos < n && pos >= 0)
|
||||
tr_variantGetStr(tr_variantListChild(urls, i + 1), &newval, &len) && tr_urlIsValidTracker(newval) && pos < n &&
|
||||
pos >= 0)
|
||||
{
|
||||
tr_free(trackers[pos].announce);
|
||||
trackers[pos].announce = tr_strndup(newval, len);
|
||||
|
@ -1379,7 +1412,10 @@ static char const* removeTrackers(tr_torrent* tor, tr_variant* ids)
|
|||
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)
|
||||
{
|
||||
TR_UNUSED(args_out);
|
||||
|
@ -1519,7 +1555,10 @@ static char const* torrentSet(tr_session* session, tr_variant* args_in, tr_varia
|
|||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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,
|
||||
size_t response_byte_count, void* user_data)
|
||||
static void portTested(
|
||||
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(did_connect);
|
||||
|
@ -1629,7 +1677,11 @@ static void portTested(tr_session* session, bool did_connect, bool did_timeout,
|
|||
|
||||
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));
|
||||
}
|
||||
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,
|
||||
size_t response_byte_count, void* user_data)
|
||||
static void gotNewBlocklist(
|
||||
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_timeout);
|
||||
|
@ -1671,7 +1729,11 @@ static void gotNewBlocklist(tr_session* session, bool did_connect, bool did_time
|
|||
|
||||
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));
|
||||
}
|
||||
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;
|
||||
err = inflate(&stream, Z_NO_FLUSH);
|
||||
|
||||
if ((stream.avail_out < buflen) &&
|
||||
(!tr_sys_file_write(fd, buf, buflen - stream.avail_out, NULL, &error)))
|
||||
if ((stream.avail_out < buflen) && (!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_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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
tr_quark const fields[] =
|
||||
{
|
||||
tr_quark const fields[] = {
|
||||
TR_KEY_id,
|
||||
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));
|
||||
|
@ -1831,8 +1894,14 @@ struct add_torrent_idle_data
|
|||
tr_ctor* ctor;
|
||||
};
|
||||
|
||||
static void gotMetadataFromURL(tr_session* session, bool did_connect, bool did_timeout, long response_code,
|
||||
void const* response, size_t response_byte_count, void* user_data)
|
||||
static void gotMetadataFromURL(
|
||||
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(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;
|
||||
|
||||
dbgmsg("torrentAdd: HTTP response code was %ld (%s); response length was %zu bytes", response_code,
|
||||
tr_webGetResponseStr(response_code), response_byte_count);
|
||||
dbgmsg(
|
||||
"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.. */
|
||||
{
|
||||
|
@ -1851,7 +1923,11 @@ static void gotMetadataFromURL(tr_session* session, bool did_connect, bool did_t
|
|||
else
|
||||
{
|
||||
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_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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
if (tr_variantDictFindStr(args_in, TR_KEY_download_dir, &download_dir, NULL) &&
|
||||
tr_sys_path_is_relative(download_dir))
|
||||
if (tr_variantDictFindStr(args_in, TR_KEY_download_dir, &download_dir, NULL) && tr_sys_path_is_relative(download_dir))
|
||||
{
|
||||
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)
|
||||
{
|
||||
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* incomplete_dir = NULL;
|
||||
|
||||
if (tr_variantDictFindStr(args_in, TR_KEY_download_dir, &download_dir, NULL) &&
|
||||
tr_sys_path_is_relative(download_dir))
|
||||
if (tr_variantDictFindStr(args_in, TR_KEY_download_dir, &download_dir, NULL) && tr_sys_path_is_relative(download_dir))
|
||||
{
|
||||
return "download directory path is not absolute";
|
||||
}
|
||||
|
||||
if (tr_variantDictFindStr(args_in, TR_KEY_incomplete_dir, &incomplete_dir, NULL) &&
|
||||
tr_sys_path_is_relative(incomplete_dir))
|
||||
if (tr_variantDictFindStr(args_in, TR_KEY_incomplete_dir, &incomplete_dir, NULL) && tr_sys_path_is_relative(incomplete_dir))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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
|
||||
{
|
||||
char const* name;
|
||||
bool immediate;
|
||||
handler func;
|
||||
}
|
||||
methods[] =
|
||||
{
|
||||
} methods[] = {
|
||||
{ "port-test", false, portTest },
|
||||
{ "blocklist-update", false, blocklistUpdate },
|
||||
{ "free-space", true, freeSpace },
|
||||
|
@ -2707,7 +2790,7 @@ methods[] =
|
|||
{ "queue-move-top", true, queueMoveTop },
|
||||
{ "queue-move-up", true, queueMoveUp },
|
||||
{ "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)
|
||||
|
@ -2717,7 +2800,10 @@ static void noop_response_callback(tr_session* session, tr_variant* response, vo
|
|||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
void tr_rpc_request_exec_uri(tr_session* session, void const* request_uri, size_t request_uri_len,
|
||||
tr_rpc_response_func callback, void* callback_user_data)
|
||||
void tr_rpc_request_exec_uri(
|
||||
tr_session* session,
|
||||
void const* request_uri,
|
||||
size_t request_uri_len,
|
||||
tr_rpc_response_func callback,
|
||||
void* callback_user_data)
|
||||
{
|
||||
char const* pch;
|
||||
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;
|
||||
tr_variant* parent = isArg ? args : ⊤
|
||||
|
||||
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));
|
||||
tr_free(key);
|
||||
}
|
||||
|
|
|
@ -18,15 +18,22 @@ TR_BEGIN_DECLS
|
|||
**** 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/ */
|
||||
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);
|
||||
|
||||
/* 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,
|
||||
tr_rpc_response_func callback, void* callback_user_data);
|
||||
void tr_rpc_request_exec_uri(
|
||||
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);
|
||||
|
||||
|
|
|
@ -180,7 +180,12 @@ static void accept_incoming_peer(evutil_socket_t fd, short what, void* vsession)
|
|||
{
|
||||
char addrstr[TR_ADDRSTRLEN];
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -986,8 +991,7 @@ static void sessionSetImpl(void* vdata)
|
|||
|
||||
free_incoming_peer_port(session);
|
||||
|
||||
if (!tr_variantDictFindStr(settings, TR_KEY_bind_address_ipv4, &str, NULL) ||
|
||||
!tr_address_from_string(&b.addr, str) ||
|
||||
if (!tr_variantDictFindStr(settings, TR_KEY_bind_address_ipv4, &str, NULL) || !tr_address_from_string(&b.addr, str) ||
|
||||
b.addr.type != TR_AF_INET)
|
||||
{
|
||||
b.addr = tr_inaddr_any;
|
||||
|
@ -996,8 +1000,7 @@ static void sessionSetImpl(void* vdata)
|
|||
b.socket = TR_BAD_SOCKET;
|
||||
session->bind_ipv4 = tr_memdup(&b, sizeof(struct tr_bindinfo));
|
||||
|
||||
if (!tr_variantDictFindStr(settings, TR_KEY_bind_address_ipv6, &str, NULL) ||
|
||||
!tr_address_from_string(&b.addr, str) ||
|
||||
if (!tr_variantDictFindStr(settings, TR_KEY_bind_address_ipv6, &str, NULL) || !tr_address_from_string(&b.addr, str) ||
|
||||
b.addr.type != TR_AF_INET6)
|
||||
{
|
||||
b.addr = tr_in6addr_any;
|
||||
|
@ -2064,7 +2067,10 @@ void tr_sessionClose(tr_session* session)
|
|||
|
||||
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);
|
||||
|
||||
/* close the session */
|
||||
|
@ -2081,10 +2087,14 @@ void tr_sessionClose(tr_session* session)
|
|||
* for a bit while they tell the router & tracker
|
||||
* that we're closing now */
|
||||
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,
|
||||
(void*)session->announcer, (size_t)time(NULL), (size_t)deadline);
|
||||
dbgmsg(
|
||||
"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);
|
||||
}
|
||||
|
||||
|
@ -2161,7 +2171,8 @@ static void sessionLoadTorrents(void* vdata)
|
|||
tr_sys_path_info info;
|
||||
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_open(dirname, NULL) : TR_BAD_SYS_DIR;
|
||||
tr_sys_dir_open(dirname, NULL) :
|
||||
TR_BAD_SYS_DIR;
|
||||
|
||||
if (odir != TR_BAD_SYS_DIR)
|
||||
{
|
||||
|
@ -2486,7 +2497,8 @@ static void loadBlocklists(tr_session* session)
|
|||
|
||||
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 */
|
||||
{
|
||||
char* old;
|
||||
|
@ -2673,7 +2685,8 @@ static void metainfoLookupInit(tr_session* session)
|
|||
tr_sys_path_info info;
|
||||
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_open(dirname, NULL) : TR_BAD_SYS_DIR;
|
||||
tr_sys_dir_open(dirname, NULL) :
|
||||
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)
|
||||
{
|
||||
tr_quickfindFirstK(candidates, num_candidates, sizeof(struct TorrentAndPosition), compareTorrentAndPositions,
|
||||
tr_quickfindFirstK(
|
||||
candidates,
|
||||
num_candidates,
|
||||
sizeof(struct TorrentAndPosition),
|
||||
compareTorrentAndPositions,
|
||||
num_wanted);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,16 +28,14 @@ typedef enum
|
|||
TR_NET_OK,
|
||||
TR_NET_ERROR,
|
||||
TR_NET_WAIT
|
||||
}
|
||||
tr_tristate_t;
|
||||
} tr_tristate_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TR_AUTO_SWITCH_UNUSED,
|
||||
TR_AUTO_SWITCH_ON,
|
||||
TR_AUTO_SWITCH_OFF,
|
||||
}
|
||||
tr_auto_switch_state_t;
|
||||
} tr_auto_switch_state_t;
|
||||
|
||||
enum
|
||||
{
|
||||
|
|
|
@ -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,
|
||||
.uploadedBytes = 0,
|
||||
.downloadedBytes = 0,
|
||||
.filesAdded = 0,
|
||||
.sessionCount = 0,
|
||||
.secondsActive = 0
|
||||
.secondsActive = 0,
|
||||
};
|
||||
|
||||
/** @brief Opaque, per-session data structure for bandwidth use statistics */
|
||||
|
|
|
@ -32,8 +32,7 @@ static void handle_sigchld(int i)
|
|||
{
|
||||
/* FIXME: Only check for our own PIDs */
|
||||
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 */
|
||||
}
|
||||
|
@ -95,8 +94,7 @@ static bool tr_spawn_async_in_parent(int pipe_fd, tr_error** error)
|
|||
do
|
||||
{
|
||||
count = read(pipe_fd, &child_errno, sizeof(child_errno));
|
||||
}
|
||||
while (count == -1 && errno == EINTR);
|
||||
} while (count == -1 && errno == EINTR);
|
||||
|
||||
close(pipe_fd);
|
||||
|
||||
|
|
|
@ -305,7 +305,10 @@ static void append_argument(char** arguments, char const* argument)
|
|||
static bool contains_batch_metachars(char const* text)
|
||||
{
|
||||
/* 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)
|
||||
|
@ -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;
|
||||
|
||||
STARTUPINFOW si =
|
||||
{
|
||||
STARTUPINFOW si = {
|
||||
.cb = sizeof(si),
|
||||
.dwFlags = STARTF_USESHOWWINDOW,
|
||||
.wShowWindow = SW_HIDE
|
||||
.wShowWindow = SW_HIDE,
|
||||
};
|
||||
|
||||
PROCESS_INFORMATION pi;
|
||||
|
||||
bool const ret = CreateProcessW(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);
|
||||
bool const ret = CreateProcessW(
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -154,8 +154,7 @@ bool tr_torrentIsPieceTransferAllowed(tr_torrent const* tor, tr_direction direct
|
|||
|
||||
bool allowed = true;
|
||||
|
||||
if (tr_torrentUsesSpeedLimit(tor, direction) &&
|
||||
tr_torrentGetSpeedLimit_Bps(tor, direction) <= 0)
|
||||
if (tr_torrentUsesSpeedLimit(tor, direction) && tr_torrentGetSpeedLimit_Bps(tor, direction) <= 0)
|
||||
{
|
||||
allowed = false;
|
||||
}
|
||||
|
@ -200,8 +199,7 @@ static int peerIdTTL(tr_torrent const* tor)
|
|||
|
||||
unsigned char const* tr_torrentGetPeerId(tr_torrent* tor)
|
||||
{
|
||||
bool const needs_new_peer_id =
|
||||
(*tor->peer_id == '\0') || // doesn't have one
|
||||
bool const needs_new_peer_id = (*tor->peer_id == '\0') || // doesn't have one
|
||||
(!tr_torrentIsPrivate(tor) && (peerIdTTL(tor) <= 0)); // has one but it's expired
|
||||
|
||||
if (needs_new_peer_id)
|
||||
|
@ -874,8 +872,11 @@ static bool setLocalErrorIfFilesDisappeared(tr_torrent* tor)
|
|||
if (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\". "
|
||||
"To re-download, remove the torrent and re-add it."));
|
||||
tr_torrentSetLocalError(
|
||||
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;
|
||||
|
@ -1030,7 +1031,11 @@ static void torrentInit(tr_torrent* tor, tr_ctor const* ctor)
|
|||
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)
|
||||
{
|
||||
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 cmd[] =
|
||||
{
|
||||
char* const cmd[] = {
|
||||
tr_strdup(script),
|
||||
NULL
|
||||
NULL,
|
||||
};
|
||||
|
||||
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_TIME_LOCALTIME=%s", ctime_str),
|
||||
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_NAME=%s", tr_torrentName(tor)),
|
||||
tr_strdup_printf("TR_TORRENT_LABELS=%s", labels),
|
||||
NULL
|
||||
NULL,
|
||||
};
|
||||
|
||||
tr_logAddTorInfo(tor, "Calling script \"%s\"", script);
|
||||
|
@ -2249,7 +2252,10 @@ void tr_torrentRecheckCompleteness(tr_torrent* tor)
|
|||
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -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_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)
|
||||
{
|
||||
uint64_t pos = block;
|
||||
|
@ -2614,8 +2627,13 @@ bool tr_torrentReqIsValid(tr_torrent const* tor, tr_piece_index_t index, uint32_
|
|||
|
||||
if (err != 0)
|
||||
{
|
||||
tr_logAddTorDbg(tor, "index %lu offset %lu length %lu err %d\n", (unsigned long)index, (unsigned long)offset,
|
||||
(unsigned long)length, err);
|
||||
tr_logAddTorDbg(
|
||||
tor,
|
||||
"index %lu offset %lu length %lu err %d\n",
|
||||
(unsigned long)index,
|
||||
(unsigned long)offset,
|
||||
(unsigned long)length,
|
||||
err);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (tr_cpFileIsComplete(&tor->completion, i) &&
|
||||
(tr_torrentGetFileMTime(tor, i) > inf->pieces[p].timeChecked))
|
||||
if (tr_cpFileIsComplete(&tor->completion, i) && (tr_torrentGetFileMTime(tor, i) > inf->pieces[p].timeChecked))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -2877,7 +2897,10 @@ bool tr_torrentSetAnnounceList(tr_torrent* tor, tr_tracker_info const* trackers_
|
|||
**/
|
||||
|
||||
#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_torrentSetActivityDate, tr_torrentSetDateActive)
|
||||
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 char const* files[] =
|
||||
{
|
||||
static char const* files[] = {
|
||||
".DS_Store",
|
||||
"desktop.ini",
|
||||
"Thumbs.db"
|
||||
"Thumbs.db",
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < TR_N_ELEMENTS(files); ++i)
|
||||
|
@ -3307,7 +3329,11 @@ static void setLocation(void* vdata)
|
|||
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)
|
||||
{
|
||||
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);
|
||||
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);
|
||||
size_t i;
|
||||
|
@ -3367,7 +3393,7 @@ char const* tr_torrentPrimaryMimeType(tr_torrent const* tor)
|
|||
|
||||
uint64_t max_len = 0;
|
||||
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))
|
||||
{
|
||||
|
@ -3441,9 +3467,7 @@ static void tr_torrentPieceCompleted(tr_torrent* tor, tr_piece_index_t pieceInde
|
|||
{
|
||||
tr_file const* file = &tor->info.files[i];
|
||||
|
||||
if ((file->firstPiece <= pieceIndex) &&
|
||||
(pieceIndex <= file->lastPiece) &&
|
||||
tr_cpFileIsComplete(&tor->completion, i))
|
||||
if ((file->firstPiece <= pieceIndex) && (pieceIndex <= file->lastPiece) && tr_cpFileIsComplete(&tor->completion, 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if ((old_pos < pos) &&
|
||||
(old_pos <= walk->queuePosition) &&
|
||||
(walk->queuePosition <= pos))
|
||||
if ((old_pos < pos) && (old_pos <= walk->queuePosition) && (walk->queuePosition <= pos))
|
||||
{
|
||||
walk->queuePosition--;
|
||||
walk->anyDate = now;
|
||||
}
|
||||
|
||||
if ((old_pos > pos) &&
|
||||
(pos <= walk->queuePosition) &&
|
||||
(walk->queuePosition < old_pos))
|
||||
if ((old_pos > pos) && (pos <= walk->queuePosition) && (walk->queuePosition < old_pos))
|
||||
{
|
||||
walk->queuePosition++;
|
||||
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_user_data = user_data;
|
||||
|
@ -4033,7 +4057,11 @@ static void torrentRenamePath(void* vdata)
|
|||
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)
|
||||
{
|
||||
struct rename_data* data;
|
||||
|
|
|
@ -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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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_WAIT,
|
||||
TR_VERIFY_NOW
|
||||
}
|
||||
tr_verify_state;
|
||||
} tr_verify_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* 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 isStopping;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue