• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/ap/gpl/transmission/transmission-2.73/libtransmission/
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 12234 2011-03-25 17:42:47Z jordan $
11 */
12
13#include <errno.h> /* EINVAL */
14#include "transmission.h"
15#include "bencode.h"
16#include "magnet.h"
17#include "session.h" /* tr_sessionFindTorrentFile() */
18#include "torrent.h" /* tr_ctorGetSave() */
19#include "utils.h" /* tr_new0 */
20
21struct optional_args
22{
23    bool            isSet_paused;
24    bool            isSet_connected;
25    bool            isSet_downloadDir;
26
27    bool            isPaused;
28    uint16_t        peerLimit;
29    char          * downloadDir;
30};
31
32/** Opaque class used when instantiating torrents.
33 * @ingroup tr_ctor */
34struct tr_ctor
35{
36    const tr_session *      session;
37    bool                    saveInOurTorrentsDir;
38    bool                    doDelete;
39
40    tr_priority_t           bandwidthPriority;
41    bool                    isSet_metainfo;
42    bool                    isSet_delete;
43    tr_benc                 metainfo;
44    char *                  sourceFile;
45
46    struct optional_args    optionalArgs[2];
47
48    char                  * cookies;
49    char                  * incompleteDir;
50
51    tr_file_index_t       * want;
52    tr_file_index_t         wantSize;
53    tr_file_index_t       * notWant;
54    tr_file_index_t         notWantSize;
55    tr_file_index_t       * low;
56    tr_file_index_t         lowSize;
57    tr_file_index_t       * normal;
58    tr_file_index_t         normalSize;
59    tr_file_index_t       * high;
60    tr_file_index_t         highSize;
61};
62
63/***
64****
65***/
66
67static void
68setSourceFile( tr_ctor *    ctor,
69               const char * sourceFile )
70{
71    tr_free( ctor->sourceFile );
72    ctor->sourceFile = tr_strdup( sourceFile );
73}
74
75static void
76clearMetainfo( tr_ctor * ctor )
77{
78    if( ctor->isSet_metainfo )
79    {
80        ctor->isSet_metainfo = 0;
81        tr_bencFree( &ctor->metainfo );
82    }
83
84    setSourceFile( ctor, NULL );
85}
86
87int
88tr_ctorSetMetainfo( tr_ctor *       ctor,
89                    const uint8_t * metainfo,
90                    size_t          len )
91{
92    int err;
93
94    clearMetainfo( ctor );
95    err = tr_bencLoad( metainfo, len, &ctor->metainfo, NULL );
96    ctor->isSet_metainfo = !err;
97    return err;
98}
99
100const char*
101tr_ctorGetSourceFile( const tr_ctor * ctor )
102{
103    return ctor->sourceFile;
104}
105
106int
107tr_ctorSetMetainfoFromMagnetLink( tr_ctor * ctor, const char * magnet_link )
108{
109    int err;
110    tr_magnet_info * magnet_info = tr_magnetParse( magnet_link );
111
112    if( magnet_info == NULL )
113        err = -1;
114    else {
115        int len;
116        tr_benc tmp;
117        char * str;
118
119        tr_magnetCreateMetainfo( magnet_info, &tmp );
120        str = tr_bencToStr( &tmp, TR_FMT_BENC, &len );
121        err = tr_ctorSetMetainfo( ctor, (const uint8_t*)str, len );
122
123        tr_free( str );
124        tr_bencFree( &tmp );
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                       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, bool deleteSource )
255{
256    ctor->doDelete = deleteSource != 0;
257    ctor->isSet_delete = 1;
258}
259
260int
261tr_ctorGetDeleteSource( const tr_ctor * ctor, bool * setme )
262{
263    int err = 0;
264
265    if( !ctor->isSet_delete )
266        err = 1;
267    else if( setme )
268        *setme = ctor->doDelete ? 1 : 0;
269
270    return err;
271}
272
273/***
274****
275***/
276
277void
278tr_ctorSetSave( tr_ctor * ctor, bool saveInOurTorrentsDir )
279{
280    ctor->saveInOurTorrentsDir = saveInOurTorrentsDir != 0;
281}
282
283int
284tr_ctorGetSave( const tr_ctor * ctor )
285{
286    return ctor && ctor->saveInOurTorrentsDir;
287}
288
289void
290tr_ctorSetPaused( tr_ctor *   ctor,
291                  tr_ctorMode mode,
292                  bool        isPaused )
293{
294    struct optional_args * args = &ctor->optionalArgs[mode];
295
296    args->isSet_paused = 1;
297    args->isPaused = isPaused ? 1 : 0;
298}
299
300void
301tr_ctorSetPeerLimit( tr_ctor *   ctor,
302                     tr_ctorMode mode,
303                     uint16_t    peerLimit )
304{
305    struct optional_args * args = &ctor->optionalArgs[mode];
306
307    args->isSet_connected = 1;
308    args->peerLimit = peerLimit;
309}
310
311void
312tr_ctorSetDownloadDir( tr_ctor *    ctor,
313                       tr_ctorMode  mode,
314                       const char * directory )
315{
316    struct optional_args * args = &ctor->optionalArgs[mode];
317
318    tr_free( args->downloadDir );
319    args->downloadDir = NULL;
320    args->isSet_downloadDir = 0;
321
322    if( directory && *directory )
323    {
324        args->isSet_downloadDir = 1;
325        args->downloadDir = tr_strdup( directory );
326    }
327}
328
329void
330tr_ctorSetIncompleteDir( tr_ctor * ctor, const char * directory )
331{
332    tr_free( ctor->incompleteDir );
333    ctor->incompleteDir = tr_strdup( directory );
334}
335
336int
337tr_ctorGetPeerLimit( const tr_ctor * ctor,
338                     tr_ctorMode     mode,
339                     uint16_t *      setmeCount )
340{
341    int err = 0;
342    const struct optional_args * args = &ctor->optionalArgs[mode];
343
344    if( !args->isSet_connected )
345        err = 1;
346    else if( setmeCount )
347        *setmeCount = args->peerLimit;
348
349    return err;
350}
351
352int
353tr_ctorGetPaused( const tr_ctor * ctor, tr_ctorMode mode, bool * setmeIsPaused )
354{
355    int                          err = 0;
356    const struct optional_args * args = &ctor->optionalArgs[mode];
357
358    if( !args->isSet_paused )
359        err = 1;
360    else if( setmeIsPaused )
361        *setmeIsPaused = args->isPaused ? 1 : 0;
362
363    return err;
364}
365
366int
367tr_ctorGetDownloadDir( const tr_ctor * ctor,
368                       tr_ctorMode     mode,
369                       const char **   setmeDownloadDir )
370{
371    int                          err = 0;
372    const struct optional_args * args = &ctor->optionalArgs[mode];
373
374    if( !args->isSet_downloadDir )
375        err = 1;
376    else if( setmeDownloadDir )
377        *setmeDownloadDir = args->downloadDir;
378
379    return err;
380}
381
382int
383tr_ctorGetIncompleteDir( const tr_ctor  * ctor,
384                         const char    ** setmeIncompleteDir )
385{
386    int err = 0;
387
388    if( ctor->incompleteDir == NULL )
389        err = 1;
390    else
391        *setmeIncompleteDir = ctor->incompleteDir;
392
393    return err;
394}
395
396int
397tr_ctorGetMetainfo( const tr_ctor *  ctor,
398                    const tr_benc ** setme )
399{
400    int err = 0;
401
402    if( !ctor->isSet_metainfo )
403        err = 1;
404    else if( setme )
405        *setme = &ctor->metainfo;
406
407    return err;
408}
409
410tr_session*
411tr_ctorGetSession( const tr_ctor * ctor )
412{
413    return (tr_session*) ctor->session;
414}
415
416/***
417****
418***/
419
420static bool
421isPriority( int i )
422{
423    return (i==TR_PRI_LOW) || (i==TR_PRI_NORMAL) || (i==TR_PRI_HIGH);
424}
425
426void
427tr_ctorSetBandwidthPriority( tr_ctor * ctor, tr_priority_t priority )
428{
429    if( isPriority( priority ) )
430        ctor->bandwidthPriority = priority;
431}
432
433tr_priority_t
434tr_ctorGetBandwidthPriority( const tr_ctor * ctor )
435{
436    return ctor->bandwidthPriority;
437}
438
439/***
440****
441***/
442
443tr_ctor*
444tr_ctorNew( const tr_session * session )
445{
446    tr_ctor * ctor = tr_new0( struct tr_ctor, 1 );
447
448    ctor->session = session;
449    ctor->bandwidthPriority = TR_PRI_NORMAL;
450    if( session != NULL )
451    {
452        tr_ctorSetDeleteSource( ctor, tr_sessionGetDeleteSource( session ) );
453        tr_ctorSetPaused( ctor, TR_FALLBACK, tr_sessionGetPaused( session ) );
454        tr_ctorSetPeerLimit( ctor, TR_FALLBACK, session->peerLimitPerTorrent );
455        tr_ctorSetDownloadDir( ctor, TR_FALLBACK, session->downloadDir );
456    }
457    tr_ctorSetSave( ctor, true );
458    return ctor;
459}
460
461void
462tr_ctorFree( tr_ctor * ctor )
463{
464    clearMetainfo( ctor );
465    tr_free( ctor->optionalArgs[1].downloadDir );
466    tr_free( ctor->optionalArgs[0].downloadDir );
467    tr_free( ctor->incompleteDir );
468    tr_free( ctor->want );
469    tr_free( ctor->notWant );
470    tr_free( ctor->low );
471    tr_free( ctor->high );
472    tr_free( ctor->normal );
473    tr_free( ctor );
474}
475