File: ctorrent.cpp

package info (click to toggle)
ctorrent 1.3.4.dnh3.3.2-5
  • links: PTS
  • area: main
  • in suites: bullseye, buster, sid, stretch
  • size: 1,240 kB
  • sloc: cpp: 13,161; sh: 675; ansic: 383; makefile: 6
file content (451 lines) | stat: -rw-r--r-- 13,590 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
#include "./def.h"
#include <sys/types.h>

#ifdef WINDOWS
#include <windows.h>
#else
#include <unistd.h>
#include <signal.h>
#endif

#include <sys/time.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#include "btconfig.h"
#include "btcontent.h"
#include "downloader.h"
#include "peerlist.h"
#include "tracker.h"
#include "ctcs.h"
#include "console.h"

#include "./config.h"

#ifndef HAVE_RANDOM
#include "compat.h"
#endif

#ifndef WINDOWS
#include "sigint.h"
#endif

void usage();
int param_check(int argc, char **argv);

#ifdef WINDOWS

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrzevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
}

#else

void Random_init()
{
  unsigned long seed;
#ifdef HAVE_GETTIMEOFDAY
  struct timeval tv; 
  gettimeofday(&tv,(struct timezone*) 0);
  seed = tv.tv_usec + tv.tv_sec + getpid();
#else
  seed = (unsigned long)time((time_t *)0);
#endif
  srandom(seed);
}

int main(int argc, char **argv)
{
  char *s;

  Random_init();
  arg_user_agent = new char[MAX_PF_LEN+1];
  strcpy(arg_user_agent,PEER_PFX);

  cfg_user_agent = new char[strlen(PACKAGE_NAME)+strlen(PACKAGE_VERSION)+2];
#ifndef WINDOWS
  if( !cfg_user_agent ) return -1;
#endif
  sprintf(cfg_user_agent, "%s/%s", PACKAGE_NAME, PACKAGE_VERSION);
  while(s = strchr(cfg_user_agent, ' ')) *s = '-';

  if( argc < 2 ){
    usage();
    exit(1);
  } else if( param_check(argc,argv) < 0 ) exit(1);

  if( arg_flg_make_torrent ){
    if( !arg_announce ){
      CONSOLE.Warning(1, "Please use -u to specify an announce URL!");
      exit(1);
    }
    if( !arg_save_as ){
      CONSOLE.Warning(1, "Please use -s to specify a metainfo file name!");
      exit(1);
    }
    if( BTCONTENT.InitialFromFS(arg_metainfo_file, arg_announce,
                                arg_piece_length) < 0 ||
        BTCONTENT.CreateMetainfoFile(arg_save_as) < 0 ){
      CONSOLE.Warning(1, "create metainfo failed.");
      exit(1);
    }
    CONSOLE.Print("Create metainfo file %s successful.", arg_save_as);
    exit(0);
  }

  if( arg_daemon ) CONSOLE.Daemonize();

  if( !arg_flg_exam_only && (!arg_flg_check_only || arg_flg_force_seed_mode) )
    if( arg_ctcs ) CTCS.Initial();
  
  if( BTCONTENT.InitialFromMI(arg_metainfo_file, arg_save_as) < 0){
    CONSOLE.Warning(1, "error, initial meta info failed.");
    exit(1);
  }

  if( !arg_flg_exam_only && (!arg_flg_check_only || arg_flg_force_seed_mode) ){
    if(WORLD.Initial_ListenPort() < 0){
      CONSOLE.Warning(2, "warn, you can't accept connections.");
    }

    if( Tracker.Initial() < 0 ){
      CONSOLE.Warning(1, "error, tracker setup failed.");
      exit(1);
    }

    sig_setup();  // setup signal handling
    CONSOLE.Interact(
      "Press 'h' or '?' for help (display/control client options)." );
    Downloader();
    if( cfg_cache_size ) BTCONTENT.FlushCache();
  }
  if( !arg_flg_exam_only ) BTCONTENT.SaveBitfield();
  WORLD.CloseAll();

  if(arg_verbose) CONSOLE.cpu();
  exit(0);
}

#endif

