Changeset 9549 for trunk/third-party/dht/dht-example.c
- Timestamp:
- Nov 24, 2009, 1:59:51 AM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/third-party/dht/dht-example.c
r9323 r9549 21 21 22 22 #define MAX_BOOTSTRAP_NODES 20 23 static struct sockaddr_ inbootstrap_nodes[MAX_BOOTSTRAP_NODES];23 static struct sockaddr_storage bootstrap_nodes[MAX_BOOTSTRAP_NODES]; 24 24 static int num_bootstrap_nodes = 0; 25 25 … … 93 93 { 94 94 int i, rc, fd; 95 int s , port;95 int s = -1, s6 = -1, port; 96 96 int have_id = 0; 97 97 unsigned char myid[20]; 98 98 time_t tosleep = 0; 99 char *id_file = "dht-example.id"; 100 int opt; 101 int quiet = 0, ipv4 = 1, ipv6 = 1; 102 struct sockaddr_in sin; 103 struct sockaddr_in6 sin6; 104 105 memset(&sin, 0, sizeof(sin)); 106 sin.sin_family = AF_INET; 107 108 memset(&sin6, 0, sizeof(sin6)); 109 sin6.sin6_family = AF_INET6; 110 111 112 113 while(1) { 114 opt = getopt(argc, argv, "q46b:i:"); 115 if(opt < 0) 116 break; 117 118 switch(opt) { 119 case 'q': quiet = 1; break; 120 case '4': ipv6 = 0; break; 121 case '6': ipv4 = 0; break; 122 case 'b': { 123 char buf[16]; 124 int rc; 125 rc = inet_pton(AF_INET, optarg, buf); 126 if(rc == 1) { 127 memcpy(&sin.sin_addr, buf, 4); 128 break; 129 } 130 rc = inet_pton(AF_INET6, optarg, buf); 131 if(rc == 1) { 132 memcpy(&sin6.sin6_addr, buf, 16); 133 break; 134 } 135 goto usage; 136 } 137 break; 138 case 'i': 139 id_file = optarg; 140 break; 141 default: 142 goto usage; 143 } 144 } 99 145 100 146 /* Ids need to be distributed evenly, so you cannot just use your 101 147 bittorrent id. Either generate it randomly, or take the SHA-1 of 102 148 something. */ 103 fd = open( "dht-example.id", O_RDONLY);149 fd = open(id_file, O_RDONLY); 104 150 if(fd >= 0) { 105 151 rc = read(fd, myid, 20); … … 109 155 } 110 156 157 fd = open("/dev/urandom", O_RDONLY); 158 if(fd < 0) { 159 perror("open(random)"); 160 exit(1); 161 } 162 111 163 if(!have_id) { 112 fd = open("/dev/urandom", O_RDONLY); 113 if(fd < 0) { 114 perror("open(random)"); 115 exit(1); 116 } 164 int ofd; 165 117 166 rc = read(fd, myid, 20); 118 167 if(rc < 0) { … … 123 172 close(fd); 124 173 125 fd = open("dht-example.id", O_WRONLY | O_CREAT | O_TRUNC, 0666);126 if( fd >= 0) {127 rc = write( fd, myid, 20);174 ofd = open(id_file, O_WRONLY | O_CREAT | O_TRUNC, 0666); 175 if(ofd >= 0) { 176 rc = write(ofd, myid, 20); 128 177 if(rc < 20) 129 unlink("dht-example.id"); 130 close(fd); 131 } 132 } 178 unlink(id_file); 179 close(ofd); 180 } 181 } 182 183 { 184 unsigned seed; 185 read(fd, &seed, sizeof(seed)); 186 srandom(seed); 187 } 188 189 close(fd); 133 190 134 191 if(argc < 2) 135 192 goto usage; 136 193 137 i = 1;194 i = optind; 138 195 139 196 if(argc < i + 1) … … 147 204 struct addrinfo hints, *info, *infop; 148 205 memset(&hints, 0, sizeof(hints)); 149 hints.ai_family = AF_INET;150 206 hints.ai_socktype = SOCK_DGRAM; 151 rc = getaddrinfo(argv[i], NULL, &hints, &info); 207 if(!ipv6) 208 hints.ai_family = AF_INET; 209 else if(!ipv4) 210 hints.ai_family = AF_INET6; 211 else 212 hints.ai_family = 0; 213 rc = getaddrinfo(argv[i], argv[i + 1], &hints, &info); 152 214 if(rc != 0) { 153 215 fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rc)); … … 161 223 infop = info; 162 224 while(infop) { 163 if(infop->ai_addr->sa_family == AF_INET) { 164 struct sockaddr_in sin; 165 memcpy(&sin, infop->ai_addr, infop->ai_addrlen); 166 sin.sin_port = htons(atoi(argv[i])); 167 bootstrap_nodes[num_bootstrap_nodes] = sin; 168 num_bootstrap_nodes++; 169 } 225 memcpy(&bootstrap_nodes[num_bootstrap_nodes], 226 infop->ai_addr, infop->ai_addrlen); 170 227 infop = infop->ai_next; 228 num_bootstrap_nodes++; 171 229 } 172 230 freeaddrinfo(info); … … 177 235 /* If you set dht_debug to a stream, every action taken by the DHT will 178 236 be logged. */ 179 dht_debug = stdout; 180 181 /* We need an IPv4 socket, bound to a stable port. Rumour has it that 182 uTorrent works better when it is the same as your Bittorrent port. */ 183 s = socket(PF_INET, SOCK_DGRAM, 0); 184 if(s < 0) { 185 perror("socket"); 237 if(!quiet) 238 dht_debug = stdout; 239 240 /* We need an IPv4 and an IPv6 socket, bound to a stable port. Rumour 241 has it that uTorrent works better when it is the same as your 242 Bittorrent port. */ 243 if(ipv4) { 244 s = socket(PF_INET, SOCK_DGRAM, 0); 245 if(s < 0) { 246 perror("socket(IPv4)"); 247 } 248 } 249 250 if(ipv6) { 251 s6 = socket(PF_INET6, SOCK_DGRAM, 0); 252 if(s6 < 0) { 253 perror("socket(IPv6)"); 254 } 255 } 256 257 if(s < 0 && s6 < 0) { 258 fprintf(stderr, "Eek!"); 186 259 exit(1); 187 260 } 188 261 189 { 190 struct sockaddr_in sin; 191 memset(&sin, 0, sizeof(sin)); 192 sin.sin_family = AF_INET; 262 263 if(s >= 0) { 193 264 sin.sin_port = htons(port); 194 265 rc = bind(s, (struct sockaddr*)&sin, sizeof(sin)); 195 266 if(rc < 0) { 196 perror("bind ");267 perror("bind(IPv4)"); 197 268 exit(1); 198 269 } 199 270 } 200 271 272 if(s6 >= 0) { 273 int rc; 274 int val = 1; 275 276 rc = setsockopt(s6, IPPROTO_IPV6, IPV6_V6ONLY, 277 (char *)&val, sizeof(val)); 278 if(rc < 0) { 279 perror("setsockopt(IPV6_V6ONLY)"); 280 exit(1); 281 } 282 283 /* BEP-32 mandates that we should bind this socket to one of our 284 global IPv6 addresses. In this simple example, this only 285 happens if the user used the -b flag. */ 286 287 sin6.sin6_port = htons(port); 288 rc = bind(s6, (struct sockaddr*)&sin6, sizeof(sin6)); 289 if(rc < 0) { 290 perror("bind(IPv6)"); 291 exit(1); 292 } 293 } 294 201 295 /* Init the dht. This sets the socket into non-blocking mode. */ 202 rc = dht_init(s, myid, NULL);296 rc = dht_init(s, s6, myid, (unsigned char*)"JC\0\0"); 203 297 if(rc < 0) { 204 298 perror("dht_init"); … … 218 312 dht_insert_node. If the ids are incorrect, the DHT will recover. */ 219 313 for(i = 0; i < num_bootstrap_nodes; i++) { 220 dht_ping_node(s, &bootstrap_nodes[i]); 314 dht_ping_node((struct sockaddr*)&bootstrap_nodes[i], 315 sizeof(bootstrap_nodes[i])); 221 316 usleep(random() % 100000); 222 317 } … … 229 324 230 325 FD_ZERO(&readfds); 231 FD_SET(s, &readfds); 232 rc = select(s + 1, &readfds, NULL, NULL, &tv); 326 if(s >= 0) 327 FD_SET(s, &readfds); 328 if(s6 >= 0) 329 FD_SET(s6, &readfds); 330 rc = select(s > s6 ? s + 1 : s6 + 1, &readfds, NULL, NULL, &tv); 233 331 if(rc < 0) { 234 332 if(errno != EINTR) { … … 241 339 break; 242 340 243 rc = dht_periodic( s,rc > 0, &tosleep, callback, NULL);341 rc = dht_periodic(rc > 0, &tosleep, callback, NULL); 244 342 if(rc < 0) { 245 343 if(errno == EINTR) { … … 254 352 255 353 /* This is how you trigger a search for a torrent hash. If port 256 (the third argument) is non-zero, it also performs an announce.354 (the second argument) is non-zero, it also performs an announce. 257 355 Since peers expire announced data after 30 minutes, it's a good 258 356 idea to reannounce every 28 minutes or so. */ 259 357 if(searching) { 260 dht_search(s, hash, 0, callback, NULL); 358 if(s >= 0) 359 dht_search(hash, 0, AF_INET, callback, NULL); 360 if(s6 >= 0) 361 dht_search(hash, 0, AF_INET6, callback, NULL); 261 362 searching = 0; 262 363 } … … 270 371 271 372 { 272 struct sockaddr_in sins[500]; 373 struct sockaddr_in sin[500]; 374 struct sockaddr_in6 sin6[500]; 375 int num = 500, num6 = 500; 273 376 int i; 274 i = dht_get_nodes(sin s, 500);275 printf("Found %d good nodes.\n", i);276 } 277 278 dht_uninit( s,1);377 i = dht_get_nodes(sin, &num, sin6, &num6); 378 printf("Found %d (%d + %d) good nodes.\n", i, num, num6); 379 } 380 381 dht_uninit(1); 279 382 return 0; 280 383 281 384 usage: 282 fprintf(stderr, "Foo!\n"); 385 printf("Usage: dht-example [-q] [-4] [-6] [-i filename] [-b address]...\n" 386 " port [address port]...\n"); 283 387 exit(1); 284 388 }
Note: See TracChangeset
for help on using the changeset viewer.