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

Last change on this file since 14532 was 14532, checked in by mikedld, 6 years ago

Add more booleans to the picture

  • Property svn:keywords set to Date Rev Author Id
File size: 11.2 KB
Line 
1/*
2 * This file Copyright (C) 2009-2014 Mnemosyne LLC
3 *
4 * It may be used under the GNU GPL versions 2 or 3
5 * or any future license endorsed by Mnemosyne LLC.
6 *
7 * $Id: torrent-ctor.c 14532 2015-05-31 22:13:31Z mikedld $
8 */
9
10#include <errno.h> /* EINVAL */
11
12#include "transmission.h"
13#include "file.h"
14#include "magnet.h"
15#include "session.h" /* tr_sessionFindTorrentFile () */
16#include "torrent.h" /* tr_ctorGetSave () */
17#include "utils.h" /* tr_new0 */
18#include "variant.h"
19
20struct optional_args
21{
22    bool            isSet_paused;
23    bool            isSet_connected;
24    bool            isSet_downloadDir;
25
26    bool            isPaused;
27    uint16_t        peerLimit;
28    char          * downloadDir;
29};
30
31/** Opaque class used when instantiating torrents.
32 * @ingroup tr_ctor */
33struct tr_ctor
34{
35    const tr_session *      session;
36    bool                    saveInOurTorrentsDir;
37    bool                    doDelete;
38
39    tr_priority_t           bandwidthPriority;
40    bool                    isSet_metainfo;
41    bool                    isSet_delete;
42    tr_variant              metainfo;
43    char *                  sourceFile;
44
45    struct optional_args    optionalArgs[2];
46
47    char                  * cookies;
48    char                  * incompleteDir;
49
50    tr_file_index_t       * want;
51    tr_file_index_t         wantSize;
52    tr_file_index_t       * notWant;
53    tr_file_index_t         notWantSize;
54    tr_file_index_t       * low;
55    tr_file_index_t         lowSize;
56    tr_file_index_t       * normal;
57    tr_file_index_t         normalSize;
58    tr_file_index_t       * high;
59    tr_file_index_t         highSize;
60};
61
62/***
63****
64***/
65
66static void
67setSourceFile (tr_ctor *    ctor,
68               const char * sourceFile)
69{
70    tr_free (ctor->sourceFile);
71    ctor->sourceFile = tr_strdup (sourceFile);
72}
73
74static void
75clearMetainfo (tr_ctor * ctor)
76{
77    if (ctor->isSet_metainfo)
78    {
79        ctor->isSet_metainfo = false;
80        tr_variantFree (&ctor->metainfo);
81    }
82
83    setSourceFile (ctor, NULL);
84}
85
86int
87tr_ctorSetMetainfo (tr_ctor *       ctor,
88                    const uint8_t * metainfo,
89                    size_t          len)
90{
91    int err;
92
93    clearMetainfo (ctor);
94    err = tr_variantFromBenc (&ctor->metainfo, metainfo, len);
95    ctor->isSet_metainfo = !err;
96    return err;
97}
98
99const char*
100tr_ctorGetSourceFile (const tr_ctor * ctor)
101{
102    return ctor->sourceFile;
103}
104
105int
106tr_ctorSetMetainfoFromMagnetLink (tr_ctor * ctor, const char * magnet_link)
107{
108    int err;
109    tr_magnet_info * magnet_info = tr_magnetParse (magnet_link);
110
111    if (magnet_info == NULL)
112        err = -1;
113    else {
114        int len;
115        tr_variant tmp;
116        char * str;
117
118        tr_magnetCreateMetainfo (magnet_info, &tmp);
119        str = tr_variantToStr (&tmp, TR_VARIANT_FMT_BENC, &len);
120        err = tr_ctorSetMetainfo (ctor, (const uint8_t*)str, len);
121
122        tr_free (str);
123        tr_variantFree (&tmp);
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, NULL);
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_variant * info;
153        if (tr_variantDictFindDict (&ctor->metainfo, TR_KEY_info, &info))
154        {
155            const char * name;
156            if (!tr_variantDictFindStr (info, TR_KEY_name_utf_8, &name, NULL))
157                if (!tr_variantDictFindStr (info, TR_KEY_name, &name, NULL))
158                    name = NULL;
159            if (!name || !*name)
160            {
161                char * base = tr_sys_path_basename (filename, NULL);
162                tr_variantDictAddStr (info, TR_KEY_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                       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, bool deleteSource)
254{
255    assert (tr_isBool (deleteSource));
256
257    ctor->doDelete = deleteSource;
258    ctor->isSet_delete = true;
259}
260
261bool
262tr_ctorGetDeleteSource (const tr_ctor * ctor, bool * setme)
263{
264    bool ret = true;
265
266    if (!ctor->isSet_delete)
267        ret = false;
268    else if (setme)
269        *setme = ctor->doDelete;
270
271    return ret;
272}
273
274/***
275****
276***/
277
278void
279tr_ctorSetSave (tr_ctor * ctor, bool saveInOurTorrentsDir)
280{
281    assert (tr_isBool (saveInOurTorrentsDir));
282
283    ctor->saveInOurTorrentsDir = saveInOurTorrentsDir;
284}
285
286bool
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                  bool        isPaused)
296{
297    struct optional_args * args;
298
299    assert (ctor != NULL);
300    assert ((mode == TR_FALLBACK) || (mode == TR_FORCE));
301    assert (tr_isBool (isPaused));
302
303    args = &ctor->optionalArgs[mode];
304    args->isSet_paused = true;
305    args->isPaused = isPaused;
306}
307
308void
309tr_ctorSetPeerLimit (tr_ctor *   ctor,
310                     tr_ctorMode mode,
311                     uint16_t    peerLimit)
312{
313    struct optional_args * args;
314
315    assert (ctor != NULL);
316    assert ((mode == TR_FALLBACK) || (mode == TR_FORCE));
317
318    args = &ctor->optionalArgs[mode];
319    args->isSet_connected = true;
320    args->peerLimit = peerLimit;
321}
322
323void
324tr_ctorSetDownloadDir (tr_ctor *    ctor,
325                       tr_ctorMode  mode,
326                       const char * directory)
327{
328    struct optional_args * args;
329
330    assert (ctor != NULL);
331    assert ((mode == TR_FALLBACK) || (mode == TR_FORCE));
332
333    args = &ctor->optionalArgs[mode];
334    tr_free (args->downloadDir);
335    args->downloadDir = NULL;
336    args->isSet_downloadDir = false;
337
338    if (directory && *directory)
339    {
340        args->isSet_downloadDir = true;
341        args->downloadDir = tr_strdup (directory);
342    }
343}
344
345void
346tr_ctorSetIncompleteDir (tr_ctor * ctor, const char * directory)
347{
348    tr_free (ctor->incompleteDir);
349    ctor->incompleteDir = tr_strdup (directory);
350}
351
352bool
353tr_ctorGetPeerLimit (const tr_ctor * ctor,
354                     tr_ctorMode     mode,
355                     uint16_t *      setmeCount)
356{
357    bool ret = true;
358    const struct optional_args * args = &ctor->optionalArgs[mode];
359
360    if (!args->isSet_connected)
361        ret = false;
362    else if (setmeCount)
363        *setmeCount = args->peerLimit;
364
365    return ret;
366}
367
368bool
369tr_ctorGetPaused (const tr_ctor * ctor, tr_ctorMode mode, bool * setmeIsPaused)
370{
371    bool ret = true;
372    const struct optional_args * args = &ctor->optionalArgs[mode];
373
374    if (!args->isSet_paused)
375        ret = false;
376    else if (setmeIsPaused)
377        *setmeIsPaused = args->isPaused;
378
379    return ret;
380}
381
382bool
383tr_ctorGetDownloadDir (const tr_ctor * ctor,
384                       tr_ctorMode     mode,
385                       const char **   setmeDownloadDir)
386{
387    bool ret = true;
388    const struct optional_args * args = &ctor->optionalArgs[mode];
389
390    if (!args->isSet_downloadDir)
391        ret = false;
392    else if (setmeDownloadDir)
393        *setmeDownloadDir = args->downloadDir;
394
395    return ret;
396}
397
398bool
399tr_ctorGetIncompleteDir (const tr_ctor  * ctor,
400                         const char    ** setmeIncompleteDir)
401{
402    bool ret = true;
403
404    if (ctor->incompleteDir == NULL)
405        ret = false;
406    else
407        *setmeIncompleteDir = ctor->incompleteDir;
408
409    return ret;
410}
411
412bool
413tr_ctorGetMetainfo (const tr_ctor *  ctor,
414                    const tr_variant ** setme)
415{
416    bool ret = true;
417
418    if (!ctor->isSet_metainfo)
419        ret = false;
420    else if (setme)
421        *setme = &ctor->metainfo;
422
423    return ret;
424}
425
426tr_session*
427tr_ctorGetSession (const tr_ctor * ctor)
428{
429    return (tr_session*) ctor->session;
430}
431
432/***
433****
434***/
435
436static bool
437isPriority (int i)
438{
439    return (i==TR_PRI_LOW) || (i==TR_PRI_NORMAL) || (i==TR_PRI_HIGH);
440}
441
442void
443tr_ctorSetBandwidthPriority (tr_ctor * ctor, tr_priority_t priority)
444{
445    if (isPriority (priority))
446        ctor->bandwidthPriority = priority;
447}
448
449tr_priority_t
450tr_ctorGetBandwidthPriority (const tr_ctor * ctor)
451{
452    return ctor->bandwidthPriority;
453}
454
455/***
456****
457***/
458
459tr_ctor*
460tr_ctorNew (const tr_session * session)
461{
462    tr_ctor * ctor = tr_new0 (struct tr_ctor, 1);
463
464    ctor->session = session;
465    ctor->bandwidthPriority = TR_PRI_NORMAL;
466    if (session != NULL)
467    {
468        tr_ctorSetDeleteSource (ctor, tr_sessionGetDeleteSource (session));
469        tr_ctorSetPaused (ctor, TR_FALLBACK, tr_sessionGetPaused (session));
470        tr_ctorSetPeerLimit (ctor, TR_FALLBACK, session->peerLimitPerTorrent);
471        tr_ctorSetDownloadDir (ctor, TR_FALLBACK, tr_sessionGetDownloadDir(session));
472    }
473    tr_ctorSetSave (ctor, true);
474    return ctor;
475}
476
477void
478tr_ctorFree (tr_ctor * ctor)
479{
480    clearMetainfo (ctor);
481    tr_free (ctor->optionalArgs[1].downloadDir);
482    tr_free (ctor->optionalArgs[0].downloadDir);
483    tr_free (ctor->incompleteDir);
484    tr_free (ctor->want);
485    tr_free (ctor->notWant);
486    tr_free (ctor->low);
487    tr_free (ctor->high);
488    tr_free (ctor->normal);
489    tr_free (ctor);
490}
Note: See TracBrowser for help on using the repository browser.