int param_check(int argc, char **argv)
{
  const char *opts;
  int c, l;
  char *s;

  if( 0==strncmp(argv[1], "-t", 2) )
    opts = "tc:l:ps:u:";
  else opts = "aA:b:cC:dD:e:E:fi:I:M:m:n:P:p:s:S:Tu:U:vxX:z:hH";

  while( (c=getopt(argc, argv, opts)) != -1 )
    switch( c ){
    case 'a':
      arg_allocate = 1;
      break;

    case 'b':
      arg_bitfield_file = new char[strlen(optarg) + 1];
#ifndef WINDOWS
      if( !arg_bitfield_file ) return -1;
#endif
      strcpy(arg_bitfield_file, optarg);
      break;

    case 'i':			// listen on ip XXXX
      cfg_listen_ip = inet_addr(optarg);
      break;

    case 'I':			// set public ip XXXX
      cfg_public_ip = new char[strlen(optarg) + 1];
      if( !cfg_public_ip ) return -1;
      strcpy(cfg_public_ip, optarg);
      break;

    case 'p':			// listen on Port XXXX
      if( arg_flg_make_torrent ) arg_flg_private = 1;
      else cfg_listen_port = atoi(optarg);
      break;

    case 's':			// Save as FILE/DIR NAME
      if( arg_save_as ) return -1;  // specified twice
      arg_save_as = new char[strlen(optarg) + 1];
#ifndef WINDOWS
      if( !arg_save_as ) return -1;
#endif
      strcpy(arg_save_as,optarg);
      break;

    case 'e':			// Exit while complete
      cfg_seed_hours = (time_t)strtoul(optarg, NULL, 10);
      break;

    case 'E':			// target seed ratio
      cfg_seed_ratio = atof(optarg);
      break;

    case 'c':			// Check exist only
      if( arg_flg_make_torrent ){
        arg_comment = new char[strlen(optarg) + 1];
        if( !arg_comment ) return -1;
        strcpy(arg_comment, optarg);
      }else arg_flg_check_only = 1;
      break;

    case 'C':			// Max cache size
      cfg_cache_size = atoi(optarg);
      break;
      
    case 'M':			// Max peers
      cfg_max_peers = atoi(optarg);
      if( cfg_max_peers > 1000 || cfg_max_peers < 20 ){
        CONSOLE.Warning(1, "-%c argument must be between 20 and 1000", c);
        return -1;
      }
      break;
      
    case 'm':			// Min peers
      cfg_min_peers = atoi(optarg);
      if( cfg_min_peers > 1000 || cfg_min_peers < 1 ){
        CONSOLE.Warning(1, "-%c argument must be between 1 and 1000", c);
        return -1;
      }
      break;

    case 'z':			// slice size
      cfg_req_slice_size = atoi(optarg) * 1024;
      if(cfg_req_slice_size < 1024 || cfg_req_slice_size > cfg_max_slice_size){
        CONSOLE.Warning(1, "-%c argument must be between 1 and %d",
          c, cfg_max_slice_size / 1024);
        return -1;
      }
      break;

    case 'n':			// Which file download
      if( arg_file_to_download ) return -1;  // specified twice
      arg_file_to_download = new char[strlen(optarg) + 1];
#ifndef WINDOWS
      if( !arg_file_to_download ) return -1;
#endif
      strcpy(arg_file_to_download,optarg);
      break;

    case 'f':			// force seed mode, skip sha1 check when startup.
      arg_flg_force_seed_mode = 1;
      break;
      
    case 'D':			// download bandwidth limit
      cfg_max_bandwidth_down = (int)(strtod(optarg, NULL) * 1024);
      break;

    case 'U':			// upload bandwidth limit
      cfg_max_bandwidth_up = (int)(strtod(optarg, NULL) * 1024);
      break;

    case 'P':			// peer ID prefix
      l = strlen(optarg);
      if (l > MAX_PF_LEN) {
        CONSOLE.Warning(1, "-P arg must be %d or less characters", MAX_PF_LEN);
        return -1;
      }
      if (l == 1 && *optarg == '-') *arg_user_agent = (char) 0;
      else strcpy(arg_user_agent,optarg);
      break;

    case 'A':			// HTTP user-agent header string
      if( cfg_user_agent ) delete []cfg_user_agent;
      cfg_user_agent = new char[strlen(optarg) + 1];
#ifndef WINDOWS
      if( !cfg_user_agent ) return -1;
#endif
      strcpy(cfg_user_agent, optarg);
      break;

    case 'T':			// convert foreign filenames to printable text
      arg_flg_convert_filenames = 1;
      break;

     // BELOW OPTIONS USED FOR CREATE TORRENT.
    case 'u':			// Announce URL
      if( arg_announce ) return -1;  // specified twice
      arg_announce = new char[strlen(optarg) + 1];
#ifndef WINDOWS
      if( !arg_announce ) return -1;
#endif
      strcpy(arg_announce, optarg);
      break;

    case 't':			// make Torrent
      arg_flg_make_torrent = 1;
      CONSOLE.ChangeChannel(O_INPUT, "off", 0);
      break;

    case 'l':			// piece Length (default 262144)
      arg_piece_length = atoi(optarg);
      if( arg_piece_length < 65536 || arg_piece_length > 4096*1024 ){
        CONSOLE.Warning(1, "-%c argument must be between 65536 and %d",
          c, 4096*1024);
        return -1;
      }
      break;
     // ABOVE OPTIONS USED FOR CREATE TORRENT.

    case 'x':			// print torrent information only
      arg_flg_exam_only = 1;
      CONSOLE.ChangeChannel(O_INPUT, "off", 0);
      break;

    case 'S':			// CTCS server
      if( arg_ctcs ) return -1;  // specified twice
      arg_ctcs = new char[strlen(optarg) + 1];
#ifndef WINDOWS
      if( !arg_ctcs ) return -1;
#endif
      if( !strchr(optarg, ':') ){
        CONSOLE.Warning(1, "-%c argument requires a port number", c);
        return -1;
      }
      strcpy(arg_ctcs, optarg);
      break;

    case 'X':			// "user exit" on download completion
      if( arg_completion_exit ) return -1;  // specified twice
      arg_completion_exit = new char[strlen(optarg) + 1];
#ifndef WINDOWS
      if( !arg_completion_exit ) return -1;
#endif
#ifndef HAVE_SYSTEM
      CONSOLE.Warning(1, "-X is not supported on your system");
      return -1;
#endif
#ifndef HAVE_WORKING_FORK
      CONSOLE.Warning(2,
        "No working fork function; be sure the -X command is brief!");
#endif
      strcpy(arg_completion_exit, optarg);
      break;

    case 'v':			// verbose output
      arg_verbose = 1;
      break;

    case 'd':			// daemon mode (fork to background)
      arg_daemon++;
      break;

    case 'h':
    case 'H':			// help
      usage();
      return -1;

    default:
      //unknown option.
      CONSOLE.Warning(1, "Use -h for help/usage.");
      return -1;
    }

  argc -= optind; argv += optind;
  if( cfg_min_peers >= cfg_max_peers ) cfg_min_peers = cfg_max_peers - 1;
  if( argc != 1 ){
    if( arg_flg_make_torrent )
      CONSOLE.Warning(1,
        "Must specify torrent contents (one file or directory)");
    else CONSOLE.Warning(1, "Must specify one torrent file");
    return -1;
  }
  arg_metainfo_file = new char[strlen(*argv) + 1];
#ifndef WINDOWS
  if( !arg_metainfo_file ) return -1;
#endif
  strcpy(arg_metainfo_file, *argv);

  if( !arg_bitfield_file ){
    arg_bitfield_file = new char[strlen(arg_metainfo_file) + 4];
#ifndef WINDOWS
    if( !arg_bitfield_file ) return -1;
#endif
    strcpy(arg_bitfield_file, arg_metainfo_file);
    strcat(arg_bitfield_file, ".bf");
  }
  return 0;
}

