source: trunk/libtransmission/torrent-ctor.c @ 12168

Last change on this file since 12168 was 12168, checked in by jordan, 11 years ago

(trunk) #4081 "Add 'cookieString' argument 'torrent-add' method in RPC" -- done.

  • Property svn:keywords set to Date Rev Author Id
File size: 11.1 KB
Line 
1/*
2 * This file Copyright (C) Mnemosyne LLC
3 *
4 * This file is licensed by the GPL version 2. Works owned by the
5 * Transmission project are granted a special exemption to clause 2(b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
9 *
10 * $Id: torrent-ctor.c 12168 2011-03-15 04:22:47Z jordan $
11 */
12
13#include <errno.h> /* EINVAL */
14#include "transmission.h"
15#include "bencode.h"
16#include "magnet.h"
17#include "platform.h"
18#include "session.h" /* tr_sessionFindTorrentFile() */
19#include "torrent.h" /* tr_ctorGetSave() */
20#include "utils.h" /* tr_new0 */
21
22struct optional_args
23{
24    tr_bool         isSet_paused;
25    tr_bool         isSet_connected;
26    tr_bool         isSet_downloadDir;
27
28    tr_bool         isPaused;
29    uint16_t        peerLimit;
30    char          * downloadDir;
31};
32
33/** Opaque class used when instantiating torrents.
34 * @ingroup tr_ctor */
35struct tr_ctor
36{
37    const tr_session *      session;
38    tr_bool                 saveInOurTorrentsDir;
39    tr_bool                 doDelete;
40
41    tr_priority_t           bandwidthPriority;
42    tr_bool                 isSet_metainfo;
43    tr_bool                 isSet_delete;
44    tr_benc                 metainfo;
45    char *                  sourceFile;
46
47    struct optional_args    optionalArgs[2];
48
49    char                  * cookies;
50    char                  * incompleteDir;
51
52    tr_file_index_t       * want;
53    tr_file_index_t         wantSize;
54    tr_file_index_t       * notWant;
55    tr_file_index_t         notWantSize;
56    tr_file_index_t       * low;
57    tr_file_index_t         lowSize;
58    tr_file_index_t       * normal;
59    tr_file_index_t         normalSize;
60    tr_file_index_t       * high;
61    tr_file_index_t         highSize;
62};
63
64/***
65****
66***/
67
68static void
69setSourceFile( tr_ctor *    ctor,
70               const char * sourceFile )
71{
72    tr_free( ctor->sourceFile );
73    ctor->sourceFile = tr_strdup( sourceFile );
74}
75
76static void
77clearMetainfo( tr_ctor * ctor )
78{
79    if( ctor->isSet_metainfo )
80    {
81        ctor->isSet_metainfo = 0;
82        tr_bencFree( &ctor->metainfo );
83    }
84
85    setSourceFile( ctor, NULL );
86}
87
88int
89tr_ctorSetMetainfo( tr_ctor *       ctor,
90                    const uint8_t * metainfo,
91                    size_t          len )
92{
93    int err;
94
95    clearMetainfo( ctor );
96    err = tr_bencLoad( metainfo, len, &ctor->metainfo, NULL );
97    ctor->isSet_metainfo = !err;
98    return err;
99}
100
101const char*
102tr_ctorGetSourceFile( const tr_ctor * ctor )
103{
104    return ctor->sourceFile;
105}
106
107int
108tr_ctorSetMetainfoFromMagnetLink( tr_ctor * ctor, const char * magnet_link )
109{
110    int err;
111    tr_magnet_info * magnet_info = tr_magnetParse( magnet_link );
112
113    if( magnet_info == NULL )
114        err = -1;
115    else {
116        int len;
117        tr_benc tmp;
118        char * str;
119
120        tr_magnetCreateMetainfo( magnet_info, &tmp );
121        str = tr_bencToStr( &tmp, TR_FMT_BENC, &len );
122        err = tr_ctorSetMetainfo( ctor, (const uint8_t*)str, len );
123
124        tr_free( str );
125        tr_magnetFree( magnet_info );
126    }
127
128    return err;
129}
130
131int
132tr_ctorSetMetainfoFromFile( tr_ctor *    ctor,
133                            const char * filename )
134{
135    uint8_t * metainfo;
136    size_t    len;
137    int       err;
138
139    metainfo = tr_loadFile( filename, &len );
140    if( metainfo && len )
141        err = tr_ctorSetMetainfo( ctor, metainfo, len );
142    else
143    {
144        clearMetainfo( ctor );
145        err = 1;
146    }
147
148    setSourceFile( ctor, filename );
149
150    /* if no `name' field was set, then set it from the filename */
151    if( ctor->isSet_metainfo )
152    {
153        tr_benc * info;
154        if( tr_bencDictFindDict( &ctor->metainfo, "info", &info ) )
155        {
156            const char * name;
157            if( !tr_bencDictFindStr( info, "name.utf-8", &name ) )
158                if( !tr_bencDictFindStr( info, "name", &name ) )
159                    name = NULL;
160            if( !name || !*name )
161            {
162                char * base = tr_basename( filename );
163                tr_bencDictAddStr( info, "name", base );
164                tr_free( base );
165            }
166        }
167    }
168
169    tr_free( metainfo );
170    return err;
171}
172
173int
174tr_ctorSetMetainfoFromHash( tr_ctor *    ctor,
175                            const char * hashString )
176{
177    int          err;
178    const char * filename;
179
180    filename = tr_sessionFindTorrentFile( ctor->session, hashString );
181    if( !filename )
182        err = EINVAL;
183    else
184        err = tr_ctorSetMetainfoFromFile( ctor, filename );
185
186    return err;
187}
188
189/***
190****
191***/
192
193void
194tr_ctorSetFilePriorities( tr_ctor                * ctor,
195                          const tr_file_index_t  * files,
196                          tr_file_index_t          fileCount,
197                          tr_priority_t            priority )
198{
199    tr_file_index_t ** myfiles;
200    tr_file_index_t * mycount;
201
202    switch( priority ) {
203        case TR_PRI_LOW: myfiles = &ctor->low; mycount = &ctor->lowSize; break;
204        case TR_PRI_HIGH: myfiles = &ctor->high; mycount = &ctor->highSize; break;
205        default /*TR_PRI_NORMAL*/: myfiles = &ctor->normal; mycount = &ctor->normalSize; break;
206    }
207
208    tr_free( *myfiles );
209    *myfiles = tr_memdup( files, sizeof(tr_file_index_t)*fileCount );
210    *mycount = fileCount;
211}
212
213void
214tr_ctorInitTorrentPriorities( const tr_ctor * ctor, tr_torrent * tor )
215{
216    tr_file_index_t i;
217
218    for( i=0; i<ctor->lowSize; ++i )
219        tr_torrentInitFilePriority( tor, ctor->low[i], TR_PRI_LOW );
220    for( i=0; i<ctor->normalSize; ++i )
221        tr_torrentInitFilePriority( tor, ctor->normal[i], TR_PRI_NORMAL );
222    for( i=0; i<ctor->highSize; ++i )
223        tr_torrentInitFilePriority( tor, ctor->high[i], TR_PRI_HIGH );
224}
225
226void
227tr_ctorSetFilesWanted( tr_ctor                * ctor,
228                       const tr_file_index_t  * files,
229                       tr_file_index_t          fileCount,
230                       tr_bool                  wanted )
231{
232    tr_file_index_t ** myfiles = wanted ? &ctor->want : &ctor->notWant;
233    tr_file_index_t * mycount = wanted ? &ctor->wantSize : &ctor->notWantSize;
234
235    tr_free( *myfiles );
236    *myfiles = tr_memdup( files, sizeof(tr_file_index_t)*fileCount );
237    *mycount = fileCount;
238}
239
240void
241tr_ctorInitTorrentWanted( const tr_ctor * ctor, tr_torrent * tor )
242{
243    if( ctor->notWantSize )
244        tr_torrentInitFileDLs( tor, ctor->notWant, ctor->notWantSize, FALSE );
245    if( ctor->wantSize )
246        tr_torrentInitFileDLs( tor, ctor->want, ctor->wantSize, TRUE );
247}
248
249/***
250****
251***/
252
253void
254tr_ctorSetDeleteSource( tr_ctor * ctor,
255                        tr_bool   deleteSource )
256{
257    ctor->doDelete = deleteSource != 0;
258    ctor->isSet_delete = 1;
259}
260
261int
262tr_ctorGetDeleteSource( const tr_ctor * ctor,
263                        uint8_t *       setme )
264{
265    int err = 0;
266
267    if( !ctor->isSet_delete )
268        err = 1;
269    else if( setme )
270        *setme = ctor->doDelete ? 1 : 0;
271
272    return err;
273}
274
275/***
276****
277***/
278
279void
280tr_ctorSetSave( tr_ctor * ctor,
281                tr_bool   saveInOurTorrentsDir )
282{
283    ctor->saveInOurTorrentsDir = saveInOurTorrentsDir != 0;
284}
285
286int
287tr_ctorGetSave( const tr_ctor * ctor )
288{
289    return ctor && ctor->saveInOurTorrentsDir;
290}
291
292void
293tr_ctorSetPaused( tr_ctor *   ctor,
294                  tr_ctorMode mode,
295                  tr_bool     isPaused )
296{
297    struct optional_args * args = &ctor->optionalArgs[mode];
298
299    args->isSet_paused = 1;
300    args->isPaused = isPaused ? 1 : 0;
301}
302
303void
304tr_ctorSetPeerLimit( tr_ctor *   ctor,
305                     tr_ctorMode mode,
306                     uint16_t    peerLimit )
307{
308    struct optional_args * args = &ctor->optionalArgs[mode];
309
310    args->isSet_connected = 1;
311    args->peerLimit = peerLimit;
312}
313
314void
315tr_ctorSetDownloadDir( tr_ctor *    ctor,
316                       tr_ctorMode  mode,
317                       const char * directory )
318{
319    struct optional_args * args = &ctor->optionalArgs[mode];
320
321    tr_free( args->downloadDir );
322    args->downloadDir = NULL;
323    args->isSet_downloadDir = 0;
324
325    if( directory && *directory )
326    {
327        args->isSet_downloadDir = 1;
328        args->downloadDir = tr_strdup( directory );
329    }
330}
331
332void
333tr_ctorSetIncompleteDir( tr_ctor * ctor, const char * directory )
334{
335    tr_free( ctor->incompleteDir );
336    ctor->incompleteDir = tr_strdup( directory );
337}
338
339int
340tr_ctorGetPeerLimit( const tr_ctor * ctor,
341                     tr_ctorMode     mode,
342                     uint16_t *      setmeCount )
343{
344    int err = 0;
345    const struct optional_args * args = &ctor->optionalArgs[mode];
346
347    if( !args->isSet_connected )
348        err = 1;
349    else if( setmeCount )
350        *setmeCount = args->peerLimit;
351
352    return err;
353}
354
355int
356tr_ctorGetPaused( const tr_ctor * ctor,
357                  tr_ctorMode     mode,
358                  uint8_t *       setmeIsPaused )
359{
360    int                          err = 0;
361    const struct optional_args * args = &ctor->optionalArgs[mode];
362
363    if( !args->isSet_paused )
364        err = 1;
365    else if( setmeIsPaused )
366        *setmeIsPaused = args->isPaused ? 1 : 0;
367
368    return err;
369}
370
371int
372tr_ctorGetDownloadDir( const tr_ctor * ctor,
373                       tr_ctorMode     mode,
374                       const char **   setmeDownloadDir )
375{
376    int                          err = 0;
377    const struct optional_args * args = &ctor->optionalArgs[mode];
378
379    if( !args->isSet_downloadDir )
380        err = 1;
381    else if( setmeDownloadDir )
382        *setmeDownloadDir = args->downloadDir;
383
384    return err;
385}
386
387int
388tr_ctorGetIncompleteDir( const tr_ctor  * ctor,
389                         const char    ** setmeIncompleteDir )
390{
391    int err = 0;
392
393    if( ctor->incompleteDir == NULL )
394        err = 1;
395    else
396        *setmeIncompleteDir = ctor->incompleteDir;
397
398    return err;
399}
400
401int
402tr_ctorGetMetainfo( const tr_ctor *  ctor,
403                    const tr_benc ** setme )
404{
405    int err = 0;
406
407    if( !ctor->isSet_metainfo )
408        err = 1;
409    else if( setme )
410        *setme = &ctor->metainfo;
411
412    return err;
413}
414
415tr_session*
416tr_ctorGetSession( const tr_ctor * ctor )
417{
418    return (tr_session*) ctor->session;
419}
420
421/***
422****
423***/
424
425static tr_bool
426isPriority( int i )
427{
428    return (i==TR_PRI_LOW) || (i==TR_PRI_NORMAL) || (i==TR_PRI_HIGH);
429}
430
431void
432tr_ctorSetBandwidthPriority( tr_ctor * ctor, tr_priority_t priority )
433{
434    if( isPriority( priority ) )
435        ctor->bandwidthPriority = priority;
436}
437
438tr_priority_t
439tr_ctorGetBandwidthPriority( const tr_ctor * ctor )
440{
441    return ctor->bandwidthPriority;
442}
443
444/***
445****
446***/
447
448tr_ctor*
449tr_ctorNew( const tr_session * session )
450{
451    tr_ctor * ctor = tr_new0( struct tr_ctor, 1 );
452
453    ctor->session = session;
454    ctor->bandwidthPriority = TR_PRI_NORMAL;
455    if( session != NULL )
456    {
457        tr_ctorSetDeleteSource( ctor, tr_sessionGetDeleteSource( session ) );
458        tr_ctorSetPaused( ctor, TR_FALLBACK, tr_sessionGetPaused( session ) );
459        tr_ctorSetPeerLimit( ctor, TR_FALLBACK, session->peerLimitPerTorrent );
460        tr_ctorSetDownloadDir( ctor, TR_FALLBACK, session->downloadDir );
461    }
462    tr_ctorSetSave( ctor, TRUE );
463    return ctor;
464}
465
466void
467tr_ctorFree( tr_ctor * ctor )
468{
469    clearMetainfo( ctor );
470    tr_free( ctor->optionalArgs[1].downloadDir );
471    tr_free( ctor->optionalArgs[0].downloadDir );
472    tr_free( ctor->incompleteDir );
473    tr_free( ctor->want );
474    tr_free( ctor->notWant );
475    tr_free( ctor->low );
476    tr_free( ctor->high );
477    tr_free( ctor->normal );
478    tr_free( ctor );
479}
Note: See TracBrowser for help on using the repository browser.