source: trunk/libtransmission/session.c @ 6049

Last change on this file since 6049 was 6049, checked in by charles, 14 years ago

get RPC password protections working in libT and the gtk+ client. mac, daemon, and cli need to be synced.

  • Property svn:keywords set to Date Rev Author Id
File size: 21.9 KB
Line 
1/******************************************************************************
2 * $Id: session.c 6049 2008-06-05 16:23:03Z charles $
3 *
4 * Copyright (c) 2005-2008 Transmission authors and contributors
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *****************************************************************************/
24
25#include <assert.h>
26#include <stdlib.h>
27#include <string.h> /* memcpy */
28
29#include <signal.h>
30#include <sys/types.h> /* stat */
31#include <sys/stat.h> /* stat */
32#include <unistd.h> /* stat */
33#include <dirent.h> /* opendir */
34
35#include "transmission.h"
36#include "blocklist.h"
37#include "fdlimit.h"
38#include "list.h"
39#include "metainfo.h" /* tr_metainfoFree */
40#include "net.h"
41#include "peer-mgr.h"
42#include "platform.h" /* tr_lock */
43#include "port-forwarding.h"
44#include "ratecontrol.h"
45#include "rpc-server.h"
46#include "stats.h"
47#include "torrent.h"
48#include "tracker.h"
49#include "trevent.h"
50#include "utils.h"
51#include "web.h"
52
53/* Generate a peer id : "-TRxyzb-" + 12 random alphanumeric
54   characters, where x is the major version number, y is the
55   minor version number, z is the maintenance number, and b
56   designates beta (Azureus-style) */
57uint8_t*
58tr_peerIdNew( void )
59{
60    int i;
61    int val;
62    int total = 0;
63    uint8_t * buf = tr_new( uint8_t, 21 );
64    const char * pool = "0123456789abcdefghijklmnopqrstuvwxyz";
65    const int base = 36;
66
67    memcpy( buf, PEERID_PREFIX, 8 );
68
69    for( i=8; i<19; ++i ) {
70        val = tr_rand( base );
71        total += val;
72        buf[i] = pool[val];
73    }
74
75    val = total % base ? base - (total % base) : 0;
76    total += val;
77    buf[19] = pool[val];
78    buf[20] = '\0';
79
80    return buf;
81}
82
83const uint8_t*
84tr_getPeerId( void )
85{
86    static uint8_t * id = NULL;
87    if( id == NULL )
88        id = tr_peerIdNew( );
89    return id;
90}
91
92/***
93****
94***/
95
96tr_encryption_mode
97tr_sessionGetEncryption( tr_session * session )
98{
99    assert( session != NULL );
100
101    return session->encryptionMode;
102}
103
104void
105tr_sessionSetEncryption( tr_session * session, tr_encryption_mode mode )
106{
107    assert( session != NULL );
108    assert( mode==TR_ENCRYPTION_PREFERRED
109         || mode==TR_ENCRYPTION_REQUIRED
110         || mode==TR_PLAINTEXT_PREFERRED );
111
112    session->encryptionMode = mode;
113}
114
115/***
116****
117***/
118
119static void metainfoLookupRescan( tr_handle * h );
120
121tr_handle *
122tr_sessionInitFull( const char * configDir,
123                    const char * downloadDir,
124                    const char * tag,
125                    int          isPexEnabled,
126                    int          isPortForwardingEnabled,
127                    int          publicPort,
128                    int          encryptionMode,
129                    int          isUploadLimitEnabled,
130                    int          uploadLimit,
131                    int          isDownloadLimitEnabled,
132                    int          downloadLimit,
133                    int          globalPeerLimit,
134                    int          messageLevel,
135                    int          isMessageQueueingEnabled,
136                    int          isBlocklistEnabled,
137                    int          peerSocketTOS,
138                    int          rpcIsEnabled,
139                    int          rpcPort,
140                    const char * rpcACL,
141                    int          rpcPasswordIsEnabled,
142                    const char * rpcUsername,
143                    const char * rpcPassword )
144{
145    tr_handle * h;
146    char filename[MAX_PATH_LENGTH];
147
148#ifndef WIN32
149    /* Don't exit when writing on a broken socket */
150    signal( SIGPIPE, SIG_IGN );
151#endif
152
153    if( configDir == NULL )
154        configDir = tr_getDefaultConfigDir( );
155
156    tr_msgInit( );
157    tr_setMessageLevel( messageLevel );
158    tr_setMessageQueuing( isMessageQueueingEnabled );
159
160    h = tr_new0( tr_handle, 1 );
161    h->lock = tr_lockNew( );
162    h->isPexEnabled = isPexEnabled ? 1 : 0;
163    h->encryptionMode = encryptionMode;
164    h->peerSocketTOS = peerSocketTOS;
165    h->downloadDir = tr_strdup( downloadDir );
166
167    tr_setConfigDir( h, configDir );
168
169    tr_netInit(); /* must go before tr_eventInit */
170
171    tr_eventInit( h );
172    while( !h->events )
173        tr_wait( 50 );
174
175    h->tag = tr_strdup( tag );
176    h->peerMgr = tr_peerMgrNew( h );
177
178    /* Initialize rate and file descripts controls */
179
180    h->upload = tr_rcInit();
181    tr_rcSetLimit( h->upload, uploadLimit );
182    h->useUploadLimit = isUploadLimitEnabled;
183
184    h->download = tr_rcInit();
185    tr_rcSetLimit( h->download, downloadLimit );
186    h->useDownloadLimit = isDownloadLimitEnabled;
187
188    tr_fdInit( globalPeerLimit );
189    h->shared = tr_sharedInit( h, isPortForwardingEnabled, publicPort );
190    h->isPortSet = publicPort >= 0;
191
192    /* first %s is the application name
193       second %s is the version number */
194    tr_inf( _( "%s %s started" ), TR_NAME, LONG_VERSION_STRING );
195
196    /* initialize the blocklist */
197    tr_buildPath( filename, sizeof( filename ), h->configDir, "blocklists", NULL );
198    tr_mkdirp( filename, 0777 );
199    tr_buildPath( filename, sizeof( filename ), h->configDir, "blocklists", "level1.bin", NULL );
200    h->blocklist = _tr_blocklistNew( filename, isBlocklistEnabled );
201
202    tr_statsInit( h );
203
204    h->web = tr_webInit( h );
205    h->rpcServer = tr_rpcInit( h, rpcIsEnabled, rpcPort, rpcACL,
206                                  rpcPasswordIsEnabled, rpcUsername, rpcPassword );
207
208    metainfoLookupRescan( h );
209
210    return h;
211}
212
213tr_handle *
214tr_sessionInit( const char * configDir,
215                const char * downloadDir,
216                const char * tag )
217{
218    return tr_sessionInitFull( configDir,
219                               downloadDir,
220                               tag,
221                               TR_DEFAULT_PEX_ENABLED,
222                               TR_DEFAULT_PORT_FORWARDING_ENABLED,
223                               -1, /* public port */
224                               TR_ENCRYPTION_PREFERRED, /* encryption mode */
225                               FALSE, /* use upload speed limit? */ 
226                               -1, /* upload speed limit */
227                               FALSE, /* use download speed limit? */
228                               -1, /* download speed limit */
229                               TR_DEFAULT_GLOBAL_PEER_LIMIT,
230                               TR_MSG_INF, /* message level */
231                               FALSE, /* is message queueing enabled? */
232                               FALSE, /* is the blocklist enabled? */
233                               TR_DEFAULT_PEER_SOCKET_TOS,
234                               TR_DEFAULT_RPC_ENABLED,
235                               TR_DEFAULT_RPC_PORT,
236                               TR_DEFAULT_RPC_ACL,
237                               FALSE,
238                               "fnord",
239                               "potzrebie" );
240}
241
242/***
243****
244***/
245
246void
247tr_sessionSetDownloadDir( tr_handle * handle, const char * dir )
248{
249    if( handle->downloadDir != dir )
250    {
251        tr_free( handle->downloadDir );
252        handle->downloadDir = tr_strdup( dir );
253    }
254}
255
256const char *
257tr_sessionGetDownloadDir( const tr_handle * handle )
258{
259    return handle->downloadDir;
260}
261
262/***
263****
264***/
265
266void
267tr_globalLock( struct tr_handle * handle )
268{
269    tr_lockLock( handle->lock );
270}
271
272void
273tr_globalUnlock( struct tr_handle * handle )
274{
275    tr_lockUnlock( handle->lock );
276}
277
278int
279tr_globalIsLocked( const struct tr_handle * handle )
280{
281    return handle && tr_lockHave( handle->lock );
282}
283
284/***********************************************************************
285 * tr_setBindPort
286 ***********************************************************************
287 *
288 **********************************************************************/
289
290struct bind_port_data
291{
292    tr_handle * handle;
293    int port;
294};
295
296static void
297tr_setBindPortImpl( void * vdata )
298{
299    struct bind_port_data * data = vdata;
300    tr_handle * handle = data->handle;
301    const int port = data->port;
302
303    handle->isPortSet = 1;
304    tr_sharedSetPort( handle->shared, port );
305
306    tr_free( data );
307}
308
309void
310tr_sessionSetPeerPort( tr_handle * handle, int port )
311{
312    struct bind_port_data * data = tr_new( struct bind_port_data, 1 );
313    data->handle = handle;
314    data->port = port;
315    tr_runInEventThread( handle, tr_setBindPortImpl, data );
316}
317
318int
319tr_sessionGetPeerPort( const tr_handle * h )
320{
321    assert( h != NULL );
322    return tr_sharedGetPeerPort( h->shared );
323}
324
325tr_port_forwarding
326tr_sessionGetPortForwarding( const tr_handle * h )
327{
328    return tr_sharedTraversalStatus( h->shared );
329}
330
331/***
332****
333***/
334
335void
336tr_sessionSetSpeedLimitEnabled( tr_handle  * h,
337                                int          up_or_down,
338                                int          use_flag )
339{
340    if( up_or_down == TR_UP )
341        h->useUploadLimit = use_flag ? 1 : 0;
342    else
343        h->useDownloadLimit = use_flag ? 1 : 0;
344}
345
346int
347tr_sessionIsSpeedLimitEnabled( const tr_handle * h, int up_or_down )
348{
349       return up_or_down==TR_UP ? h->useUploadLimit : h->useDownloadLimit;
350}
351
352void
353tr_sessionSetSpeedLimit( tr_handle  * h,
354                         int          up_or_down,
355                         int          KiB_sec )
356{
357    if( up_or_down == TR_DOWN )
358        tr_rcSetLimit( h->download, KiB_sec );
359    else
360        tr_rcSetLimit( h->upload, KiB_sec );
361}
362
363int
364tr_sessionGetSpeedLimit( const tr_handle * h, int up_or_down )
365{
366    return tr_rcGetLimit( up_or_down==TR_UP ? h->upload : h->download );
367}
368
369/***
370****
371***/
372
373void
374tr_sessionSetPeerLimit( tr_handle * handle UNUSED,
375                        uint16_t    maxGlobalPeers )
376{
377    tr_fdSetPeerLimit( maxGlobalPeers );
378}
379
380uint16_t
381tr_sessionGetPeerLimit( const tr_handle * handle UNUSED )
382{
383    return tr_fdGetPeerLimit( );
384}
385
386/***
387****
388***/
389
390void
391tr_sessionGetSpeed( const tr_handle  * session,
392                    float            * toClient,
393                    float            * toPeer )
394{
395    if( session && toClient )
396        *toClient = tr_rcRate( session->download );
397    if( session && toPeer )
398        *toPeer = tr_rcRate( session->upload );
399}
400
401int
402tr_sessionCountTorrents( const tr_handle * h )
403{
404    return h->torrentCount;
405}
406
407/* close the biggest torrents first */
408static int
409compareTorrentByCur( const void * va, const void * vb )
410{
411    const tr_torrent * a = *(const tr_torrent**)va;
412    const tr_torrent * b = *(const tr_torrent**)vb;
413    return -tr_compareUint64( a->downloadedCur + a->uploadedCur,
414                              b->downloadedCur + b->uploadedCur );
415}
416
417static void
418tr_closeAllConnections( void * vh )
419{
420    tr_handle * h = vh;
421    tr_torrent * tor;
422    int i, n;
423    tr_torrent ** torrents;
424
425    tr_sharedShuttingDown( h->shared );
426    tr_trackerShuttingDown( h );
427    tr_rpcClose( &h->rpcServer );
428
429    /* close the torrents.  get the most active ones first so that
430     * if we can't get them all closed in a reasonable amount of time,
431     * at least we get the most important ones first. */
432    tor = NULL;
433    n = h->torrentCount;
434    torrents = tr_new( tr_torrent*, h->torrentCount );
435    for( i=0; i<n; ++i )
436        torrents[i] = tor = tr_torrentNext( h, tor );
437    qsort( torrents, n, sizeof(tr_torrent*), compareTorrentByCur );
438    for( i=0; i<n; ++i )
439        tr_torrentFree( torrents[i] );
440    tr_free( torrents );
441
442    tr_peerMgrFree( h->peerMgr );
443
444    tr_rcClose( h->upload );
445    tr_rcClose( h->download );
446   
447    h->isClosed = TRUE;
448}
449
450static int
451deadlineReached( const uint64_t deadline )
452{
453    return tr_date( ) >= deadline;
454}
455
456#define SHUTDOWN_MAX_SECONDS 30
457
458void
459tr_sessionClose( tr_handle * h )
460{
461    int i;
462    const int maxwait_msec = SHUTDOWN_MAX_SECONDS * 1000;
463    const uint64_t deadline = tr_date( ) + maxwait_msec;
464
465    tr_deepLog( __FILE__, __LINE__, NULL, "shutting down transmission session %p", h );
466    tr_statsClose( h );
467
468    tr_runInEventThread( h, tr_closeAllConnections, h );
469    while( !h->isClosed && !deadlineReached( deadline ) )
470        tr_wait( 100 );
471
472    _tr_blocklistFree( h->blocklist );
473    h->blocklist = NULL;
474    tr_webClose( &h->web );
475
476    tr_eventClose( h );
477    while( h->events && !deadlineReached( deadline ) )
478        tr_wait( 100 );
479
480    tr_fdClose( );
481    tr_lockFree( h->lock );
482    for( i=0; i<h->metainfoLookupCount; ++i )
483        tr_free( h->metainfoLookup[i].filename );
484    tr_free( h->metainfoLookup );
485    tr_free( h->tag );
486    tr_free( h->configDir );
487    tr_free( h->resumeDir );
488    tr_free( h->torrentDir );
489    tr_free( h->downloadDir );
490    free( h );
491}
492
493tr_torrent **
494tr_sessionLoadTorrents ( tr_handle   * h,
495                         tr_ctor     * ctor,
496                         int         * setmeCount )
497{
498    int i, n = 0;
499    struct stat sb;
500    DIR * odir = NULL;
501    const char * dirname = tr_getTorrentDir( h );
502    tr_torrent ** torrents;
503    tr_list *l=NULL, *list=NULL;
504
505    tr_ctorSetSave( ctor, FALSE ); /* since we already have them */
506
507    if( !stat( dirname, &sb )
508        && S_ISDIR( sb.st_mode )
509        && (( odir = opendir ( dirname ) )) )
510    {
511        struct dirent *d;
512        for (d = readdir( odir ); d!=NULL; d=readdir( odir ) )
513        {
514            if( d->d_name && d->d_name[0]!='.' ) /* skip dotfiles, ., and .. */
515            {
516                tr_torrent * tor;
517                char filename[MAX_PATH_LENGTH];
518                tr_buildPath( filename, sizeof(filename), dirname, d->d_name, NULL );
519                tr_ctorSetMetainfoFromFile( ctor, filename );
520                tor = tr_torrentNew( h, ctor, NULL );
521                if( tor ) {
522                    tr_list_append( &list, tor );
523                    n++;
524                }
525            }
526        }
527        closedir( odir );
528    }
529
530    torrents = tr_new( tr_torrent*, n );
531    for( i=0, l=list; l!=NULL; l=l->next )
532        torrents[i++] = (tr_torrent*) l->data;
533    assert( i==n );
534
535    tr_list_free( &list, NULL );
536
537    if( n )
538        tr_inf( _( "Loaded %d torrents" ), n );
539
540    if( setmeCount )
541        *setmeCount = n;
542    return torrents;
543}
544
545/***
546****
547***/
548
549void
550tr_sessionSetPexEnabled( tr_handle * handle, int isPexEnabled )
551{
552    handle->isPexEnabled = isPexEnabled ? 1 : 0;
553}
554
555int
556tr_sessionIsPexEnabled( const tr_handle * handle )
557{
558    return handle->isPexEnabled;
559}
560
561/***
562****
563***/
564
565void
566tr_sessionSetPortForwardingEnabled( tr_handle * h, int enable )
567{
568    tr_globalLock( h );
569    tr_sharedTraversalEnable( h->shared, enable );
570    tr_globalUnlock( h );
571}
572
573int
574tr_sessionIsPortForwardingEnabled( const tr_handle * h )
575{
576    return tr_sharedTraversalIsEnabled( h->shared );
577}
578
579/***
580****
581***/
582
583int
584tr_blocklistGetRuleCount( tr_handle * handle )
585{
586    return _tr_blocklistGetRuleCount( handle->blocklist );
587}
588
589int
590tr_blocklistIsEnabled( const tr_handle * handle )
591{
592    return _tr_blocklistIsEnabled( handle->blocklist );
593}
594
595void
596tr_blocklistSetEnabled( tr_handle * handle, int isEnabled )
597{
598    _tr_blocklistSetEnabled( handle->blocklist, isEnabled );
599}
600
601int
602tr_blocklistExists( const tr_handle * handle )
603{
604    return _tr_blocklistExists( handle->blocklist );
605}
606
607int
608tr_blocklistSetContent( tr_handle  * handle, const char * filename )
609{
610    return _tr_blocklistSetContent( handle->blocklist, filename );
611}
612
613int
614tr_blocklistHasAddress( tr_handle * handle, const struct in_addr * addr )
615{
616    return _tr_blocklistHasAddress( handle->blocklist, addr );
617}
618
619/***
620****
621***/
622
623static int
624compareLookupEntries( const void * va, const void * vb )
625{
626    const struct tr_metainfo_lookup * a = va;
627    const struct tr_metainfo_lookup * b = vb;
628    return strcmp( a->hashString, b->hashString );
629}
630
631static void
632metainfoLookupResort( tr_handle * h )
633{
634    qsort( h->metainfoLookup, 
635           h->metainfoLookupCount,
636           sizeof( struct tr_metainfo_lookup ),
637           compareLookupEntries );
638}
639
640static int
641compareHashStringToLookupEntry( const void * va, const void * vb )
642{
643    const char * a = va;
644    const struct tr_metainfo_lookup * b = vb;
645    return strcmp( a, b->hashString );
646}
647
648const char*
649tr_sessionFindTorrentFile( const tr_handle  * h,
650                           const char       * hashStr )
651{
652    struct tr_metainfo_lookup * l = bsearch( hashStr,
653                                             h->metainfoLookup,
654                                             h->metainfoLookupCount,
655                                             sizeof( struct tr_metainfo_lookup ),
656                                             compareHashStringToLookupEntry );
657    return l ? l->filename : NULL;
658}
659
660static void
661metainfoLookupRescan( tr_handle * h )
662{
663    int i;
664    int n;
665    struct stat sb;
666    const char * dirname = tr_getTorrentDir( h );
667    DIR * odir = NULL;
668    tr_ctor * ctor = NULL;
669    tr_list * list = NULL;
670
671    /* walk through the directory and find the mappings */
672    ctor = tr_ctorNew( h );
673    tr_ctorSetSave( ctor, FALSE ); /* since we already have them */
674    if( !stat( dirname, &sb ) && S_ISDIR( sb.st_mode ) && (( odir = opendir( dirname ))))
675    {
676        struct dirent *d;
677        for (d = readdir( odir ); d!=NULL; d=readdir( odir ) )
678        {
679            if( d->d_name && d->d_name[0]!='.' ) /* skip dotfiles, ., and .. */
680            {
681                tr_info inf;
682                char filename[MAX_PATH_LENGTH];
683                tr_buildPath( filename, sizeof(filename), dirname, d->d_name, NULL );
684                tr_ctorSetMetainfoFromFile( ctor, filename );
685                if( !tr_torrentParse( h, ctor, &inf ) )
686                {
687                    tr_list_append( &list, tr_strdup( inf.hashString ) );
688                    tr_list_append( &list, tr_strdup( filename ) );
689                    tr_metainfoFree( &inf );
690                }
691            }
692        }
693        closedir( odir );
694    }
695    tr_ctorFree( ctor );
696
697    n = tr_list_size( list ) / 2;
698    h->metainfoLookup = tr_new0( struct tr_metainfo_lookup, n );
699    h->metainfoLookupCount = n;
700    for( i=0; i<n; ++i )
701    {
702        char * hashString = tr_list_pop_front( &list );
703        char * filename = tr_list_pop_front( &list );
704
705        memcpy( h->metainfoLookup[i].hashString, hashString, 2*SHA_DIGEST_LENGTH+1 );
706        tr_free( hashString );
707        h->metainfoLookup[i].filename = filename;
708    }
709
710    metainfoLookupResort( h );
711    tr_dbg( "Found %d torrents in \"%s\"", n, dirname );
712}
713
714void
715tr_sessionSetTorrentFile( tr_handle    * h,
716                          const char   * hashString,
717                          const char   * filename )
718{
719    struct tr_metainfo_lookup * l = bsearch( hashString,
720                                             h->metainfoLookup,
721                                             h->metainfoLookupCount,
722                                             sizeof( struct tr_metainfo_lookup ),
723                                             compareHashStringToLookupEntry );
724    if( l != NULL )
725    {
726        if( l->filename != filename )
727        {
728            tr_free( l->filename );
729            l->filename = tr_strdup( filename );
730        }
731    }
732    else
733    {
734        const int n = h->metainfoLookupCount++;
735        struct tr_metainfo_lookup * node;
736        h->metainfoLookup = tr_renew( struct tr_metainfo_lookup,
737                                      h->metainfoLookup,
738                                      h->metainfoLookupCount );
739        node = h->metainfoLookup + n;
740        memcpy( node->hashString, hashString, 2*SHA_DIGEST_LENGTH+1 );
741        node->filename = tr_strdup( filename );
742        metainfoLookupResort( h );
743    }
744}
745
746tr_torrent*
747tr_torrentNext( tr_handle * session, tr_torrent * tor )
748{
749    return tor ? tor->next : session->torrentList;
750}
751
752/***
753****
754***/
755
756void
757tr_sessionSetRPCEnabled( tr_handle * session, int isEnabled )
758{
759    tr_rpcSetEnabled( session->rpcServer, isEnabled );
760}
761int
762tr_sessionIsRPCEnabled( const tr_handle * session )
763{
764    return tr_rpcIsEnabled( session->rpcServer );
765}
766void
767tr_sessionSetRPCPort( tr_handle * session, int port )
768{
769    tr_rpcSetPort( session->rpcServer, port );
770}
771int
772tr_sessionGetRPCPort( const tr_handle * session )
773{
774    return tr_rpcGetPort( session->rpcServer );
775}
776void
777tr_sessionSetRPCCallback( tr_handle    * session,
778                          tr_rpc_func    func,
779                          void         * user_data )
780{
781    session->rpc_func = func;
782    session->rpc_func_user_data = user_data;
783}
784
785int
786tr_sessionTestRPCACL( const tr_handle  * session,
787                      const char       * acl,
788                      char            ** allocme_errmsg )
789{
790    return tr_rpcTestACL( session->rpcServer, acl, allocme_errmsg );
791}
792
793int
794tr_sessionSetRPCACL( tr_handle    * session,
795                     const char   * acl,
796                     char        ** allocme_errmsg )
797{
798    return tr_rpcSetACL( session->rpcServer, acl, allocme_errmsg );
799}
800
801char*
802tr_sessionGetRPCACL( const tr_session * session )
803{
804    return tr_rpcGetACL( session->rpcServer );
805}
806
807void
808tr_sessionSetRPCPassword( tr_handle * session, const char * password )
809{
810    tr_rpcSetPassword( session->rpcServer, password );
811}
812
813char*
814tr_sessionGetRPCPassword( const tr_handle * session )
815{
816    return tr_rpcGetPassword( session->rpcServer );
817}
818
819void
820tr_sessionSetRPCUsername( tr_handle * session, const char * username )
821{
822    tr_rpcSetUsername( session->rpcServer, username );
823}
824
825char*
826tr_sessionGetRPCUsername( const tr_handle * session )
827{
828    return tr_rpcGetUsername( session->rpcServer );
829}
830
831void
832tr_sessionSetRPCPasswordEnabled( tr_handle * session, int isEnabled )
833{
834    tr_rpcSetPasswordEnabled( session->rpcServer, isEnabled );
835}
836
837int
838tr_sessionIsRPCPasswordEnabled( const tr_handle * session )
839{
840    return tr_rpcIsPasswordEnabled( session->rpcServer );
841}
Note: See TracBrowser for help on using the repository browser.