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

Last change on this file since 11599 was 11599, checked in by charles, 11 years ago

(trunk) Join the 21st century and use only 1 space at the end sentences. This commit is nearly as important as the semi-annual ones that remove trailing spaces from the ends of lines of code... :)

  • Property svn:keywords set to Date Rev Author Id
File size: 11.1 KB
Line 
1/*
2 * This file Copyright (C) 2007-2010 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 11599 2010-12-27 19:18:17Z charles $
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                  * 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_magnetFree( magnet_info );
125    }
126
127    return err;
128}
129
130int
131tr_ctorSetMetainfoFromFile( tr_ctor *    ctor,
132                            const char * filename )
133{
134    uint8_t * metainfo;
135    size_t    len;
136    int       err;
137
138    metainfo = tr_loadFile( filename, &len );
139    if( metainfo && len )
140        err = tr_ctorSetMetainfo( ctor, metainfo, len );
141    else
142    {
143        clearMetainfo( ctor );
144        err = 1;
145    }
146
147    setSourceFile( ctor, filename );
148
149    /* if no `name' field was set, then set it from the filename */
150    if( ctor->isSet_metainfo )
151    {
152        tr_benc * info;
153        if( tr_bencDictFindDict( &ctor->metainfo, "info", &info ) )
154        {
155            const char * name;
156            if( !tr_bencDictFindStr( info, "name.utf-8", &name ) )
157                if( !tr_bencDictFindStr( info, "name", &name ) )
158                    name = NULL;
159            if( !name || !*name )
160            {
161                char * base = tr_basename( filename );
162                tr_bencDictAddStr( info, "name", base );
163                tr_free( base );
164            }
165        }
166    }
167
168    tr_free( metainfo );
169    return err;
170}
171
172int
173tr_ctorSetMetainfoFromHash( tr_ctor *    ctor,
174                            const char * hashString )
175{
176    int          err;
177    const char * filename;
178
179    filename = tr_sessionFindTorrentFile( ctor->session, hashString );
180    if( !filename )
181        err = EINVAL;
182    else
183        err = tr_ctorSetMetainfoFromFile( ctor, filename );
184
185    return err;
186}
187
188/***
189****
190***/
191
192void
193tr_ctorSetFilePriorities( tr_ctor                * ctor,
194                          const tr_file_index_t  * files,
195                          tr_file_index_t          fileCount,
196                          tr_priority_t            priority )
197{
198    tr_file_index_t ** myfiles;
199    tr_file_index_t * mycount;
200
201    switch( priority ) {
202        case TR_PRI_LOW: myfiles = &ctor->low; mycount = &ctor->lowSize; break;
203        case TR_PRI_HIGH: myfiles = &ctor->high; mycount = &ctor->highSize; break;
204        default /*TR_PRI_NORMAL*/: myfiles = &ctor->normal; mycount = &ctor->normalSize; break;
205    }
206
207    tr_free( *myfiles );
208    *myfiles = tr_memdup( files, sizeof(tr_file_index_t)*fileCount );
209    *mycount = fileCount;
210}
211
212void
213tr_ctorInitTorrentPriorities( const tr_ctor * ctor, tr_torrent * tor )
214{
215    tr_file_index_t i;
216
217    for( i=0; i<ctor->lowSize; ++i )
218        tr_torrentInitFilePriority( tor, ctor->low[i], TR_PRI_LOW );
219    for( i=0; i<ctor->normalSize; ++i )
220        tr_torrentInitFilePriority( tor, ctor->normal[i], TR_PRI_NORMAL );
221    for( i=0; i<ctor->highSize; ++i )
222        tr_torrentInitFilePriority( tor, ctor->high[i], TR_PRI_HIGH );
223}
224
225void
226tr_ctorSetFilesWanted( tr_ctor                * ctor,
227                       const tr_file_index_t  * files,
228                       tr_file_index_t          fileCount,
229                       tr_bool                  wanted )
230{
231    tr_file_index_t ** myfiles = wanted ? &ctor->want : &ctor->notWant;
232    tr_file_index_t * mycount = wanted ? &ctor->wantSize : &ctor->notWantSize;
233
234    tr_free( *myfiles );
235    *myfiles = tr_memdup( files, sizeof(tr_file_index_t)*fileCount );
236    *mycount = fileCount;
237}
238
239void
240tr_ctorInitTorrentWanted( const tr_ctor * ctor, tr_torrent * tor )
241{
242    if( ctor->notWantSize )
243        tr_torrentInitFileDLs( tor, ctor->notWant, ctor->notWantSize, FALSE );
244    if( ctor->wantSize )
245        tr_torrentInitFileDLs( tor, ctor->want, ctor->wantSize, TRUE );
246}
247
248/***
249****
250***/
251
252void
253tr_ctorSetDeleteSource( tr_ctor * ctor,
254                        tr_bool   deleteSource )
255{
256    ctor->doDelete = deleteSource != 0;
257    ctor->isSet_delete = 1;
258}
259
260int
261tr_ctorGetDeleteSource( const tr_ctor * ctor,
262                        uint8_t *       setme )
263{
264    int err = 0;
265
266    if( !ctor->isSet_delete )
267        err = 1;
268    else if( setme )
269        *setme = ctor->doDelete ? 1 : 0;
270
271    return err;
272}
273
274/***
275****
276***/
277
278void
279tr_ctorSetSave( tr_ctor * ctor,
280                tr_bool   saveInOurTorrentsDir )
281{
282    ctor->saveInOurTorrentsDir = saveInOurTorrentsDir != 0;
283}
284
285int
286tr_ctorGetSave( const tr_ctor * ctor )
287{
288    return ctor && ctor->saveInOurTorrentsDir;
289}
290
291void
292tr_ctorSetPaused( tr_ctor *   ctor,
293                  tr_ctorMode mode,
294                  tr_bool     isPaused )
295{
296    struct optional_args * args = &ctor->optionalArgs[mode];
297
298    args->isSet_paused = 1;
299    args->isPaused = isPaused ? 1 : 0;
300}
301
302void
303tr_ctorSetPeerLimit( tr_ctor *   ctor,
304                     tr_ctorMode mode,
305                     uint16_t    peerLimit )
306{
307    struct optional_args * args = &ctor->optionalArgs[mode];
308
309    args->isSet_connected = 1;
310    args->peerLimit = peerLimit;
311}
312
313void
314tr_ctorSetDownloadDir( tr_ctor *    ctor,
315                       tr_ctorMode  mode,
316                       const char * directory )
317{
318    struct optional_args * args = &ctor->optionalArgs[mode];
319
320    tr_free( args->downloadDir );
321    args->downloadDir = NULL;
322    args->isSet_downloadDir = 0;
323
324    if( directory && *directory )
325    {
326        args->isSet_downloadDir = 1;
327        args->downloadDir = tr_strdup( directory );
328    }
329}
330
331void
332tr_ctorSetIncompleteDir( tr_ctor * ctor, const char * directory )
333{
334    tr_free( ctor->incompleteDir );
335    ctor->incompleteDir = tr_strdup( directory );
336}
337
338int
339tr_ctorGetPeerLimit( const tr_ctor * ctor,
340                     tr_ctorMode     mode,
341                     uint16_t *      setmeCount )
342{
343    int err = 0;
344    const struct optional_args * args = &ctor->optionalArgs[mode];
345
346    if( !args->isSet_connected )
347        err = 1;
348    else if( setmeCount )
349        *setmeCount = args->peerLimit;
350
351    return err;
352}
353
354int
355tr_ctorGetPaused( const tr_ctor * ctor,
356                  tr_ctorMode     mode,
357                  uint8_t *       setmeIsPaused )
358{
359    int                          err = 0;
360    const struct optional_args * args = &ctor->optionalArgs[mode];
361
362    if( !args->isSet_paused )
363        err = 1;
364    else if( setmeIsPaused )
365        *setmeIsPaused = args->isPaused ? 1 : 0;
366
367    return err;
368}
369
370int
371tr_ctorGetDownloadDir( const tr_ctor * ctor,
372                       tr_ctorMode     mode,
373                       const char **   setmeDownloadDir )
374{
375    int                          err = 0;
376    const struct optional_args * args = &ctor->optionalArgs[mode];
377
378    if( !args->isSet_downloadDir )
379        err = 1;
380    else if( setmeDownloadDir )
381        *setmeDownloadDir = args->downloadDir;
382
383    return err;
384}
385
386int
387tr_ctorGetIncompleteDir( const tr_ctor  * ctor,
388                         const char    ** setmeIncompleteDir )
389{
390    int err = 0;
391
392    if( ctor->incompleteDir == NULL )
393        err = 1;
394    else
395        *setmeIncompleteDir = ctor->incompleteDir;
396
397    return err;
398}
399
400int
401tr_ctorGetMetainfo( const tr_ctor *  ctor,
402                    const tr_benc ** setme )
403{
404    int err = 0;
405
406    if( !ctor->isSet_metainfo )
407        err = 1;
408    else if( setme )
409        *setme = &ctor->metainfo;
410
411    return err;
412}
413
414tr_session*
415tr_ctorGetSession( const tr_ctor * ctor )
416{
417    return (tr_session*) ctor->session;
418}
419
420/***
421****
422***/
423
424static tr_bool
425isPriority( int i )
426{
427    return (i==TR_PRI_LOW) || (i==TR_PRI_NORMAL) || (i==TR_PRI_HIGH);
428}
429
430void
431tr_ctorSetBandwidthPriority( tr_ctor * ctor, tr_priority_t priority )
432{
433    if( isPriority( priority ) )
434        ctor->bandwidthPriority = priority;
435}
436
437tr_priority_t
438tr_ctorGetBandwidthPriority( const tr_ctor * ctor )
439{
440    return ctor->bandwidthPriority;
441}
442
443/***
444****
445***/
446
447tr_ctor*
448tr_ctorNew( const tr_session * session )
449{
450    tr_ctor * ctor = tr_new0( struct tr_ctor, 1 );
451
452    ctor->session = session;
453    ctor->bandwidthPriority = TR_PRI_NORMAL;
454    if( session != NULL )
455    {
456        tr_ctorSetDeleteSource( ctor, tr_sessionGetDeleteSource( session ) );
457        tr_ctorSetPaused( ctor, TR_FALLBACK, tr_sessionGetPaused( session ) );
458        tr_ctorSetPeerLimit( ctor, TR_FALLBACK, session->peerLimitPerTorrent );
459        tr_ctorSetDownloadDir( ctor, TR_FALLBACK, session->downloadDir );
460    }
461    tr_ctorSetSave( ctor, TRUE );
462    return ctor;
463}
464
465void
466tr_ctorFree( tr_ctor * ctor )
467{
468    clearMetainfo( ctor );
469    tr_free( ctor->optionalArgs[1].downloadDir );
470    tr_free( ctor->optionalArgs[0].downloadDir );
471    tr_free( ctor->incompleteDir );
472    tr_free( ctor->want );
473    tr_free( ctor->notWant );
474    tr_free( ctor->low );
475    tr_free( ctor->high );
476    tr_free( ctor->normal );
477    tr_free( ctor );
478}
Note: See TracBrowser for help on using the repository browser.