From: Charles Kerr Date: Wed, 25 Mar 2009 19:18:00 +0000 (+0000) Subject: (trunk) #1950: Add off-peak hour bandwidth limiting to libtransmission, rpc X-Git-Tag: 1.60~218 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b1fc4ed8c45f1b95f547e6c28f2bdeaf64c3cc4e;p=transmission (trunk) #1950: Add off-peak hour bandwidth limiting to libtransmission, rpc --- diff --git a/daemon/remote.c b/daemon/remote.c index 74b02ed27..69960179b 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -416,7 +416,7 @@ readargs( int argc, case 'p': tr_bencDictAddStr( &top, "method", "session-set" ); - tr_bencDictAddInt( args, "port", numarg( optarg ) ); + tr_bencDictAddInt( args, TR_PREFS_KEY_PEER_PORT, numarg( optarg ) ); break; case 'r': @@ -469,19 +469,19 @@ readargs( int argc, case 'w': { char * path = absolutify( optarg ); tr_bencDictAddStr( &top, "method", "session-set" ); - tr_bencDictAddStr( args, "download-dir", path ); + tr_bencDictAddStr( args, TR_PREFS_KEY_DOWNLOAD_DIR, path ); tr_free( path ); break; } case 'x': tr_bencDictAddStr( &top, "method", "session-set" ); - tr_bencDictAddInt( args, "pex-allowed", 1 ); + tr_bencDictAddInt( args, TR_PREFS_KEY_PEX_ENABLED, 1 ); break; case 'X': tr_bencDictAddStr( &top, "method", "session-set" ); - tr_bencDictAddInt( args, "pex-allowed", 0 ); + tr_bencDictAddInt( args, TR_PREFS_KEY_PEX_ENABLED, 0 ); break; case 900: @@ -504,17 +504,17 @@ readargs( int argc, case 910: tr_bencDictAddStr( &top, "method", "session-set" ); - tr_bencDictAddStr( args, "encryption", "required" ); + tr_bencDictAddStr( args, TR_PREFS_KEY_ENCRYPTION, "required" ); break; case 911: tr_bencDictAddStr( &top, "method", "session-set" ); - tr_bencDictAddStr( args, "encryption", "preferred" ); + tr_bencDictAddStr( args, TR_PREFS_KEY_ENCRYPTION, "preferred" ); break; case 912: tr_bencDictAddStr( &top, "method", "session-set" ); - tr_bencDictAddStr( args, "encryption", "tolerated" ); + tr_bencDictAddStr( args, TR_PREFS_KEY_ENCRYPTION, "tolerated" ); break; case 920: @@ -530,7 +530,7 @@ readargs( int argc, case 931: tr_bencDictAddStr( &top, "method", "session-set" ); - tr_bencDictAddInt( args, "peer-limit", atoi(optarg) ); + tr_bencDictAddInt( args, TR_PREFS_KEY_PEER_LIMIT_GLOBAL, atoi(optarg) ); break; case 940: @@ -811,7 +811,7 @@ printSession( tr_benc * top ) printf( "\n" ); printf( "LIMITS\n" ); - if( tr_bencDictFindInt( args, "peer-limit", &i ) ) + if( tr_bencDictFindInt( args, TR_PREFS_KEY_PEER_LIMIT_GLOBAL, &i ) ) printf( " Peer limit: %" PRId64 "\n", i ); if( tr_bencDictFindInt( args, "speed-limit-down-enabled", &i ) ) printf( " Downloadlimit enabled: %s\n", ( i ? "Yes" : "No" ) ); diff --git a/doc/rpc-spec.txt b/doc/rpc-spec.txt index f76aecfef..2284c7bf8 100644 --- a/doc/rpc-spec.txt +++ b/doc/rpc-spec.txt @@ -336,11 +336,18 @@ string | value type & description ---------------------------+------------------------------------------------- + "alt-speed-limit-enabled" | 'boolean' true means enabled + "alt-speed-limit-up" | number max global upload speed (in K/s) + "alt-speed-limit-down" | number max global download speed (in K/s) + "alt-speed-limit-begin" | number minutes after midnight. (ex: 60 means starting at 1 am) + "alt-speed-limit-end" | number minutes after midnight. (ex: 300 means ending at 5 am) + "blocklist-enabled" | 'boolean' true means enabled "encryption" | string "required", "preferred", "tolerated" "download-dir" | string default path to download torrents - "peer-limit" | number maximum global number of peers - "pex-allowed" | 'boolean' true means allow pex in public torrents - "port" | number port number + "peer-limit-global" | number maximum global number of peers + "peer-limit-per-torrent" | number maximum global number of peers + "pex-enabled" | 'boolean' true means allow pex in public torrents + "peer-port" | number port number "port-forwarding-enabled" | 'boolean' true means enabled "speed-limit-down" | number max global download speed (in K/s) "speed-limit-down-enabled" | 'boolean' true means enabled @@ -435,10 +442,20 @@ | | yes | torrent-get | new arg "speed-limit-up-enabled" | | yes | torrent-get | new arg "speed-limit-up-global-enabled" | | yes | torrent-get | new ids option "recently-active" + | | yes | session-get | new arg "alt-speed-limit-enabled" + | | yes | session-get | new arg "alt-speed-limit-up" + | | yes | session-get | new arg "alt-speed-limit-down" + | | yes | session-get | new arg "alt-speed-limit-begin" + | | yes | session-get | new arg "alt-speed-limit-end" + | | yes | session-get | new arg "blocklist-enabled" + | | yes | session-get | new arg "peer-limit-per-torrent" | | NO | torrent-get | removed arg "downloadLimit" | | NO | torrent-get | removed arg "downloadLimitMode" | | NO | torrent-get | removed arg "uploadLimit" | | NO | torrent-get | removed arg "uploadLimitMode" + | | NO | session-get | renamed "pex-allowed" to "pex-enabled" + | | NO | session-get | renamed "port" to "peer-port" + | | NO | session-get | renamed "peer-limit" to "peer-limit-global" ------+---------+-----------+----------------+------------------------------- diff --git a/gtk/conf.c b/gtk/conf.c index d1067aed3..88b1f48b4 100644 --- a/gtk/conf.c +++ b/gtk/conf.c @@ -178,12 +178,6 @@ tr_prefs_init_defaults( tr_benc * d ) tr_bencDictAddInt( d, PREF_KEY_SHOW_DESKTOP_NOTIFICATION, TRUE ); tr_bencDictAddStr( d, PREF_KEY_STATUSBAR_STATS, "total-ratio" ); - tr_bencDictAddInt( d, PREF_KEY_SCHED_LIMIT_ENABLED, FALSE ); - tr_bencDictAddInt( d, PREF_KEY_SCHED_BEGIN, 60 * 23 ); /* 11pm */ - tr_bencDictAddInt( d, PREF_KEY_SCHED_END, 60 * 7 ); /* 7am */ - tr_bencDictAddInt( d, PREF_KEY_SCHED_DL_LIMIT, 200 ); /* 2x the other limit */ - tr_bencDictAddInt( d, PREF_KEY_SCHED_UL_LIMIT, 100 ); /* 2x the other limit */ - tr_bencDictAddInt( d, PREF_KEY_OPTIONS_PROMPT, TRUE ); tr_bencDictAddInt( d, PREF_KEY_MAIN_WINDOW_HEIGHT, 500 ); diff --git a/gtk/main.c b/gtk/main.c index 6a610d8b2..e47394917 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -459,96 +459,6 @@ main( int argc, return 0; } -static gboolean -updateScheduledLimits( gpointer data ) -{ - tr_session * tr = data; - static gboolean last_state = FALSE; - gboolean in_sched_state = FALSE; - - if( !pref_flag_get( PREF_KEY_SCHED_LIMIT_ENABLED ) ) - { - in_sched_state = FALSE; - } - else - { - const int begin_time = pref_int_get( PREF_KEY_SCHED_BEGIN ); - const int end_time = pref_int_get( PREF_KEY_SCHED_END ); - time_t t; - struct tm *tm; - int cur_time; - - time( &t ); - tm = localtime ( &t ); - cur_time = ( tm->tm_hour * 60 ) + tm->tm_min; - - if( end_time >= begin_time ) - { - if( ( cur_time >= begin_time ) && ( cur_time <= end_time ) ) - in_sched_state = TRUE; - } - else - { - if( ( cur_time >= begin_time ) || ( cur_time <= end_time ) ) - in_sched_state = TRUE; - } - } - - if( last_state != in_sched_state ) - { - if( in_sched_state ) - { - int limit; - - tr_inf ( _( "Beginning to use scheduled bandwidth limits" ) ); - - tr_sessionSetSpeedLimitEnabled( tr, TR_DOWN, TRUE ); - limit = pref_int_get( PREF_KEY_SCHED_DL_LIMIT ); - tr_sessionSetSpeedLimit( tr, TR_DOWN, limit ); - tr_sessionSetSpeedLimitEnabled( tr, TR_UP, TRUE ); - limit = pref_int_get( PREF_KEY_SCHED_UL_LIMIT ); - tr_sessionSetSpeedLimit( tr, TR_UP, limit ); - } - else - { - gboolean b; - int limit; - - tr_inf ( _( "Ending use of scheduled bandwidth limits" ) ); - - b = pref_flag_get( TR_PREFS_KEY_DSPEED_ENABLED ); - tr_sessionSetSpeedLimitEnabled( tr, TR_DOWN, b ); - limit = pref_int_get( TR_PREFS_KEY_DSPEED ); - tr_sessionSetSpeedLimit( tr, TR_DOWN, limit ); - b = pref_flag_get( TR_PREFS_KEY_USPEED_ENABLED ); - tr_sessionSetSpeedLimitEnabled( tr, TR_UP, b ); - limit = pref_int_get( TR_PREFS_KEY_USPEED ); - tr_sessionSetSpeedLimit( tr, TR_UP, limit ); - } - - last_state = in_sched_state; - } - else if( in_sched_state ) - { - static int old_dl_limit = 0, old_ul_limit = 0; - int dl_limit = pref_int_get( PREF_KEY_SCHED_DL_LIMIT ); - int ul_limit = pref_int_get( PREF_KEY_SCHED_UL_LIMIT ); - - if( ( dl_limit != old_dl_limit ) || ( ul_limit != old_ul_limit ) ) - { - tr_sessionSetSpeedLimitEnabled( tr, TR_DOWN, TRUE ); - tr_sessionSetSpeedLimit( tr, TR_DOWN, dl_limit ); - tr_sessionSetSpeedLimitEnabled( tr, TR_UP, TRUE ); - tr_sessionSetSpeedLimit( tr, TR_UP, ul_limit ); - - old_dl_limit = dl_limit; - old_ul_limit = ul_limit; - } - } - - return TRUE; -} - static void appsetup( TrWindow * wind, GSList * torrentFiles, @@ -601,10 +511,6 @@ appsetup( TrWindow * wind, cbdata->timer = gtr_timeout_add_seconds( REFRESH_INTERVAL_SECONDS, updatemodel, cbdata ); updatemodel( cbdata ); - /* start scheduled rate timer */ - updateScheduledLimits ( tr_core_session( cbdata->core ) ); - gtr_timeout_add_seconds( 60, updateScheduledLimits, tr_core_session( cbdata->core ) ); - /* either show the window or iconify it */ if( !isIconified ) gtk_widget_show( GTK_WIDGET( wind ) ); @@ -1087,10 +993,6 @@ prefschanged( TrCore * core UNUSED, const double limit = pref_double_get( key ); tr_sessionSetRatioLimit( tr, limit ); } - else if( !strncmp( key, "sched-", 6 ) ) - { - updateScheduledLimits( tr ); - } else if( !strcmp( key, TR_PREFS_KEY_PORT_FORWARDING ) ) { tr_sessionSetPortForwardingEnabled( tr, pref_flag_get( key ) ); @@ -1170,6 +1072,31 @@ prefschanged( TrCore * core UNUSED, const char * s = pref_string_get( key ); tr_sessionSetProxyPassword( tr, s ); } + else if( !strcmp( key, TR_PREFS_KEY_ALT_LIMIT_ENABLED ) ) + { + const gboolean enabled = pref_flag_get( key ); + tr_sessionSetAltSpeedLimitEnabled( tr, enabled ); + } + else if( !strcmp( key, TR_PREFS_KEY_ALT_BEGIN ) ) + { + const int minutes = pref_int_get( key ); + tr_sessionSetAltSpeedLimitBegin( tr, minutes ); + } + else if( !strcmp( key, TR_PREFS_KEY_ALT_DL_LIMIT ) ) + { + const int speed = pref_int_get( key ); + tr_sessionSetAltSpeedLimit( tr, TR_DOWN, speed ); + } + else if( !strcmp( key, TR_PREFS_KEY_ALT_END ) ) + { + const int minutes = pref_int_get( key ); + tr_sessionSetAltSpeedLimitEnd( tr, minutes ); + } + else if( !strcmp( key, TR_PREFS_KEY_ALT_UL_LIMIT ) ) + { + const int speed = pref_int_get( key ); + tr_sessionSetAltSpeedLimit( tr, TR_UP, speed ); + } } static gboolean diff --git a/gtk/tr-prefs.c b/gtk/tr-prefs.c index 05ae8552e..758fc53c9 100644 --- a/gtk/tr-prefs.c +++ b/gtk/tr-prefs.c @@ -990,8 +990,7 @@ static void refreshSchedSensitivity( struct BandwidthPage * p ) { GSList * l; - const gboolean sched_enabled = pref_flag_get( - PREF_KEY_SCHED_LIMIT_ENABLED ); + const gboolean sched_enabled = pref_flag_get( TR_PREFS_KEY_ALT_LIMIT_ENABLED ); for( l = p->sched_widgets; l != NULL; l = l->next ) gtk_widget_set_sensitive( GTK_WIDGET( l->data ), sched_enabled ); @@ -1111,27 +1110,27 @@ bandwidthPage( GObject * core ) hig_workarea_add_section_title( t, &row, _( "Scheduled Limits" ) ); h = gtk_hbox_new( FALSE, 0 ); - w2 = new_time_combo( core, PREF_KEY_SCHED_BEGIN ); + w2 = new_time_combo( core, TR_PREFS_KEY_ALT_BEGIN ); page->sched_widgets = g_slist_append( page->sched_widgets, w2 ); gtk_box_pack_start( GTK_BOX( h ), w2, FALSE, FALSE, 0 ); w2 = gtk_label_new ( _( " and " ) ); page->sched_widgets = g_slist_append( page->sched_widgets, w2 ); gtk_box_pack_start( GTK_BOX( h ), w2, FALSE, FALSE, 0 ); - w2 = new_time_combo( core, PREF_KEY_SCHED_END ); + w2 = new_time_combo( core, TR_PREFS_KEY_ALT_END ); page->sched_widgets = g_slist_append( page->sched_widgets, w2 ); gtk_box_pack_start( GTK_BOX( h ), w2, FALSE, FALSE, 0 ); s = _( "_Limit bandwidth between" ); - w = new_check_button( s, PREF_KEY_SCHED_LIMIT_ENABLED, core ); + w = new_check_button( s, TR_PREFS_KEY_ALT_LIMIT_ENABLED, core ); g_signal_connect( w, "toggled", G_CALLBACK( onSchedToggled ), page ); hig_workarea_add_row_w( t, &row, w, h, NULL ); - w = new_spin_button( PREF_KEY_SCHED_DL_LIMIT, core, 0, INT_MAX, 5 ); + w = new_spin_button( TR_PREFS_KEY_ALT_DL_LIMIT, core, 0, INT_MAX, 5 ); page->sched_widgets = g_slist_append( page->sched_widgets, w ); l = hig_workarea_add_row( t, &row, _( "Limit d_ownload speed (KB/s):" ), w, NULL ); page->sched_widgets = g_slist_append( page->sched_widgets, l ); - w = new_spin_button( PREF_KEY_SCHED_UL_LIMIT, core, 0, INT_MAX, 5 ); + w = new_spin_button( TR_PREFS_KEY_ALT_UL_LIMIT, core, 0, INT_MAX, 5 ); page->sched_widgets = g_slist_append( page->sched_widgets, w ); l = hig_workarea_add_row( t, &row, _( "Limit u_pload speed (KB/s):" ), w, NULL ); page->sched_widgets = g_slist_append( page->sched_widgets, l ); diff --git a/gtk/tr-prefs.h b/gtk/tr-prefs.h index ff0aa6f6c..6f79e5f34 100644 --- a/gtk/tr-prefs.h +++ b/gtk/tr-prefs.h @@ -21,11 +21,6 @@ GtkWidget * tr_prefs_dialog_new( GObject * core, /* if you add a key here, you /must/ add its * default in tr_prefs_init_defaults( void ) */ -#define PREF_KEY_SCHED_LIMIT_ENABLED "sched-limit-enabled" -#define PREF_KEY_SCHED_BEGIN "sched-begin" -#define PREF_KEY_SCHED_END "sched-end" -#define PREF_KEY_SCHED_DL_LIMIT "sched-download-limit" -#define PREF_KEY_SCHED_UL_LIMIT "sched-upload-limit" #define PREF_KEY_OPTIONS_PROMPT "show-options-window" #define PREF_KEY_OPEN_DIALOG_FOLDER "open-dialog-dir" #define PREF_KEY_INHIBIT_HIBERNATION "inhibit-desktop-hibernation" diff --git a/libtransmission/rpcimpl.c b/libtransmission/rpcimpl.c index 5d6068256..df53beb00 100644 --- a/libtransmission/rpcimpl.c +++ b/libtransmission/rpcimpl.c @@ -842,15 +842,29 @@ sessionSet( tr_session * session, assert( idle_data == NULL ); - if( tr_bencDictFindStr( args_in, "download-dir", &str ) ) + if( tr_bencDictFindInt( args_in, TR_PREFS_KEY_ALT_LIMIT_ENABLED, &i ) ) + tr_sessionSetAltSpeedLimitEnabled( session, i!=0 ); + if( tr_bencDictFindInt( args_in, TR_PREFS_KEY_ALT_BEGIN, &i ) ) + tr_sessionSetAltSpeedLimitBegin( session, i ); + if( tr_bencDictFindInt( args_in, TR_PREFS_KEY_ALT_END, &i ) ) + tr_sessionSetAltSpeedLimitEnd( session, i ); + if( tr_bencDictFindInt( args_in, TR_PREFS_KEY_ALT_DL_LIMIT, &i ) ) + tr_sessionSetAltSpeedLimit( session, TR_DOWN, i ); + if( tr_bencDictFindInt( args_in, TR_PREFS_KEY_ALT_UL_LIMIT, &i ) ) + tr_sessionSetAltSpeedLimit( session, TR_UP, i ); + if( tr_bencDictFindInt( args_in, TR_PREFS_KEY_BLOCKLIST_ENABLED, &i ) ) + tr_blocklistSetEnabled( session, i!=0 ); + if( tr_bencDictFindStr( args_in, TR_PREFS_KEY_DOWNLOAD_DIR, &str ) ) tr_sessionSetDownloadDir( session, str ); - if( tr_bencDictFindInt( args_in, "peer-limit", &i ) ) + if( tr_bencDictFindInt( args_in, TR_PREFS_KEY_PEER_LIMIT_GLOBAL, &i ) ) tr_sessionSetPeerLimit( session, i ); - if( tr_bencDictFindInt( args_in, "pex-allowed", &i ) ) + if( tr_bencDictFindInt( args_in, TR_PREFS_KEY_PEER_LIMIT_TORRENT, &i ) ) + tr_sessionSetPeerLimitPerTorrent( session, i ); + if( tr_bencDictFindInt( args_in, TR_PREFS_KEY_PEX_ENABLED, &i ) ) tr_sessionSetPexEnabled( session, i ); - if( tr_bencDictFindInt( args_in, "port", &i ) ) + if( tr_bencDictFindInt( args_in, TR_PREFS_KEY_PEER_PORT, &i ) ) tr_sessionSetPeerPort( session, i ); - if( tr_bencDictFindInt( args_in, "port-forwarding-enabled", &i ) ) + if( tr_bencDictFindInt( args_in, TR_PREFS_KEY_PORT_FORWARDING, &i ) ) tr_sessionSetPortForwardingEnabled( session, i ); if( tr_bencDictFindInt( args_in, "speed-limit-down", &i ) ) tr_sessionSetSpeedLimit( session, TR_DOWN, i ); @@ -927,7 +941,7 @@ sessionStats( tr_session * session, } static const char* -sessionGet( tr_session * session, +sessionGet( tr_session * s, tr_benc * args_in UNUSED, tr_benc * args_out, struct tr_rpc_idle_data * idle_data ) @@ -936,22 +950,28 @@ sessionGet( tr_session * session, tr_benc * d = args_out; assert( idle_data == NULL ); - - tr_bencDictAddStr( d, "download-dir", tr_sessionGetDownloadDir( session ) ); - tr_bencDictAddInt( d, "peer-limit", tr_sessionGetPeerLimit( session ) ); - tr_bencDictAddInt( d, "pex-allowed", tr_sessionIsPexEnabled( session ) ); - tr_bencDictAddInt( d, "port", tr_sessionGetPeerPort( session ) ); - tr_bencDictAddInt( d, "port-forwarding-enabled", tr_sessionIsPortForwardingEnabled( session ) ); + tr_bencDictAddInt( d, TR_PREFS_KEY_ALT_LIMIT_ENABLED, tr_sessionIsAltSpeedLimitEnabled( s ) ); + tr_bencDictAddInt( d, TR_PREFS_KEY_ALT_UL_LIMIT, tr_sessionGetAltSpeedLimit( s, TR_UP ) ); + tr_bencDictAddInt( d, TR_PREFS_KEY_ALT_DL_LIMIT, tr_sessionGetAltSpeedLimit( s, TR_DOWN ) ); + tr_bencDictAddInt( d, TR_PREFS_KEY_ALT_BEGIN, tr_sessionGetAltSpeedLimitBegin( s ) ); + tr_bencDictAddInt( d, TR_PREFS_KEY_ALT_END, tr_sessionGetAltSpeedLimitEnd( s ) ); + tr_bencDictAddInt( d, TR_PREFS_KEY_BLOCKLIST_ENABLED, tr_blocklistIsEnabled( s ) ); + tr_bencDictAddStr( d, TR_PREFS_KEY_DOWNLOAD_DIR, tr_sessionGetDownloadDir( s ) ); + tr_bencDictAddInt( d, TR_PREFS_KEY_PEER_LIMIT_GLOBAL, tr_sessionGetPeerLimit( s ) ); + tr_bencDictAddInt( d, TR_PREFS_KEY_PEER_LIMIT_TORRENT, tr_sessionGetPeerLimitPerTorrent( s ) ); + tr_bencDictAddInt( d, TR_PREFS_KEY_PEX_ENABLED, tr_sessionIsPexEnabled( s ) ); + tr_bencDictAddInt( d, TR_PREFS_KEY_PEER_PORT, tr_sessionGetPeerPort( s ) ); + tr_bencDictAddInt( d, TR_PREFS_KEY_PORT_FORWARDING, tr_sessionIsPortForwardingEnabled( s ) ); tr_bencDictAddInt( d, "rpc-version", 4 ); tr_bencDictAddInt( d, "rpc-version-minimum", 1 ); - tr_bencDictAddInt( d, "speed-limit-up", tr_sessionGetSpeedLimit( session, TR_UP ) ); - tr_bencDictAddInt( d, "speed-limit-up-enabled", tr_sessionIsSpeedLimitEnabled( session, TR_UP ) ); - tr_bencDictAddInt( d, "speed-limit-down", tr_sessionGetSpeedLimit( session, TR_DOWN ) ); - tr_bencDictAddInt( d, "speed-limit-down-enabled", tr_sessionIsSpeedLimitEnabled( session, TR_DOWN ) ); - tr_bencDictAddDouble( d, "ratio-limit", tr_sessionGetRatioLimit( session ) ); - tr_bencDictAddInt( d, "ratio-limit-enabled", tr_sessionIsRatioLimited( session ) ); + tr_bencDictAddInt( d, "speed-limit-up", tr_sessionGetSpeedLimit( s, TR_UP ) ); + tr_bencDictAddInt( d, "speed-limit-up-enabled", tr_sessionIsSpeedLimitEnabled( s, TR_UP ) ); + tr_bencDictAddInt( d, "speed-limit-down", tr_sessionGetSpeedLimit( s, TR_DOWN ) ); + tr_bencDictAddInt( d, "speed-limit-down-enabled", tr_sessionIsSpeedLimitEnabled( s, TR_DOWN ) ); + tr_bencDictAddDouble( d, "ratio-limit", tr_sessionGetRatioLimit( s ) ); + tr_bencDictAddInt( d, "ratio-limit-enabled", tr_sessionIsRatioLimited( s ) ); tr_bencDictAddStr( d, "version", LONG_VERSION_STRING ); - switch( tr_sessionGetEncryption( session ) ) { + switch( tr_sessionGetEncryption( s ) ) { case TR_CLEAR_PREFERRED: str = "tolerated"; break; case TR_ENCRYPTION_REQUIRED: str = "required"; break; default: str = "preferred"; break; diff --git a/libtransmission/session.c b/libtransmission/session.c index b0fb10286..8008075d6 100644 --- a/libtransmission/session.c +++ b/libtransmission/session.c @@ -219,7 +219,7 @@ tr_sessionGetDefaultSettings( tr_benc * d ) { assert( tr_bencIsDict( d ) ); - tr_bencDictReserve( d, 30 ); + tr_bencDictReserve( d, 35 ); tr_bencDictAddInt( d, TR_PREFS_KEY_BLOCKLIST_ENABLED, FALSE ); tr_bencDictAddStr( d, TR_PREFS_KEY_DOWNLOAD_DIR, tr_getDefaultDownloadDir( ) ); tr_bencDictAddInt( d, TR_PREFS_KEY_DSPEED, 100 ); @@ -254,6 +254,11 @@ tr_sessionGetDefaultSettings( tr_benc * d ) tr_bencDictAddStr( d, TR_PREFS_KEY_RPC_WHITELIST, TR_DEFAULT_RPC_WHITELIST ); tr_bencDictAddInt( d, TR_PREFS_KEY_RPC_WHITELIST_ENABLED, TRUE ); tr_bencDictAddInt( d, TR_PREFS_KEY_RPC_PORT, atoi( TR_DEFAULT_RPC_PORT_STR ) ); + tr_bencDictAddInt( d, TR_PREFS_KEY_ALT_LIMIT_ENABLED, FALSE ); + tr_bencDictAddInt( d, TR_PREFS_KEY_ALT_BEGIN, 1320 ); /* 10pm */ + tr_bencDictAddInt( d, TR_PREFS_KEY_ALT_END, 300 ); /* 5am */ + tr_bencDictAddInt( d, TR_PREFS_KEY_ALT_DL_LIMIT, 200 ); /* double the regular default */ + tr_bencDictAddInt( d, TR_PREFS_KEY_ALT_UL_LIMIT, 200 ); /* double the regular default */ tr_bencDictAddInt( d, TR_PREFS_KEY_USPEED, 100 ); tr_bencDictAddInt( d, TR_PREFS_KEY_USPEED_ENABLED, 0 ); tr_bencDictAddInt( d, TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT, 14 ); @@ -302,6 +307,11 @@ tr_sessionGetSettings( tr_session * s, struct tr_benc * d ) tr_bencDictAddStr( d, TR_PREFS_KEY_RPC_USERNAME, freeme[n++] = tr_sessionGetRPCUsername( s ) ); tr_bencDictAddStr( d, TR_PREFS_KEY_RPC_WHITELIST, freeme[n++] = tr_sessionGetRPCWhitelist( s ) ); tr_bencDictAddInt( d, TR_PREFS_KEY_RPC_WHITELIST_ENABLED, tr_sessionGetRPCWhitelistEnabled( s ) ); + tr_bencDictAddInt( d, TR_PREFS_KEY_ALT_LIMIT_ENABLED, tr_sessionIsAltSpeedLimitEnabled( s ) ); + tr_bencDictAddInt( d, TR_PREFS_KEY_ALT_BEGIN, tr_sessionGetAltSpeedLimitBegin( s ) ); + tr_bencDictAddInt( d, TR_PREFS_KEY_ALT_END, tr_sessionGetAltSpeedLimitEnd( s ) ); + tr_bencDictAddInt( d, TR_PREFS_KEY_ALT_DL_LIMIT, tr_sessionGetAltSpeedLimit( s, TR_DOWN ) ); + tr_bencDictAddInt( d, TR_PREFS_KEY_ALT_UL_LIMIT, tr_sessionGetAltSpeedLimit( s, TR_UP ) ); tr_bencDictAddInt( d, TR_PREFS_KEY_USPEED, tr_sessionGetSpeedLimit( s, TR_UP ) ); tr_bencDictAddInt( d, TR_PREFS_KEY_USPEED_ENABLED, tr_sessionIsSpeedLimitEnabled( s, TR_UP ) ); tr_bencDictAddInt( d, TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT, s->uploadSlotsPerTorrent ); @@ -369,6 +379,7 @@ tr_sessionSaveSettings( tr_session * session, const char * configDir, tr_benc * static void metainfoLookupRescan( tr_session * ); static void tr_sessionInitImpl( void * ); +static int onBandwidthTimer( void * ); struct init_data { @@ -573,6 +584,25 @@ tr_sessionInitImpl( void * vdata ) tr_sessionSetRatioLimit( session, d ); tr_sessionSetRatioLimited( session, j ); + /** + *** Alternate speed limits for off-peak hours + **/ + found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_ALT_LIMIT_ENABLED, &i ); + assert( found ); + session->isAltSpeedLimited = i != 0; + + found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_ALT_BEGIN, &i ) + && tr_bencDictFindInt( &settings, TR_PREFS_KEY_ALT_END, &j ); + assert( found ); + session->altSpeedBeginTime = i; + session->altSpeedEndTime = j; + + found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_ALT_DL_LIMIT, &i ) + && tr_bencDictFindInt( &settings, TR_PREFS_KEY_ALT_UL_LIMIT, &j ); + assert( found ); + session->altSpeedLimit[TR_DOWN] = i; + session->altSpeedLimit[TR_UP] = j; + /* initialize the blocklist */ filename = tr_buildPath( session->configDir, "blocklists", NULL ); tr_mkdirp( filename, 0777 ); @@ -588,6 +618,8 @@ tr_sessionInitImpl( void * vdata ) assert( tr_isSession( session ) ); + session->bandwidthTimer = tr_timerNew( session, onBandwidthTimer, session, 60000 ); + /* first %s is the application name second %s is the version number */ tr_inf( _( "%s %s started" ), TR_NAME, LONG_VERSION_STRING ); @@ -776,18 +808,79 @@ tr_sessionGetRatioLimit( const tr_session * session ) **** ***/ +static tr_bool +isAltTime( const tr_session * session ) +{ + const time_t now = time( NULL ); + struct tm tm; + int minutes; + + tr_localtime_r( &now, &tm ); + minutes = tm.tm_hour*60 + tm.tm_min; + + if( session->altSpeedBeginTime <= session->altSpeedEndTime ) + { + return ( session->altSpeedBeginTime <= minutes ) + && ( minutes < session->altSpeedEndTime ); + } + else /* goes past midnight */ + { + return ( minutes >= session->altSpeedBeginTime ) + || ( minutes < session->altSpeedEndTime ); + } +} + +static int +getActiveSpeedLimit( const tr_session * session, tr_direction dir ) +{ + int val; + + if( tr_sessionIsAltSpeedLimitEnabled( session ) && session->isAltTime ) + val = tr_sessionGetAltSpeedLimit( session, dir ); + else if( tr_sessionIsSpeedLimitEnabled( session, dir ) ) + val = tr_sessionGetSpeedLimit( session, dir ); + else + val = -1; + + return val; +} + static void updateBandwidth( tr_session * session, tr_direction dir ) { - tr_bool zeroCase; + const int limit = getActiveSpeedLimit( session, dir ); + const tr_bool isLimited = limit >= 0; + const tr_bool zeroCase = isLimited && !limit; + + tr_bandwidthSetLimited( session->bandwidth, dir, isLimited && !zeroCase ); + + tr_bandwidthSetDesiredSpeed( session->bandwidth, dir, limit ); +} + +/* this is called once a minute to: + * (1) update session->isAltTime + * (2) alter the speed limits when the alt limits go on and off */ +static int +onBandwidthTimer( void * vsession ) +{ + tr_session * session = vsession; + tr_bool wasAltTime; assert( tr_isSession( session ) ); - zeroCase = session->speedLimit[dir] < 1 && session->isSpeedLimited[dir]; + wasAltTime = session->isAltTime; + session->isAltTime = isAltTime( session ); - tr_bandwidthSetLimited( session->bandwidth, dir, session->isSpeedLimited[dir] && !zeroCase ); + if( tr_sessionIsAltSpeedLimitEnabled( session ) && ( wasAltTime != session->isAltTime ) ) + { + updateBandwidth( session, TR_UP ); + updateBandwidth( session, TR_DOWN ); - tr_bandwidthSetDesiredSpeed( session->bandwidth, dir, session->speedLimit[dir] ); + if( session->altCallback != NULL ) + (*session->altCallback)( session, session->isAltTime, session->altCallbackUserData ); + } + + return TRUE; /* invoke again when another minute's passed */ } void @@ -832,6 +925,107 @@ tr_sessionGetSpeedLimit( const tr_session * session, tr_direction dir ) return session->speedLimit[dir]; } +tr_bool +tr_sessionIsAltSpeedLimitTime( const tr_session * session ) +{ + assert( tr_isSession( session ) ); + + return session->isAltTime; +} + +void +tr_sessionSetAltSpeedLimitEnabled( tr_session * session, + tr_bool isEnabled ) +{ + assert( tr_isSession( session ) ); + assert( tr_isBool( isEnabled ) ); + + session->isAltSpeedLimited = isEnabled; + + onBandwidthTimer( session ); +} + +tr_bool +tr_sessionIsAltSpeedLimitEnabled( const tr_session * session ) +{ + assert( tr_isSession( session ) ); + + return session->isAltSpeedLimited; +} + +void +tr_sessionSetAltSpeedLimit( tr_session * session, + tr_direction dir, + int desiredSpeed ) +{ + assert( tr_isSession( session ) ); + assert( tr_isDirection( dir ) ); + assert( desiredSpeed >= 0 ); + + session->altSpeedLimit[dir] = desiredSpeed; + updateBandwidth( session, dir ); +} + +int +tr_sessionGetAltSpeedLimit( const tr_session * session, + tr_direction dir ) +{ + assert( tr_isSession( session ) ); + assert( tr_isDirection( dir ) ); + + return session->altSpeedLimit[dir]; +} + +void +tr_sessionSetAltSpeedLimitBegin( tr_session * session, int minutesSinceMidnight ) +{ + assert( tr_isSession( session ) ); + + session->altSpeedBeginTime = minutesSinceMidnight; +} + +int +tr_sessionGetAltSpeedLimitBegin( const tr_session * session ) +{ + assert( tr_isSession( session ) ); + + return session->altSpeedBeginTime; +} + +void +tr_sessionSetAltSpeedLimitEnd( tr_session * session, int minutesSinceMidnight ) +{ + assert( tr_isSession( session ) ); + + session->altSpeedEndTime = minutesSinceMidnight; +} + +int +tr_sessionGetAltSpeedLimitEnd( const tr_session * session ) +{ + assert( tr_isSession( session ) ); + + return session->altSpeedEndTime; +} + +void +tr_sessionSetAltSpeedCallback( tr_session * session, + tr_alt_speed_func func, + void * userData ) +{ + assert( tr_isSession( session ) ); + + session->altCallback = func; + session->altCallbackUserData = userData; +} + +void +tr_sessionClearAltSpeedCallback( tr_session * session ) +{ + tr_sessionSetAltSpeedCallback( session, NULL, NULL ); +} + + /*** **** ***/ @@ -914,6 +1108,7 @@ tr_closeAllConnections( void * vsession ) assert( tr_isSession( session ) ); + tr_timerFree( &session->bandwidthTimer ); tr_statsClose( session ); tr_sharedShuttingDown( session->shared ); tr_rpcClose( &session->rpcServer ); diff --git a/libtransmission/session.h b/libtransmission/session.h index 340a08276..bdb41e28e 100644 --- a/libtransmission/session.h +++ b/libtransmission/session.h @@ -70,6 +70,15 @@ struct tr_session tr_bool isSpeedLimited[2]; int speedLimit[2]; + tr_bool isAltSpeedLimited; + int altSpeedBeginTime; + int altSpeedEndTime; + int altSpeedLimit[2]; + tr_bool isAltTime; + tr_alt_speed_func * altCallback; + void * altCallbackUserData; + + int magicNumber; tr_encryption_mode encryptionMode; @@ -122,6 +131,8 @@ struct tr_session struct tr_metainfo_lookup * metainfoLookup; int metainfoLookupCount; + struct tr_timer * bandwidthTimer; + /* the size of the output buffer for peer connections */ int so_sndbuf; diff --git a/libtransmission/transmission.h b/libtransmission/transmission.h index 7fa4c9603..066874592 100644 --- a/libtransmission/transmission.h +++ b/libtransmission/transmission.h @@ -151,6 +151,11 @@ static TR_INLINE tr_bool tr_isEncryptionMode( tr_encryption_mode m ) #define TR_DEFAULT_PEER_LIMIT_GLOBAL_STR "240" #define TR_DEFAULT_PEER_LIMIT_TORRENT_STR "60" +#define TR_PREFS_KEY_ALT_LIMIT_ENABLED "alt-speed-limit-enabled" +#define TR_PREFS_KEY_ALT_BEGIN "alt-speed-limit-begin" +#define TR_PREFS_KEY_ALT_DL_LIMIT "alt-speed-limit-down" +#define TR_PREFS_KEY_ALT_END "alt-speed-limit-end" +#define TR_PREFS_KEY_ALT_UL_LIMIT "alt-speed-limit-up" #define TR_PREFS_KEY_BLOCKLIST_ENABLED "blocklist-enabled" #define TR_PREFS_KEY_DOWNLOAD_DIR "download-dir" #define TR_PREFS_KEY_DSPEED "download-limit" @@ -230,9 +235,9 @@ void tr_sessionGetSettings( tr_session *, struct tr_benc * dictionary ); * * FIXME: this belongs in libtransmissionapp * + * @param dictionary pointer to an uninitialized tr_benc * @param configDir the configuration directory to find settings.json - * @param initme pointer to an uninitialized tr_benc - * @param appName examples: Transmission, transmission-daemon + * @param appName if configDir is empty, appName is used to get the default config dir. * @see tr_sessionGetDefaultSettings() * @see tr_sessionInit() * @see tr_sessionSaveSettings() @@ -548,6 +553,10 @@ typedef enum } tr_direction; +/*** +**** +***/ + void tr_sessionSetSpeedLimitEnabled ( tr_session * session, tr_direction direction, tr_bool isEnabled ); @@ -562,6 +571,58 @@ void tr_sessionSetSpeedLimit ( tr_session * session, int tr_sessionGetSpeedLimit ( const tr_session * session, tr_direction direction ); +/*** +**** +***/ + +typedef void ( tr_alt_speed_func )( tr_session * session, + tr_bool isAltActive, + void * userData ); + +/** + * Register to be notified whenever the alternate speed limits go on and off. + * + * func is invoked FROM LIBTRANSMISSION'S THREAD! + * This means func must be fast (to avoid blocking peers), + * shouldn't call libtransmission functions (to avoid deadlock), + * and shouldn't modify client-level memory without using a mutex! + */ +void tr_sessionSetAltSpeedCallback( tr_session * session, + tr_alt_speed_func func, + void * userData ); + +void tr_sessionClearAltSpeedCallback( tr_session * session ); + + +void tr_sessionSetAltSpeedLimitEnabled( tr_session * session, + tr_bool isEnabled ); + +tr_bool tr_sessionIsAltSpeedLimitEnabled( const tr_session * session ); + +/** @return true if the current time is between the alt begin and end times */ +tr_bool tr_sessionIsAltSpeedLimitTime( const tr_session * session ); + +void tr_sessionSetAltSpeedLimitBegin( tr_session * session, + int minutesSinceMidnight ); + +int tr_sessionGetAltSpeedLimitBegin( const tr_session * session ); + +void tr_sessionSetAltSpeedLimitEnd( tr_session * session, + int minutesSinceMidnight ); + +int tr_sessionGetAltSpeedLimitEnd( const tr_session * session ); + +void tr_sessionSetAltSpeedLimit( tr_session * session, + tr_direction direction, + int KiB_sec ); + +int tr_sessionGetAltSpeedLimit( const tr_session * session, + tr_direction direction ); + +/*** +**** +***/ + void tr_sessionSetRatioLimited ( tr_session * session, tr_bool isEnabled ); diff --git a/web/javascript/transmission.js b/web/javascript/transmission.js index 71ae2c784..1827d2781 100644 --- a/web/javascript/transmission.js +++ b/web/javascript/transmission.js @@ -723,8 +723,8 @@ Transmission.prototype = var up_limit = prefs[RPC._UpSpeedLimit]; var up_limited = prefs[RPC._UpSpeedLimited]; - $('div.download_location input')[0].value = prefs['download-dir']; - $('div.port input')[0].value = prefs['port']; + $('div.download_location input')[0].value = prefs[RPC._DownloadDir]; + $('div.port input')[0].value = prefs[RPC._PeerPort]; $('div.auto_start input')[0].checked = prefs[Prefs._AutoStart]; $('input#limit_download')[0].checked = down_limited == 1; $('input#download_rate')[0].value = down_limit; diff --git a/web/javascript/transmission.remote.js b/web/javascript/transmission.remote.js index d5e2b3a53..0b2b69777 100644 --- a/web/javascript/transmission.remote.js +++ b/web/javascript/transmission.remote.js @@ -17,7 +17,7 @@ RPC._EncryptionRequired = 'required'; RPC._UpSpeedLimit = 'speed-limit-up'; RPC._DownSpeedLimit = 'speed-limit-down'; RPC._DownloadDir = 'download-dir'; -RPC._PeerPort = 'port'; +RPC._PeerPort = 'peer-port'; RPC._UpSpeedLimited = 'speed-limit-up-enabled'; RPC._DownSpeedLimited = 'speed-limit-down-enabled';