Compiles well under MinGW and VC++ alike. Last but not least, runs afterwards.
[swift-upb.git] / swift.cpp
1 /*
2  *  swift.cpp
3  *  swift the multiparty transport protocol
4  *
5  *  Created by Victor Grishchenko on 2/15/10.
6  *  Copyright 2010 Delft University of Technology. All rights reserved.
7  *
8  */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include "compat.h"
12 #include "swift.h"
13
14 using namespace swift;
15
16 #define quit(...) {fprintf(stderr,__VA_ARGS__); exit(1); }
17
18
19 int main (int argc, char** argv) {
20     
21     static struct option long_options[] =
22     {
23         {"hash",    required_argument,       0, 'h'},
24         {"file",    required_argument,       0, 'f'},
25         {"daemon",  no_argument, 0, 'd'},
26         {"listen",  required_argument, 0, 'l'},
27         {"tracker", required_argument, 0, 't'},
28         {"debug",   no_argument, 0, 'D'},
29         {"progress",no_argument, 0, 'p'},
30         {"wait",    optional_argument, 0, 'w'},
31         {0, 0, 0, 0}
32     };
33
34     Sha1Hash root_hash;
35     char* filename = 0;
36     bool daemonize = false, report_progress = false;
37     Address bindaddr;
38     Address tracker;
39     tint wait_time = 0;
40     
41     LibraryInit();
42     
43     int c;
44     while ( -1 != (c = getopt_long (argc, argv, ":h:f:dl:t:Dpw::", long_options, 0)) ) {
45         
46         switch (c) {
47             case 'h':
48                 if (strlen(optarg)!=40)
49                     quit("SHA1 hash must be 40 hex symbols\n");
50                 root_hash = Sha1Hash(true,optarg); // FIXME ambiguity
51                 if (root_hash==Sha1Hash::ZERO)
52                     quit("SHA1 hash must be 40 hex symbols\n");
53                 break;
54             case 'f':
55                 filename = strdup(optarg);
56                 break;
57             case 'd':
58                 daemonize = true;
59                 break;
60             case 'l':
61                 bindaddr = Address(optarg);
62                 if (bindaddr==Address())
63                     quit("address must be hostname:port, ip:port or just port\n");
64                 break;
65             case 't':
66                 tracker = Address(optarg);
67                 if (tracker==Address())
68                     quit("address must be hostname:port, ip:port or just port\n");
69                 SetTracker(tracker);
70                 break;
71             case 'D':
72                 Channel::debug_file = optarg ? fopen(optarg,"a") : stdout;
73                 break;
74             case 'p':
75                 report_progress = true;
76                 break;
77             case 'w':
78                 wait_time = TINT_NEVER;
79                 if (optarg) {
80                     char unit = 'u';
81                     if (sscanf(optarg,"%lli%c",&wait_time,&unit)!=2)
82                         quit("time format: 1234[umsMHD], e.g. 1M = one minute\n");
83                     switch (unit) {
84                         case 'D': wait_time *= 24;
85                         case 'H': wait_time *= 60;
86                         case 'M': wait_time *= 60;
87                         case 's': wait_time *= 1000;
88                         case 'm': wait_time *= 1000;
89                         case 'u': break;
90                         default:  quit("time format: 1234[umsMHD], e.g. 1D = one day\n");
91                     }
92                 }
93                 break;
94         }
95
96     }   // arguments parsed
97     
98     if (bindaddr!=Address()) { // seeding
99         if (Listen(bindaddr)<=0)
100             quit("cant listen to %s\n",bindaddr.str())
101         if (wait_time==0)
102             wait_time=TINT_NEVER;
103     } else if (tracker!=Address()) { // leeching
104         int base = rand()%10000, i;
105         for (i=0; i<100 && Listen(Address((uint32_t)INADDR_ANY,i*7+base))<=0; i++);
106         if (i==100)
107             quit("cant listen to a port\n");
108     }
109     
110     if (tracker!=Address())
111         SetTracker(tracker);
112     
113         int file = Open(filename,root_hash);
114     // FIXME open err 
115     printf("Root hash: %s\n", RootMerkleHash(file).hex().c_str());
116
117         if (root_hash==Sha1Hash() && bindaddr==Address() && tracker==Address())
118         exit(0);
119
120     tint start_time = NOW;
121     tint end_time = TINT_NEVER;
122     
123     while (NOW<end_time+wait_time){
124         if (end_time==TINT_NEVER && IsComplete(file))
125             end_time = NOW;
126         // and yes, I add up infinities and go away with that
127         tint towait = (end_time+wait_time)-NOW;
128                 Loop(TINT_SEC<towait?TINT_SEC:towait);
129         if (report_progress) {
130             fprintf(stderr,
131                     "%s %lli of %lli (seq %lli) %lli dgram %lli bytes up, "\
132                     "%lli dgram %lli bytes down\n",
133                 IsComplete(file) ? "DONE" : "done",
134                 Complete(file), Size(file), SeqComplete(file),
135                 Datagram::dgrams_up, Datagram::bytes_up,
136                 Datagram::dgrams_down, Datagram::bytes_down );
137         }
138     }
139     
140         Close(file);
141     
142     if (Channel::debug_file)
143         fclose(Channel::debug_file);
144     
145         Shutdown();
146     
147     return 0;
148     
149 }
150