mfold prettification
[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 <getopt.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     int c;
42     while ( -1 != (c = getopt_long (argc, argv, ":h:f:dl:t:Dpw::", long_options, 0)) ) {
43         
44         switch (c) {
45             case 'h':
46                 if (strlen(optarg)!=40)
47                     quit("SHA1 hash must be 40 hex symbols\n");
48                 root_hash = Sha1Hash(true,optarg); // FIXME ambiguity
49                 if (root_hash==Sha1Hash::ZERO)
50                     quit("SHA1 hash must be 40 hex symbols\n");
51                 break;
52             case 'f':
53                 filename = strdup(optarg);
54                 break;
55             case 'd':
56                 daemonize = true;
57                 break;
58             case 'l':
59                 bindaddr = Address(optarg);
60                 if (bindaddr==Address())
61                     quit("address must be hostname:port, ip:port or just port\n");
62                 break;
63             case 't':
64                 tracker = Address(optarg);
65                 if (tracker==Address())
66                     quit("address must be hostname:port, ip:port or just port\n");
67                 SetTracker(tracker);
68                 break;
69             case 'D':
70                 Channel::debug_file = optarg ? fopen(optarg,"a") : stdout;
71                 break;
72             case 'p':
73                 report_progress = true;
74                 break;
75             case 'w':
76                 wait_time = TINT_NEVER;
77                 if (optarg) {
78                     char unit = 'u';
79                     if (sscanf(optarg,"%lli%c",&wait_time,&unit)!=2)
80                         quit("time format: 1234[umsMHD], e.g. 1M = one minute\n");
81                     switch (unit) {
82                         case 'D': wait_time *= 24;
83                         case 'H': wait_time *= 60;
84                         case 'M': wait_time *= 60;
85                         case 's': wait_time *= 1000;
86                         case 'm': wait_time *= 1000;
87                         case 'u': break;
88                         default:  quit("time format: 1234[umsMHD], e.g. 1D = one day\n");
89                     }
90                 }
91                 break;
92         }
93
94     }   // arguments parsed
95     
96     LibraryInit();
97     
98     if (root_hash==Sha1Hash() && bindaddr==Address())
99         exit(0);
100
101     if (bindaddr!=Address()) { // seeding
102         if (Listen(bindaddr)<=0)
103             quit("cant listen to %s\n",bindaddr.str())
104         if (wait_time==0)
105             wait_time=TINT_NEVER;
106     } else {
107         int base = rand()%10000, i;
108         for (i=0; i<100 && Listen(Address(INADDR_ANY,i*7+base))<=0; i++);
109         if (i==100)
110             quit("cant listen to a port\n");
111     }
112     
113     if (tracker!=Address())
114         SetTracker(tracker);
115     
116         int file = Open(filename,root_hash);
117     // FIXME open err 
118     printf("Root hash: %s\n", RootMerkleHash(file).hex().c_str());
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(std::min(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