Merge branch 'trac5348-misidentification-of-local-session'
This commit is contained in:
commit
efba03695a
|
@ -518,15 +518,16 @@
|
|||
|
||||
Method name: "session-set"
|
||||
Request arguments: one or more of 4.1's arguments, except: "blocklist-size",
|
||||
"config-dir", "rpc-version", "rpc-version-minimum", and
|
||||
"version"
|
||||
"config-dir", "rpc-version", "rpc-version-minimum",
|
||||
"version", and "session-id"
|
||||
Response arguments: none
|
||||
|
||||
4.1.2. Accessors
|
||||
|
||||
Method name: "session-get"
|
||||
Request arguments: none
|
||||
Response arguments: all of 4.1's arguments
|
||||
Request arguments: an optional "fields" array of keys (see 4.1)
|
||||
Response arguments: key/value pairs matching the request's "fields"
|
||||
argument if present, or all supported fields (see 4.1) otherwise.
|
||||
|
||||
4.2. Session Statistics
|
||||
|
||||
|
@ -743,7 +744,7 @@
|
|||
13 | 2.30 | yes | session-get | new arg "isUTP" to the "peers" list
|
||||
| | yes | torrent-add | new arg "cookies"
|
||||
| | NO | torrent-get | removed arg "peersKnown"
|
||||
------+---------+-----------+--------------------------+-------------------------------
|
||||
------+---------+-----------+----------------------+-------------------------------
|
||||
14 | 2.40 | NO | torrent-get | values of "status" field changed
|
||||
| | yes | torrent-get | new arg "queuePosition"
|
||||
| | yes | torrent-get | new arg "isStalled"
|
||||
|
@ -760,11 +761,14 @@
|
|||
| | yes | | new method "queue-move-down"
|
||||
| | yes | | new method "queue-move-bottom"
|
||||
| | yes | | new method "torrent-start-now"
|
||||
------+---------+-----------+--------------------------+-------------------------------
|
||||
------+---------+-----------+----------------------+-------------------------------
|
||||
15 | 2.80 | yes | torrent-get | new arg "etaIdle"
|
||||
| | yes | torrent-rename-path | new method
|
||||
| | yes | free-space | new method
|
||||
| | yes | torrent-add | new return return arg "torrent-duplicate"
|
||||
| | yes | torrent-add | new return arg "torrent-duplicate"
|
||||
------+---------+-----------+----------------------+-------------------------------
|
||||
16 | 3.00 | yes | session-get | new request arg "fields"
|
||||
| | yes | session-get | new arg "session-id"
|
||||
|
||||
5.1. Upcoming Breakage
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ set(${PROJECT_NAME}_SOURCES
|
|||
rpcimpl.c
|
||||
rpc-server.c
|
||||
session.c
|
||||
session-id.c
|
||||
stats.c
|
||||
torrent.c
|
||||
torrent-ctor.c
|
||||
|
@ -105,6 +106,7 @@ set(${PROJECT_NAME}_PUBLIC_HEADERS
|
|||
makemeta.h
|
||||
quark.h
|
||||
rpcimpl.h
|
||||
session-id.h
|
||||
tr-getopt.h
|
||||
transmission.h
|
||||
utils.h
|
||||
|
|
|
@ -6,21 +6,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#if defined (HAVE_MKDTEMP) && (!defined (_XOPEN_SOURCE) || _XOPEN_SOURCE < 700)
|
||||
#undef _XOPEN_SOURCE
|
||||
#define _XOPEN_SOURCE 700
|
||||
#elif (defined (HAVE_POSIX_FADVISE) || defined (HAVE_POSIX_FALLOCATE)) && (!defined (_XOPEN_SOURCE) || _XOPEN_SOURCE < 600)
|
||||
#undef _XOPEN_SOURCE
|
||||
#define _XOPEN_SOURCE 600
|
||||
#endif
|
||||
|
||||
#if (defined (HAVE_FALLOCATE64) || defined (HAVE_CANONICALIZE_FILE_NAME)) && !defined (_GNU_SOURCE)
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#if defined (__APPLE__) && !defined (_DARWIN_C_SOURCE)
|
||||
#define _DARWIN_C_SOURCE
|
||||
#endif
|
||||
#undef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <assert.h>
|
||||
#include <dirent.h>
|
||||
|
@ -31,8 +18,9 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h> /* mmap (), munmap () */
|
||||
#include <sys/types.h>
|
||||
#include <sys/file.h> /* flock () */
|
||||
#include <sys/mman.h> /* mmap (), munmap () */
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h> /* lseek (), write (), ftruncate (), pread (), pwrite (), pathconf (), etc */
|
||||
|
||||
|
@ -920,6 +908,35 @@ tr_sys_file_unmap (const void * address,
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
tr_sys_file_lock (tr_sys_file_t handle,
|
||||
int operation,
|
||||
tr_error ** error)
|
||||
{
|
||||
bool ret;
|
||||
int native_operation = 0;
|
||||
|
||||
assert (handle != TR_BAD_SYS_FILE);
|
||||
assert ((operation & ~(TR_SYS_FILE_LOCK_SH | TR_SYS_FILE_LOCK_EX | TR_SYS_FILE_LOCK_NB | TR_SYS_FILE_LOCK_UN)) == 0);
|
||||
assert (!!(operation & TR_SYS_FILE_LOCK_SH) + !!(operation & TR_SYS_FILE_LOCK_EX) + !!(operation & TR_SYS_FILE_LOCK_UN) == 1);
|
||||
|
||||
if ((operation & TR_SYS_FILE_LOCK_SH) != 0)
|
||||
native_operation |= LOCK_SH;
|
||||
if ((operation & TR_SYS_FILE_LOCK_EX) != 0)
|
||||
native_operation |= LOCK_EX;
|
||||
if ((operation & TR_SYS_FILE_LOCK_NB) != 0)
|
||||
native_operation |= LOCK_NB;
|
||||
if ((operation & TR_SYS_FILE_LOCK_UN) != 0)
|
||||
native_operation |= LOCK_UN;
|
||||
|
||||
ret = flock (handle, native_operation) != -1;
|
||||
|
||||
if (!ret)
|
||||
set_system_error (error, errno);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *
|
||||
tr_sys_dir_get_current (tr_error ** error)
|
||||
{
|
||||
|
|
|
@ -1144,6 +1144,40 @@ tr_sys_file_unmap (const void * address,
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
tr_sys_file_lock (tr_sys_file_t handle,
|
||||
int operation,
|
||||
tr_error ** error)
|
||||
{
|
||||
bool ret;
|
||||
OVERLAPPED overlapped = { .Pointer = 0, .hEvent = NULL };
|
||||
|
||||
assert (handle != TR_BAD_SYS_FILE);
|
||||
assert ((operation & ~(TR_SYS_FILE_LOCK_SH | TR_SYS_FILE_LOCK_EX | TR_SYS_FILE_LOCK_NB | TR_SYS_FILE_LOCK_UN)) == 0);
|
||||
assert (!!(operation & TR_SYS_FILE_LOCK_SH) + !!(operation & TR_SYS_FILE_LOCK_EX) + !!(operation & TR_SYS_FILE_LOCK_UN) == 1);
|
||||
|
||||
if ((operation & TR_SYS_FILE_LOCK_UN) == 0)
|
||||
{
|
||||
DWORD native_flags = 0;
|
||||
|
||||
if ((operation & TR_SYS_FILE_LOCK_EX) != 0)
|
||||
native_flags |= LOCKFILE_EXCLUSIVE_LOCK;
|
||||
if ((operation & TR_SYS_FILE_LOCK_NB) != 0)
|
||||
native_flags |= LOCKFILE_FAIL_IMMEDIATELY;
|
||||
|
||||
ret = LockFileEx (handle, native_flags, 0, MAXDWORD, MAXDWORD, &overlapped) != FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = UnlockFileEx (handle, 0, MAXDWORD, MAXDWORD, &overlapped) != FALSE;
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
set_system_error (error, GetLastError ());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *
|
||||
tr_sys_dir_get_current (tr_error ** error)
|
||||
{
|
||||
|
|
|
@ -76,6 +76,15 @@ typedef enum
|
|||
}
|
||||
tr_seek_origin_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TR_SYS_FILE_LOCK_SH = 1 << 0,
|
||||
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;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TR_SYS_PATH_NO_FOLLOW = 1 << 0
|
||||
|
@ -524,6 +533,23 @@ bool tr_sys_file_unmap (const void * address,
|
|||
uint64_t size,
|
||||
struct tr_error ** error);
|
||||
|
||||
/**
|
||||
* @brief Portability wrapper for `flock ()`.
|
||||
*
|
||||
* Don't try to upgrade or downgrade the lock unless you know what you are
|
||||
* doing, as behavior varies a bit between platforms.
|
||||
*
|
||||
* @param[in] handle Valid file descriptor.
|
||||
* @param[in] operation Combination of @ref tr_sys_file_lock_flags_t values.
|
||||
* @param[out] error Pointer to error object. Optional, pass `NULL` if you
|
||||
* are not interested in error details.
|
||||
*
|
||||
* @return `True` on success, `false` otherwise (with `error` set accordingly).
|
||||
*/
|
||||
bool tr_sys_file_lock (tr_sys_file_t handle,
|
||||
int operation,
|
||||
struct tr_error ** error);
|
||||
|
||||
/* File-related wrappers (utility) */
|
||||
|
||||
/**
|
||||
|
|
|
@ -224,13 +224,12 @@ tr_lockUnlock (tr_lock * l)
|
|||
#ifdef _WIN32
|
||||
|
||||
static char *
|
||||
win32_get_known_folder (REFKNOWNFOLDERID folder_id)
|
||||
win32_get_known_folder_ex (REFKNOWNFOLDERID folder_id, DWORD flags)
|
||||
{
|
||||
char * ret = NULL;
|
||||
PWSTR path;
|
||||
|
||||
if (SHGetKnownFolderPath (folder_id, KF_FLAG_DONT_UNEXPAND | KF_FLAG_DONT_VERIFY,
|
||||
NULL, &path) == S_OK)
|
||||
if (SHGetKnownFolderPath (folder_id, flags | KF_FLAG_DONT_UNEXPAND, NULL, &path) == S_OK)
|
||||
{
|
||||
ret = tr_win32_native_to_utf8 (path, -1);
|
||||
CoTaskMemFree (path);
|
||||
|
@ -239,6 +238,12 @@ win32_get_known_folder (REFKNOWNFOLDERID folder_id)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static char *
|
||||
win32_get_known_folder (REFKNOWNFOLDERID folder_id)
|
||||
{
|
||||
return win32_get_known_folder_ex (folder_id, KF_FLAG_DONT_VERIFY);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static const char *
|
||||
|
@ -586,3 +591,21 @@ tr_getWebClientDir (const tr_session * session UNUSED)
|
|||
|
||||
return s;
|
||||
}
|
||||
|
||||
char *
|
||||
tr_getSessionIdDir (void)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
|
||||
return tr_strdup ("/tmp");
|
||||
|
||||
#else
|
||||
|
||||
char * program_data_dir = win32_get_known_folder_ex (&FOLDERID_ProgramData, KF_FLAG_CREATE);
|
||||
char * result = tr_buildPath (program_data_dir, "Transmission", NULL);
|
||||
tr_free (program_data_dir);
|
||||
tr_sys_dir_create (result, 0, 0, NULL);
|
||||
return result;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -37,6 +37,9 @@ const char * tr_getTorrentDir (const tr_session *);
|
|||
/** @brief return the directory where the Web Client's web ui files are kept */
|
||||
const char * tr_getWebClientDir (const tr_session *);
|
||||
|
||||
/** @brief return the directory where session id lock files are stored */
|
||||
char * tr_getSessionIdDir (void);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
|
|
|
@ -315,6 +315,7 @@ static const struct tr_key_struct my_static[] =
|
|||
{ "seederCount", 11 },
|
||||
{ "seeding-time-seconds", 20 },
|
||||
{ "session-count", 13 },
|
||||
{ "session-id", 10 },
|
||||
{ "sessionCount", 12 },
|
||||
{ "show-backup-trackers", 20 },
|
||||
{ "show-extra-peer-details", 23 },
|
||||
|
|
|
@ -316,6 +316,7 @@ enum
|
|||
TR_KEY_seederCount,
|
||||
TR_KEY_seeding_time_seconds,
|
||||
TR_KEY_session_count,
|
||||
TR_KEY_session_id,
|
||||
TR_KEY_sessionCount,
|
||||
TR_KEY_show_backup_trackers,
|
||||
TR_KEY_show_extra_peer_details,
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "rpcimpl.h"
|
||||
#include "rpc-server.h"
|
||||
#include "session.h"
|
||||
#include "session-id.h"
|
||||
#include "trevent.h"
|
||||
#include "utils.h"
|
||||
#include "variant.h"
|
||||
|
@ -63,9 +64,6 @@ struct tr_rpc_server
|
|||
char * whitelistStr;
|
||||
tr_list * whitelist;
|
||||
|
||||
char * sessionId;
|
||||
time_t sessionIdExpiresAt;
|
||||
|
||||
bool isStreamInitialized;
|
||||
z_stream stream;
|
||||
};
|
||||
|
@ -81,33 +79,12 @@ struct tr_rpc_server
|
|||
****
|
||||
***/
|
||||
|
||||
static char*
|
||||
static const char *
|
||||
get_current_session_id (struct tr_rpc_server * server)
|
||||
{
|
||||
const time_t now = tr_time ();
|
||||
|
||||
if (!server->sessionId || (now >= server->sessionIdExpiresAt))
|
||||
{
|
||||
int i;
|
||||
const int n = 48;
|
||||
const char * pool = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
const size_t pool_size = strlen (pool);
|
||||
unsigned char * buf = tr_new (unsigned char, n+1);
|
||||
|
||||
tr_rand_buffer (buf, n);
|
||||
for (i=0; i<n; ++i)
|
||||
buf[i] = pool[ buf[i] % pool_size ];
|
||||
buf[n] = '\0';
|
||||
|
||||
tr_free (server->sessionId);
|
||||
server->sessionId = (char*) buf;
|
||||
server->sessionIdExpiresAt = now + (60*60); /* expire in an hour */
|
||||
}
|
||||
|
||||
return server->sessionId;
|
||||
return tr_session_id_get_current (server->session->session_id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
***
|
||||
**/
|
||||
|
@ -1004,7 +981,6 @@ closeServer (void * vserver)
|
|||
if (s->isStreamInitialized)
|
||||
deflateEnd (&s->stream);
|
||||
tr_free (s->url);
|
||||
tr_free (s->sessionId);
|
||||
tr_free (s->whitelistStr);
|
||||
tr_free (s->username);
|
||||
tr_free (s->password);
|
||||
|
|
|
@ -26,13 +26,14 @@
|
|||
#include "platform-quota.h" /* tr_device_info_get_free_space() */
|
||||
#include "rpcimpl.h"
|
||||
#include "session.h"
|
||||
#include "session-id.h"
|
||||
#include "torrent.h"
|
||||
#include "utils.h"
|
||||
#include "variant.h"
|
||||
#include "version.h"
|
||||
#include "web.h"
|
||||
|
||||
#define RPC_VERSION 15
|
||||
#define RPC_VERSION 16
|
||||
#define RPC_VERSION_MIN 1
|
||||
|
||||
#define RECENTLY_ACTIVE_SECONDS 60
|
||||
|
@ -2039,71 +2040,268 @@ sessionStats (tr_session * session,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
addSessionField (tr_session * s,
|
||||
tr_variant * d,
|
||||
tr_quark key)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case TR_KEY_alt_speed_up:
|
||||
tr_variantDictAddInt (d, key, tr_sessionGetAltSpeed_KBps (s, TR_UP));
|
||||
break;
|
||||
|
||||
case TR_KEY_alt_speed_down:
|
||||
tr_variantDictAddInt (d, key, tr_sessionGetAltSpeed_KBps (s, TR_DOWN));
|
||||
break;
|
||||
|
||||
case TR_KEY_alt_speed_enabled:
|
||||
tr_variantDictAddBool (d, key, tr_sessionUsesAltSpeed (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_alt_speed_time_begin:
|
||||
tr_variantDictAddInt (d, key, tr_sessionGetAltSpeedBegin (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_alt_speed_time_end:
|
||||
tr_variantDictAddInt (d, key,tr_sessionGetAltSpeedEnd (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_alt_speed_time_day:
|
||||
tr_variantDictAddInt (d, key,tr_sessionGetAltSpeedDay (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_alt_speed_time_enabled:
|
||||
tr_variantDictAddBool (d, key, tr_sessionUsesAltSpeedTime (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_blocklist_enabled:
|
||||
tr_variantDictAddBool (d, key, tr_blocklistIsEnabled (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_blocklist_url:
|
||||
tr_variantDictAddStr (d, key, tr_blocklistGetURL (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_cache_size_mb:
|
||||
tr_variantDictAddInt (d, key, tr_sessionGetCacheLimit_MB (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_blocklist_size:
|
||||
tr_variantDictAddInt (d, key, tr_blocklistGetRuleCount (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_config_dir:
|
||||
tr_variantDictAddStr (d, key, tr_sessionGetConfigDir (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_download_dir:
|
||||
tr_variantDictAddStr (d, key, tr_sessionGetDownloadDir (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_download_dir_free_space:
|
||||
tr_variantDictAddInt (d, key, tr_device_info_get_free_space (s->downloadDir));
|
||||
break;
|
||||
|
||||
case TR_KEY_download_queue_enabled:
|
||||
tr_variantDictAddBool (d, key, tr_sessionGetQueueEnabled (s, TR_DOWN));
|
||||
break;
|
||||
|
||||
case TR_KEY_download_queue_size:
|
||||
tr_variantDictAddInt (d, key, tr_sessionGetQueueSize (s, TR_DOWN));
|
||||
break;
|
||||
|
||||
case TR_KEY_peer_limit_global:
|
||||
tr_variantDictAddInt (d, key, tr_sessionGetPeerLimit (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_peer_limit_per_torrent:
|
||||
tr_variantDictAddInt (d, key, tr_sessionGetPeerLimitPerTorrent (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_incomplete_dir:
|
||||
tr_variantDictAddStr (d, key, tr_sessionGetIncompleteDir (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_incomplete_dir_enabled:
|
||||
tr_variantDictAddBool (d, key, tr_sessionIsIncompleteDirEnabled (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_pex_enabled:
|
||||
tr_variantDictAddBool (d, key, tr_sessionIsPexEnabled (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_utp_enabled:
|
||||
tr_variantDictAddBool (d, key, tr_sessionIsUTPEnabled (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_dht_enabled:
|
||||
tr_variantDictAddBool (d, key, tr_sessionIsDHTEnabled (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_lpd_enabled:
|
||||
tr_variantDictAddBool (d, key, tr_sessionIsLPDEnabled (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_peer_port:
|
||||
tr_variantDictAddInt (d, key, tr_sessionGetPeerPort (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_peer_port_random_on_start:
|
||||
tr_variantDictAddBool (d, key, tr_sessionGetPeerPortRandomOnStart (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_port_forwarding_enabled:
|
||||
tr_variantDictAddBool (d, key, tr_sessionIsPortForwardingEnabled (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_rename_partial_files:
|
||||
tr_variantDictAddBool (d, key, tr_sessionIsIncompleteFileNamingEnabled (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_rpc_version:
|
||||
tr_variantDictAddInt (d, key, RPC_VERSION);
|
||||
break;
|
||||
|
||||
case TR_KEY_rpc_version_minimum:
|
||||
tr_variantDictAddInt (d, key, RPC_VERSION_MIN);
|
||||
break;
|
||||
|
||||
case TR_KEY_seedRatioLimit:
|
||||
tr_variantDictAddReal (d, key, tr_sessionGetRatioLimit (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_seedRatioLimited:
|
||||
tr_variantDictAddBool (d, key, tr_sessionIsRatioLimited (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_idle_seeding_limit:
|
||||
tr_variantDictAddInt (d, key, tr_sessionGetIdleLimit (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_idle_seeding_limit_enabled:
|
||||
tr_variantDictAddBool (d, key, tr_sessionIsIdleLimited (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_seed_queue_enabled:
|
||||
tr_variantDictAddBool (d, key, tr_sessionGetQueueEnabled (s, TR_UP));
|
||||
break;
|
||||
|
||||
case TR_KEY_seed_queue_size:
|
||||
tr_variantDictAddInt (d, key, tr_sessionGetQueueSize (s, TR_UP));
|
||||
break;
|
||||
|
||||
case TR_KEY_start_added_torrents:
|
||||
tr_variantDictAddBool (d, key, !tr_sessionGetPaused (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_trash_original_torrent_files:
|
||||
tr_variantDictAddBool (d, key, tr_sessionGetDeleteSource (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_speed_limit_up:
|
||||
tr_variantDictAddInt (d, key, tr_sessionGetSpeedLimit_KBps (s, TR_UP));
|
||||
break;
|
||||
|
||||
case TR_KEY_speed_limit_up_enabled:
|
||||
tr_variantDictAddBool (d, key, tr_sessionIsSpeedLimited (s, TR_UP));
|
||||
break;
|
||||
|
||||
case TR_KEY_speed_limit_down:
|
||||
tr_variantDictAddInt (d, key, tr_sessionGetSpeedLimit_KBps (s, TR_DOWN));
|
||||
break;
|
||||
|
||||
case TR_KEY_speed_limit_down_enabled:
|
||||
tr_variantDictAddBool (d, key, tr_sessionIsSpeedLimited (s, TR_DOWN));
|
||||
break;
|
||||
|
||||
case TR_KEY_script_torrent_done_filename:
|
||||
tr_variantDictAddStr (d, key, tr_sessionGetTorrentDoneScript (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_script_torrent_done_enabled:
|
||||
tr_variantDictAddBool (d, key, tr_sessionIsTorrentDoneScriptEnabled (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_queue_stalled_enabled:
|
||||
tr_variantDictAddBool (d, key, tr_sessionGetQueueStalledEnabled (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_queue_stalled_minutes:
|
||||
tr_variantDictAddInt (d, key, tr_sessionGetQueueStalledMinutes (s));
|
||||
break;
|
||||
|
||||
case TR_KEY_units:
|
||||
tr_formatter_get_units (tr_variantDictAddDict (d, key, 0));
|
||||
break;
|
||||
|
||||
case TR_KEY_version:
|
||||
tr_variantDictAddStr (d, key, LONG_VERSION_STRING);
|
||||
break;
|
||||
|
||||
case TR_KEY_encryption:
|
||||
{
|
||||
const char * str;
|
||||
|
||||
switch (tr_sessionGetEncryption (s))
|
||||
{
|
||||
case TR_CLEAR_PREFERRED:
|
||||
str = "tolerated";
|
||||
break;
|
||||
|
||||
case TR_ENCRYPTION_REQUIRED:
|
||||
str = "required";
|
||||
break;
|
||||
|
||||
default:
|
||||
str = "preferred";
|
||||
break;
|
||||
}
|
||||
|
||||
tr_variantDictAddStr (d, key, str);
|
||||
break;
|
||||
}
|
||||
|
||||
case TR_KEY_session_id:
|
||||
tr_variantDictAddStr (d, key, tr_session_id_get_current (s->session_id));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const char*
|
||||
sessionGet (tr_session * s,
|
||||
tr_variant * args_in UNUSED,
|
||||
tr_variant * args_in,
|
||||
tr_variant * args_out,
|
||||
struct tr_rpc_idle_data * idle_data UNUSED)
|
||||
{
|
||||
const char * str;
|
||||
tr_variant * d = args_out;
|
||||
tr_variant * fields;
|
||||
|
||||
assert (idle_data == NULL);
|
||||
tr_variantDictAddInt (d, TR_KEY_alt_speed_up, tr_sessionGetAltSpeed_KBps (s,TR_UP));
|
||||
tr_variantDictAddInt (d, TR_KEY_alt_speed_down, tr_sessionGetAltSpeed_KBps (s,TR_DOWN));
|
||||
tr_variantDictAddBool (d, TR_KEY_alt_speed_enabled, tr_sessionUsesAltSpeed (s));
|
||||
tr_variantDictAddInt (d, TR_KEY_alt_speed_time_begin, tr_sessionGetAltSpeedBegin (s));
|
||||
tr_variantDictAddInt (d, TR_KEY_alt_speed_time_end,tr_sessionGetAltSpeedEnd (s));
|
||||
tr_variantDictAddInt (d, TR_KEY_alt_speed_time_day,tr_sessionGetAltSpeedDay (s));
|
||||
tr_variantDictAddBool (d, TR_KEY_alt_speed_time_enabled, tr_sessionUsesAltSpeedTime (s));
|
||||
tr_variantDictAddBool (d, TR_KEY_blocklist_enabled, tr_blocklistIsEnabled (s));
|
||||
tr_variantDictAddStr (d, TR_KEY_blocklist_url, tr_blocklistGetURL (s));
|
||||
tr_variantDictAddInt (d, TR_KEY_cache_size_mb, tr_sessionGetCacheLimit_MB (s));
|
||||
tr_variantDictAddInt (d, TR_KEY_blocklist_size, tr_blocklistGetRuleCount (s));
|
||||
tr_variantDictAddStr (d, TR_KEY_config_dir, tr_sessionGetConfigDir (s));
|
||||
tr_variantDictAddStr (d, TR_KEY_download_dir, tr_sessionGetDownloadDir (s));
|
||||
tr_variantDictAddInt (d, TR_KEY_download_dir_free_space, tr_device_info_get_free_space (s->downloadDir));
|
||||
tr_variantDictAddBool (d, TR_KEY_download_queue_enabled, tr_sessionGetQueueEnabled (s, TR_DOWN));
|
||||
tr_variantDictAddInt (d, TR_KEY_download_queue_size, tr_sessionGetQueueSize (s, TR_DOWN));
|
||||
tr_variantDictAddInt (d, TR_KEY_peer_limit_global, tr_sessionGetPeerLimit (s));
|
||||
tr_variantDictAddInt (d, TR_KEY_peer_limit_per_torrent, tr_sessionGetPeerLimitPerTorrent (s));
|
||||
tr_variantDictAddStr (d, TR_KEY_incomplete_dir, tr_sessionGetIncompleteDir (s));
|
||||
tr_variantDictAddBool (d, TR_KEY_incomplete_dir_enabled, tr_sessionIsIncompleteDirEnabled (s));
|
||||
tr_variantDictAddBool (d, TR_KEY_pex_enabled, tr_sessionIsPexEnabled (s));
|
||||
tr_variantDictAddBool (d, TR_KEY_utp_enabled, tr_sessionIsUTPEnabled (s));
|
||||
tr_variantDictAddBool (d, TR_KEY_dht_enabled, tr_sessionIsDHTEnabled (s));
|
||||
tr_variantDictAddBool (d, TR_KEY_lpd_enabled, tr_sessionIsLPDEnabled (s));
|
||||
tr_variantDictAddInt (d, TR_KEY_peer_port, tr_sessionGetPeerPort (s));
|
||||
tr_variantDictAddBool (d, TR_KEY_peer_port_random_on_start, tr_sessionGetPeerPortRandomOnStart (s));
|
||||
tr_variantDictAddBool (d, TR_KEY_port_forwarding_enabled, tr_sessionIsPortForwardingEnabled (s));
|
||||
tr_variantDictAddBool (d, TR_KEY_rename_partial_files, tr_sessionIsIncompleteFileNamingEnabled (s));
|
||||
tr_variantDictAddInt (d, TR_KEY_rpc_version, RPC_VERSION);
|
||||
tr_variantDictAddInt (d, TR_KEY_rpc_version_minimum, RPC_VERSION_MIN);
|
||||
tr_variantDictAddReal (d, TR_KEY_seedRatioLimit, tr_sessionGetRatioLimit (s));
|
||||
tr_variantDictAddBool (d, TR_KEY_seedRatioLimited, tr_sessionIsRatioLimited (s));
|
||||
tr_variantDictAddInt (d, TR_KEY_idle_seeding_limit, tr_sessionGetIdleLimit (s));
|
||||
tr_variantDictAddBool (d, TR_KEY_idle_seeding_limit_enabled, tr_sessionIsIdleLimited (s));
|
||||
tr_variantDictAddBool (d, TR_KEY_seed_queue_enabled, tr_sessionGetQueueEnabled (s, TR_UP));
|
||||
tr_variantDictAddInt (d, TR_KEY_seed_queue_size, tr_sessionGetQueueSize (s, TR_UP));
|
||||
tr_variantDictAddBool (d, TR_KEY_start_added_torrents, !tr_sessionGetPaused (s));
|
||||
tr_variantDictAddBool (d, TR_KEY_trash_original_torrent_files, tr_sessionGetDeleteSource (s));
|
||||
tr_variantDictAddInt (d, TR_KEY_speed_limit_up, tr_sessionGetSpeedLimit_KBps (s, TR_UP));
|
||||
tr_variantDictAddBool (d, TR_KEY_speed_limit_up_enabled, tr_sessionIsSpeedLimited (s, TR_UP));
|
||||
tr_variantDictAddInt (d, TR_KEY_speed_limit_down, tr_sessionGetSpeedLimit_KBps (s, TR_DOWN));
|
||||
tr_variantDictAddBool (d, TR_KEY_speed_limit_down_enabled, tr_sessionIsSpeedLimited (s, TR_DOWN));
|
||||
tr_variantDictAddStr (d, TR_KEY_script_torrent_done_filename, tr_sessionGetTorrentDoneScript (s));
|
||||
tr_variantDictAddBool (d, TR_KEY_script_torrent_done_enabled, tr_sessionIsTorrentDoneScriptEnabled (s));
|
||||
tr_variantDictAddBool (d, TR_KEY_queue_stalled_enabled, tr_sessionGetQueueStalledEnabled (s));
|
||||
tr_variantDictAddInt (d, TR_KEY_queue_stalled_minutes, tr_sessionGetQueueStalledMinutes (s));
|
||||
tr_formatter_get_units (tr_variantDictAddDict (d, TR_KEY_units, 0));
|
||||
tr_variantDictAddStr (d, TR_KEY_version, LONG_VERSION_STRING);
|
||||
switch (tr_sessionGetEncryption (s))
|
||||
|
||||
if (tr_variantDictFindList (args_in, TR_KEY_fields, &fields))
|
||||
{
|
||||
case TR_CLEAR_PREFERRED: str = "tolerated"; break;
|
||||
case TR_ENCRYPTION_REQUIRED: str = "required"; break;
|
||||
default: str = "preferred"; break;
|
||||
const size_t field_count = tr_variantListSize (fields);
|
||||
|
||||
for (size_t i = 0; i < field_count; ++i)
|
||||
{
|
||||
const char * field_name;
|
||||
size_t field_name_len;
|
||||
tr_quark field_id;
|
||||
|
||||
if (!tr_variantGetStr (tr_variantListChild (fields, i), &field_name, &field_name_len))
|
||||
continue;
|
||||
|
||||
if (!tr_quark_lookup (field_name, field_name_len, &field_id))
|
||||
continue;
|
||||
|
||||
addSessionField (s, args_out, field_id);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (tr_quark field_id = TR_KEY_NONE + 1; field_id < TR_N_KEYS; ++field_id)
|
||||
addSessionField (s, args_out, field_id);
|
||||
}
|
||||
tr_variantDictAddStr (d, TR_KEY_encryption, str);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,210 @@
|
|||
/*
|
||||
* This file Copyright (C) 2016 Mnemosyne LLC
|
||||
*
|
||||
* It may be used under the GNU GPL versions 2 or 3
|
||||
* or any future license endorsed by Mnemosyne LLC.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#include "transmission.h"
|
||||
#include "crypto-utils.h"
|
||||
#include "error.h"
|
||||
#include "error-types.h"
|
||||
#include "file.h"
|
||||
#include "log.h"
|
||||
#include "platform.h"
|
||||
#include "session-id.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define SESSION_ID_SIZE 48
|
||||
#define SESSION_ID_DURATION_SEC (60 * 60) /* expire in an hour */
|
||||
|
||||
struct tr_session_id
|
||||
{
|
||||
char * current_value;
|
||||
char * previous_value;
|
||||
tr_sys_file_t current_lock_file;
|
||||
tr_sys_file_t previous_lock_file;
|
||||
time_t expires_at;
|
||||
};
|
||||
|
||||
static char *
|
||||
generate_new_session_id_value (void)
|
||||
{
|
||||
const char pool[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
const size_t pool_size = sizeof (pool) - 1;
|
||||
|
||||
char * buf = tr_new (char, SESSION_ID_SIZE + 1);
|
||||
|
||||
tr_rand_buffer (buf, SESSION_ID_SIZE);
|
||||
for (size_t i = 0; i < SESSION_ID_SIZE; ++i)
|
||||
buf[i] = pool[(unsigned char) buf[i] % pool_size];
|
||||
buf[SESSION_ID_SIZE] = '\0';
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static char *
|
||||
get_session_id_lock_file_path (const char * session_id)
|
||||
{
|
||||
char * lock_file_dir = tr_getSessionIdDir ();
|
||||
char * lock_file_path = tr_strdup_printf ("%s/tr_session_id_%s", lock_file_dir, session_id);
|
||||
tr_free (lock_file_dir);
|
||||
return lock_file_path;
|
||||
}
|
||||
|
||||
static tr_sys_file_t
|
||||
create_session_id_lock_file (const char * session_id)
|
||||
{
|
||||
if (session_id == NULL)
|
||||
return TR_BAD_SYS_FILE;
|
||||
|
||||
char * lock_file_path = get_session_id_lock_file_path (session_id);
|
||||
tr_sys_file_t lock_file;
|
||||
tr_error * error = NULL;
|
||||
|
||||
lock_file = tr_sys_file_open (lock_file_path, TR_SYS_FILE_READ | TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE, 0600, &error);
|
||||
|
||||
if (lock_file != TR_BAD_SYS_FILE)
|
||||
{
|
||||
if (tr_sys_file_lock (lock_file, TR_SYS_FILE_LOCK_EX | TR_SYS_FILE_LOCK_NB, &error))
|
||||
{
|
||||
#ifndef _WIN32
|
||||
/* Allow any user to lock the file regardless of current umask */
|
||||
fchmod (lock_file, 0644);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
tr_sys_file_close (lock_file, NULL);
|
||||
lock_file = TR_BAD_SYS_FILE;
|
||||
}
|
||||
}
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
tr_logAddError ("Unable to create session lock file (%d): %s", error->code, error->message);
|
||||
tr_error_free (error);
|
||||
}
|
||||
|
||||
tr_free (lock_file_path);
|
||||
return lock_file;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_session_id_lock_file (tr_sys_file_t lock_file,
|
||||
const char * session_id)
|
||||
{
|
||||
if (lock_file != TR_BAD_SYS_FILE)
|
||||
tr_sys_file_close (lock_file, NULL);
|
||||
|
||||
if (session_id != NULL)
|
||||
{
|
||||
char * lock_file_path = get_session_id_lock_file_path (session_id);
|
||||
tr_sys_path_remove (lock_file_path, NULL);
|
||||
tr_free (lock_file_path);
|
||||
}
|
||||
}
|
||||
|
||||
tr_session_id_t
|
||||
tr_session_id_new (void)
|
||||
{
|
||||
const tr_session_id_t session_id = tr_new0 (struct tr_session_id, 1);
|
||||
|
||||
session_id->current_lock_file = TR_BAD_SYS_FILE;
|
||||
session_id->previous_lock_file = TR_BAD_SYS_FILE;
|
||||
|
||||
return session_id;
|
||||
}
|
||||
|
||||
void
|
||||
tr_session_id_free (tr_session_id_t session_id)
|
||||
{
|
||||
if (session_id == NULL)
|
||||
return;
|
||||
|
||||
destroy_session_id_lock_file (session_id->previous_lock_file, session_id->previous_value);
|
||||
destroy_session_id_lock_file (session_id->current_lock_file, session_id->current_value);
|
||||
|
||||
tr_free (session_id->previous_value);
|
||||
tr_free (session_id->current_value);
|
||||
|
||||
tr_free (session_id);
|
||||
}
|
||||
|
||||
const char *
|
||||
tr_session_id_get_current (tr_session_id_t session_id)
|
||||
{
|
||||
const time_t now = tr_time ();
|
||||
|
||||
if (session_id->current_value == NULL || now >= session_id->expires_at)
|
||||
{
|
||||
destroy_session_id_lock_file (session_id->previous_lock_file, session_id->previous_value);
|
||||
tr_free (session_id->previous_value);
|
||||
|
||||
session_id->previous_value = session_id->current_value;
|
||||
session_id->current_value = generate_new_session_id_value ();
|
||||
|
||||
session_id->previous_lock_file = session_id->current_lock_file;
|
||||
session_id->current_lock_file = create_session_id_lock_file (session_id->current_value);
|
||||
|
||||
session_id->expires_at = now + SESSION_ID_DURATION_SEC;
|
||||
}
|
||||
|
||||
return session_id->current_value;
|
||||
}
|
||||
|
||||
bool
|
||||
tr_session_id_is_local (const char * session_id)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if (session_id != NULL)
|
||||
{
|
||||
char * lock_file_path = get_session_id_lock_file_path (session_id);
|
||||
tr_sys_file_t lock_file;
|
||||
tr_error * error = NULL;
|
||||
|
||||
lock_file = tr_sys_file_open (lock_file_path, TR_SYS_FILE_READ, 0, &error);
|
||||
|
||||
if (lock_file == TR_BAD_SYS_FILE)
|
||||
{
|
||||
if (TR_ERROR_IS_ENOENT (error->code))
|
||||
tr_error_clear (&error);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!tr_sys_file_lock (lock_file, TR_SYS_FILE_LOCK_SH | TR_SYS_FILE_LOCK_NB, &error))
|
||||
{
|
||||
#ifndef _WIN32
|
||||
if (error->code == EWOULDBLOCK)
|
||||
#else
|
||||
if (error->code == ERROR_LOCK_VIOLATION)
|
||||
#endif
|
||||
{
|
||||
ret = true;
|
||||
tr_error_clear (&error);
|
||||
}
|
||||
}
|
||||
|
||||
tr_sys_file_close (lock_file, NULL);
|
||||
}
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
tr_logAddError ("Unable to open session lock file (%d): %s", error->code, error->message);
|
||||
tr_error_free (error);
|
||||
}
|
||||
|
||||
tr_free (lock_file_path);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* This file Copyright (C) 2016 Mnemosyne LLC
|
||||
*
|
||||
* It may be used under the GNU GPL versions 2 or 3
|
||||
* or any future license endorsed by Mnemosyne LLC.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct tr_session_id * tr_session_id_t;
|
||||
|
||||
/**
|
||||
* Create new session identifier object.
|
||||
*
|
||||
* @return New session identifier object.
|
||||
*/
|
||||
tr_session_id_t tr_session_id_new (void);
|
||||
|
||||
/**
|
||||
* Free session identifier object.
|
||||
*
|
||||
* @param[in] session_id Session identifier object.
|
||||
*/
|
||||
void tr_session_id_free (tr_session_id_t session_id);
|
||||
|
||||
/**
|
||||
* Get current session identifier as string.
|
||||
*
|
||||
* @param[in] session_id Session identifier object.
|
||||
*
|
||||
* @return String representation of current session identifier.
|
||||
*/
|
||||
const char * tr_session_id_get_current (tr_session_id_t session_id);
|
||||
|
||||
/**
|
||||
* Check if session ID corresponds to session running on the same machine as
|
||||
* the caller.
|
||||
*
|
||||
* This is useful for various behavior alterations, such as transforming
|
||||
* relative paths to absolute before passing through RPC, or presenting
|
||||
* different UI for local and remote sessions.
|
||||
*
|
||||
* @param[in] session_id String representation of session identifier object.
|
||||
*
|
||||
* @return `True` if session is valid and local, `false` otherwise.
|
||||
*/
|
||||
bool tr_session_id_is_local (const char * session_id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -11,6 +11,7 @@
|
|||
#include <string.h>
|
||||
#include "transmission.h"
|
||||
#include "session.h"
|
||||
#include "session-id.h"
|
||||
#include "utils.h"
|
||||
#include "version.h"
|
||||
|
||||
|
@ -45,4 +46,96 @@ testPeerId (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
MAIN_SINGLE_TEST (testPeerId)
|
||||
static int
|
||||
test_session_id (void)
|
||||
{
|
||||
tr_session_id_t session_id;
|
||||
const char * session_id_str_1 = NULL;
|
||||
const char * session_id_str_2 = NULL;
|
||||
const char * session_id_str_3 = NULL;
|
||||
|
||||
check (!tr_session_id_is_local (NULL));
|
||||
check (!tr_session_id_is_local (""));
|
||||
check (!tr_session_id_is_local ("test"));
|
||||
|
||||
session_id = tr_session_id_new ();
|
||||
check (session_id != NULL);
|
||||
|
||||
tr_timeUpdate (0);
|
||||
|
||||
session_id_str_1 = tr_session_id_get_current (session_id);
|
||||
check (session_id_str_1 != NULL);
|
||||
check (strlen (session_id_str_1) == 48);
|
||||
session_id_str_1 = tr_strdup (session_id_str_1);
|
||||
|
||||
check (tr_session_id_is_local (session_id_str_1));
|
||||
|
||||
tr_timeUpdate (60 * 60 - 1);
|
||||
|
||||
check (tr_session_id_is_local (session_id_str_1));
|
||||
|
||||
session_id_str_2 = tr_session_id_get_current (session_id);
|
||||
check (session_id_str_2 != NULL);
|
||||
check (strlen (session_id_str_2) == 48);
|
||||
check (strcmp (session_id_str_2, session_id_str_1) == 0);
|
||||
|
||||
tr_timeUpdate (60 * 60);
|
||||
|
||||
check (tr_session_id_is_local (session_id_str_1));
|
||||
|
||||
session_id_str_2 = tr_session_id_get_current (session_id);
|
||||
check (session_id_str_2 != NULL);
|
||||
check (strlen (session_id_str_2) == 48);
|
||||
check (strcmp (session_id_str_2, session_id_str_1) != 0);
|
||||
session_id_str_2 = tr_strdup (session_id_str_2);
|
||||
|
||||
check (tr_session_id_is_local (session_id_str_2));
|
||||
check (tr_session_id_is_local (session_id_str_1));
|
||||
|
||||
tr_timeUpdate (60 * 60 * 2);
|
||||
|
||||
check (tr_session_id_is_local (session_id_str_2));
|
||||
check (tr_session_id_is_local (session_id_str_1));
|
||||
|
||||
session_id_str_3 = tr_session_id_get_current (session_id);
|
||||
check (session_id_str_3 != NULL);
|
||||
check (strlen (session_id_str_3) == 48);
|
||||
check (strcmp (session_id_str_3, session_id_str_2) != 0);
|
||||
check (strcmp (session_id_str_3, session_id_str_1) != 0);
|
||||
session_id_str_3 = tr_strdup (session_id_str_3);
|
||||
|
||||
check (tr_session_id_is_local (session_id_str_3));
|
||||
check (tr_session_id_is_local (session_id_str_2));
|
||||
check (!tr_session_id_is_local (session_id_str_1));
|
||||
|
||||
tr_timeUpdate (60 * 60 * 10);
|
||||
|
||||
check (tr_session_id_is_local (session_id_str_3));
|
||||
check (tr_session_id_is_local (session_id_str_2));
|
||||
check (!tr_session_id_is_local (session_id_str_1));
|
||||
|
||||
check (!tr_session_id_is_local (NULL));
|
||||
check (!tr_session_id_is_local (""));
|
||||
check (!tr_session_id_is_local ("test"));
|
||||
|
||||
tr_session_id_free (session_id);
|
||||
|
||||
check (!tr_session_id_is_local (session_id_str_3));
|
||||
check (!tr_session_id_is_local (session_id_str_2));
|
||||
check (!tr_session_id_is_local (session_id_str_1));
|
||||
|
||||
tr_free (session_id_str_3);
|
||||
tr_free (session_id_str_2);
|
||||
tr_free (session_id_str_1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
const testFunc tests[] = { testPeerId,
|
||||
test_session_id };
|
||||
|
||||
return runTests (tests, NUM_TESTS (tests));
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "port-forwarding.h"
|
||||
#include "rpc-server.h"
|
||||
#include "session.h"
|
||||
#include "session-id.h"
|
||||
#include "stats.h"
|
||||
#include "torrent.h"
|
||||
#include "tr-dht.h" /* tr_dhtUpkeep () */
|
||||
|
@ -599,6 +600,7 @@ tr_sessionInit (const char * configDir,
|
|||
session->lock = tr_lockNew ();
|
||||
session->cache = tr_cacheNew (1024*1024*2);
|
||||
session->magicNumber = SESSION_MAGIC_NUMBER;
|
||||
session->session_id = tr_session_id_new ();
|
||||
tr_bandwidthConstruct (&session->bandwidth, session, NULL);
|
||||
tr_variantInitList (&session->removedTorrents, 0);
|
||||
|
||||
|
@ -1955,6 +1957,7 @@ tr_sessionClose (tr_session * session)
|
|||
tr_variantFree (&session->removedTorrents);
|
||||
tr_bandwidthDestruct (&session->bandwidth);
|
||||
tr_bitfieldDestruct (&session->turtle.minutes);
|
||||
tr_session_id_free (session->session_id);
|
||||
tr_lockFree (session->lock);
|
||||
if (session->metainfoLookup)
|
||||
{
|
||||
|
|
|
@ -196,6 +196,7 @@ struct tr_session
|
|||
|
||||
struct tr_web * web;
|
||||
|
||||
struct tr_session_id * session_id;
|
||||
struct tr_rpc_server * rpcServer;
|
||||
tr_rpc_func rpc_func;
|
||||
void * rpc_func_user_data;
|
||||
|
|
Loading…
Reference in New Issue