void usage()
{
  CONSOLE.ChangeChannel(O_INPUT, "off", 0);
  fprintf(stderr,"%s   Original code Copyright: YuHong(992126018601033)\n",
    PACKAGE_STRING);
  fprintf(stderr,"WARNING: THERE IS NO WARRANTY FOR CTorrent. USE AT YOUR OWN RISK!!!\n");
  fprintf(stderr,"\nGeneral Options:\n");
  fprintf(stderr, "%-15s %s\n", "-h/-H", "Show this message");
  fprintf(stderr, "%-15s %s\n", "-x",
    "Decode metainfo (torrent) file only, don't download");
  fprintf(stderr, "%-15s %s\n", "-c", "Check pieces only, don't download");
  fprintf(stderr, "%-15s %s\n", "-v", "Verbose output (for debugging)");

  fprintf(stderr,"\nDownload Options:\n");
  fprintf(stderr, "%-15s %s\n", "-e int",
    "Exit while seed <int> hours later (default 72 hours)");
  fprintf(stderr, "%-15s %s\n", "-E num",
    "Exit after seeding to <num> ratio (UL:DL)");
  fprintf(stderr, "%-15s %s\n", "-i ip",
    "Listen for connections on specific IP address (default all/any)");
  fprintf(stderr, "%-15s %s\n", "-p port",
    "Listen port (default 2706 -> 2106)");
  fprintf(stderr, "%-15s %s\n", "-I ip",
    "Specify public/external IP address for peer connections");
  fprintf(stderr, "%-15s %s\n", "-u num or URL",
    "Use an alternate announce (tracker) URL");
  fprintf(stderr, "%-15s %s\n", "-s filename",
    "Download (\"save as\") to a different file or directory");
  fprintf(stderr, "%-15s %s\n", "-C cache_size",
    "Cache size, unit MB (default 16MB)");
  fprintf(stderr, "%-15s %s\n", "-f",
    "Force saved bitfield or seed mode (skip initial hash check)");
  fprintf(stderr, "%-15s %s\n", "-b filename",
    "Specify bitfield save file (default is torrent+\".bf\")");
  fprintf(stderr, "%-15s %s\n", "-M max_peers",
    "Max peers count (default 100)");
  fprintf(stderr, "%-15s %s\n", "-m min_peers", "Min peers count (default 1)");
  fprintf(stderr, "%-15s %s\n", "-z slice_size",
    "Download slice/block size, unit KB (default 16, max 128)");
  fprintf(stderr, "%-15s %s\n", "-n file_list",
    "Specify file number(s) to download");
  fprintf(stderr, "%-15s %s\n", "-D rate", "Max bandwidth down (unit KB/s)");
  fprintf(stderr, "%-15s %s\n", "-U rate", "Max bandwidth up (unit KB/s)");
  fprintf(stderr, "%-15s %s%s\")\n", "-P peer_id",
    "Set Peer ID prefix (default \"", PEER_PFX);
  fprintf(stderr, "%-15s %s%s\")\n", "-A user_agent",
    "Set User-Agent header (default \"", cfg_user_agent);
  fprintf(stderr, "%-15s %s\n", "-S host:port",
    "Use CTCS server at host:port");
  fprintf(stderr, "%-15s %s\n", "-a", "Preallocate files on disk");
  fprintf(stderr, "%-15s %s\n", "-T",
    "Convert foreign filenames to printable text");
  fprintf(stderr, "%-15s %s\n", "-X command",
    "Run command upon download completion (\"user exit\")");
  fprintf(stderr, "%-15s %s\n", "-d", "Daemon mode (fork to background)");
  fprintf(stderr, "%-15s %s\n", "-dd", "Daemon mode with I/O redirection");

  fprintf(stderr,"\nMake metainfo (torrent) file options:\n");
  fprintf(stderr, "%-15s %s\n", "-t", "Create a new torrent file");
  fprintf(stderr, "%-15s %s\n", "-u URL", "Tracker's URL");
  fprintf(stderr, "%-15s %s\n", "-l piece_len",
    "Piece length (default 262144)");
  fprintf(stderr, "%-15s %s\n", "-s filename", "Specify metainfo file name");
  fprintf(stderr, "%-15s %s\n", "-p", "Private (disable peer exchange)");
  fprintf(stderr, "%-15s %s\n", "-c comment", "Include a comment/description");

  fprintf(stderr,"\nExample:\n");
  fprintf(stderr,"ctorrent -s new_filename -e 12 -C 32 -p 6881 example.torrent\n");
  fprintf(stderr,"\nhome page: http://ctorrent.sourceforge.net/\n");
  fprintf(stderr,"see also: http://www.rahul.net/dholmes/ctorrent/\n");
  fprintf(stderr,"bug report: %s\n",PACKAGE_BUGREPORT);
  fprintf(stderr,"original author: bsdi@sina.com\n\n");
}