Added the single swift app;
[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(optarg);
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                 break;
68             case 'D':
69                 Channel::debug_file = optarg ? fopen(optarg,"a") : stdout;
70                 break;
71             case 'p':
72                 report_progress = true;
73                 break;
74             case 'w':
75                 wait_time = TINT_NEVER;
76                 if (optarg) {
77                     char unit = 'u';
78                     if (sscanf(optarg,"%lli%c",&wait_time,&unit)!=2)
79                         quit("time format: 1234[umsMHD], e.g. 1M = one minute\n");
80                     switch (unit) {
81                         case 'D': wait_time *= 24;
82                         case 'H': wait_time *= 60;
83                         case 'M': wait_time *= 60;
84                         case 's': wait_time *= 1000;
85                         case 'm': wait_time *= 1000;
86                         case 'u': break;
87                         default:  quit("time format: 1234[umsMHD], e.g. 1D = one day\n");
88                     }
89                 }
90                 break;
91         }
92
93     }   // arguments parsed
94     
95     LibraryInit();
96     
97         int file = Open(filename,root_hash);
98     // FIXME open err 
99     printf("Root hash: %s\n", RootMerkleHash(file).hex().c_str());
100     
101     if (root_hash==Sha1Hash() && bindaddr==Address())
102         exit(0);
103
104     if (bindaddr!=Address()) { // seeding
105         if (Listen(bindaddr)<=0)
106             quit("cant listen to %s\n",bindaddr.str())
107         if (wait_time==0)
108             wait_time=TINT_NEVER;
109     } else {
110         int base = rand()%10000, i;
111         for (i=0; i<100 && Listen(Address(INADDR_ANY,i*7+base))<=0; i++);
112         if (i==100)
113             quit("cant listen to a port\n");
114     }
115     
116     
117     if (tracker!=Address())
118         SetTracker(tracker);
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