add .gitignore
[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 SOCKET InstallHTTPGateway (Address addr);
18
19
20 int main (int argc, char** argv) {
21     
22     static struct option long_options[] =
23     {
24         {"hash",    required_argument, 0, 'h'},
25         {"file",    required_argument, 0, 'f'},
26         {"daemon",  no_argument, 0, 'd'},
27         {"listen",  required_argument, 0, 'l'},
28         {"tracker", required_argument, 0, 't'},
29         {"debug",   no_argument, 0, 'D'},
30         {"progress",no_argument, 0, 'p'},
31         {"http",    optional_argument, 0, 'g'},
32         {"wait",    optional_argument, 0, 'w'},
33         {0, 0, 0, 0}
34     };
35
36     Sha1Hash root_hash;
37     char* filename = 0;
38     bool daemonize = false, report_progress = false;
39     Address bindaddr;
40     Address tracker;
41     Address http_gw;
42     tint wait_time = 0;
43     
44     LibraryInit();
45     
46     int c;
47     while ( -1 != (c = getopt_long (argc, argv, ":h:f:dl:t:Dpg::w::", long_options, 0)) ) {
48         
49         switch (c) {
50             case 'h':
51                 if (strlen(optarg)!=40)
52                     quit("SHA1 hash must be 40 hex symbols\n");
53                 root_hash = Sha1Hash(true,optarg); // FIXME ambiguity
54                 if (root_hash==Sha1Hash::ZERO)
55                     quit("SHA1 hash must be 40 hex symbols\n");
56                 break;
57             case 'f':
58                 filename = strdup(optarg);
59                 break;
60             case 'd':
61                 daemonize = true;
62                 break;
63             case 'l':
64                 bindaddr = Address(optarg);
65                 if (bindaddr==Address())
66                     quit("address must be hostname:port, ip:port or just port\n");
67                 wait_time = TINT_NEVER;
68                 break;
69             case 't':
70                 tracker = Address(optarg);
71                 if (tracker==Address())
72                     quit("address must be hostname:port, ip:port or just port\n");
73                 SetTracker(tracker);
74                 break;
75             case 'D':
76                 Channel::debug_file = optarg ? fopen(optarg,"a") : stdout;
77                 break;
78             case 'p':
79                 report_progress = true;
80                 break;
81             case 'g':
82                 http_gw = optarg ? Address(optarg) : Address(Address::LOCALHOST,8080);
83                 if (wait_time==-1)
84                     wait_time = TINT_NEVER; // seed
85                 break;
86             case 'w':
87                 if (optarg) {
88                     char unit = 'u';
89                     if (sscanf(optarg,"%lli%c",&wait_time,&unit)!=2)
90                         quit("time format: 1234[umsMHD], e.g. 1M = one minute\n");
91                     switch (unit) {
92                         case 'D': wait_time *= 24;
93                         case 'H': wait_time *= 60;
94                         case 'M': wait_time *= 60;
95                         case 's': wait_time *= 1000;
96                         case 'm': wait_time *= 1000;
97                         case 'u': break;
98                         default:  quit("time format: 1234[umsMHD], e.g. 1D = one day\n");
99                     }
100                 } else
101                     wait_time = TINT_NEVER;
102                 break;
103         }
104
105     }   // arguments parsed
106     
107
108     if (bindaddr!=Address()) { // seeding
109         if (Listen(bindaddr)<=0)
110             quit("cant listen to %s\n",bindaddr.str())
111     } else if (tracker!=Address() || http_gw!=Address()) { // leeching
112         for (int i=0; i<=10; i++) {
113             bindaddr = Address((uint32_t)INADDR_ANY,0);
114             if (Listen(bindaddr)>0)
115                 break;
116             if (i==10)
117                 quit("cant listen on %s\n",bindaddr.str());
118         }
119     }
120     
121     if (tracker!=Address())
122         SetTracker(tracker);
123
124     if (http_gw!=Address())
125         InstallHTTPGateway(http_gw);
126
127     if (root_hash!=Sha1Hash::ZERO && !filename)
128         filename = strdup(root_hash.hex().c_str());
129
130     int file = -1;
131     if (filename) {
132         file = Open(filename,root_hash);
133         if (file<=0)
134             quit("cannot open file %s",filename);
135         printf("Root hash: %s\n", RootMerkleHash(file).hex().c_str());
136     }
137
138     if (bindaddr==Address() && file==-1 && http_gw==Address()) {
139         fprintf(stderr,"Usage:\n");
140         fprintf(stderr,"  -h, --hash\troot Merkle hash for the transmission\n");
141         fprintf(stderr,"  -f, --file\tname of file to use (root hash by default)\n");
142         fprintf(stderr,"  -l, --listen\t[ip:|host:]port to listen to (default: random)\n");
143         fprintf(stderr,"  -t, --tracker\t[ip:|host:]port of the tracker (default: none)\n");
144         fprintf(stderr,"  -D, --debug\tfile name for debugging logs (default: stdout)\n");
145         fprintf(stderr,"  -p, --progress\treport transfer progress\n");
146         fprintf(stderr,"  -g, --http\t[ip:|host:]port to bind HTTP gateway to (default localhost:8080)\n");
147         fprintf(stderr,"  -w, --wait\tlimit running time, e.g. 1[DHMs] (default: infinite with -l, -g)\n");
148         return 1;
149     }
150
151     tint start_time = NOW;
152     
153     while ( (file>=0 && !IsComplete(file)) ||
154             (start_time+wait_time>NOW)   ) {
155         swift::Loop(TINT_SEC);
156         if (report_progress && file>=0) {
157             fprintf(stderr,
158                     "%s %lli of %lli (seq %lli) %lli dgram %lli bytes up, "\
159                     "%lli dgram %lli bytes down\n",
160                 IsComplete(file) ? "DONE" : "done",
161                 Complete(file), Size(file), SeqComplete(file),
162                 Datagram::dgrams_up, Datagram::bytes_up,
163                 Datagram::dgrams_down, Datagram::bytes_down );
164         }
165     }
166     
167     if (file!=-1)
168         Close(file);
169     
170     if (Channel::debug_file)
171         fclose(Channel::debug_file);
172     
173     swift::Shutdown();
174     
175     return 0;
176     
177 }
178