at 17.09-beta 4.2 kB view raw
1# This test runs a Bittorrent tracker on one machine, and verifies 2# that two client machines can download the torrent using 3# `transmission'. The first client (behind a NAT router) downloads 4# from the initial seeder running on the tracker. Then we kill the 5# initial seeder. The second client downloads from the first client, 6# which only works if the first client successfully uses the UPnP-IGD 7# protocol to poke a hole in the NAT. 8 9import ./make-test.nix ({ pkgs, ... }: 10 11let 12 13 # Some random file to serve. 14 file = pkgs.hello.src; 15 16 miniupnpdConf = nodes: pkgs.writeText "miniupnpd.conf" 17 '' 18 ext_ifname=eth1 19 listening_ip=${(pkgs.lib.head nodes.router.config.networking.interfaces.eth2.ip4).address}/24 20 allow 1024-65535 192.168.2.0/24 1024-65535 21 ''; 22 23in 24 25{ 26 name = "bittorrent"; 27 meta = with pkgs.stdenv.lib.maintainers; { 28 maintainers = [ domenkozar eelco chaoflow rob wkennington ]; 29 }; 30 31 nodes = 32 { tracker = 33 { config, pkgs, ... }: 34 { environment.systemPackages = [ pkgs.transmission pkgs.opentracker ]; 35 36 # We need Apache on the tracker to serve the torrents. 37 services.httpd.enable = true; 38 services.httpd.adminAddr = "foo@example.org"; 39 services.httpd.documentRoot = "/tmp"; 40 41 networking.firewall.enable = false; # FIXME: figure out what ports we actually need 42 }; 43 44 router = 45 { config, pkgs, ... }: 46 { environment.systemPackages = [ pkgs.miniupnpd ]; 47 virtualisation.vlans = [ 1 2 ]; 48 networking.nat.enable = true; 49 networking.nat.internalInterfaces = [ "eth2" ]; 50 networking.nat.externalInterface = "eth1"; 51 networking.firewall.enable = false; 52 }; 53 54 client1 = 55 { config, pkgs, nodes, ... }: 56 { environment.systemPackages = [ pkgs.transmission ]; 57 virtualisation.vlans = [ 2 ]; 58 networking.defaultGateway = 59 (pkgs.lib.head nodes.router.config.networking.interfaces.eth2.ip4).address; 60 networking.firewall.enable = false; 61 }; 62 63 client2 = 64 { config, pkgs, ... }: 65 { environment.systemPackages = [ pkgs.transmission ]; 66 networking.firewall.enable = false; 67 }; 68 }; 69 70 testScript = 71 { nodes, ... }: 72 '' 73 startAll; 74 75 # Enable NAT on the router and start miniupnpd. 76 $router->waitForUnit("nat"); 77 $router->succeed( 78 "iptables -w -t nat -N MINIUPNPD", 79 "iptables -w -t nat -A PREROUTING -i eth1 -j MINIUPNPD", 80 "echo 1 > /proc/sys/net/ipv4/ip_forward", 81 "miniupnpd -f ${miniupnpdConf nodes}" 82 ); 83 84 # Create the torrent. 85 $tracker->succeed("mkdir /tmp/data"); 86 $tracker->succeed("cp ${file} /tmp/data/test.tar.bz2"); 87 $tracker->succeed("transmission-create /tmp/data/test.tar.bz2 -p -t http://${(pkgs.lib.head nodes.tracker.config.networking.interfaces.eth1.ip4).address}:6969/announce -o /tmp/test.torrent"); 88 $tracker->succeed("chmod 644 /tmp/test.torrent"); 89 90 # Start the tracker. !!! use a less crappy tracker 91 $tracker->waitForUnit("network.target"); 92 $tracker->succeed("opentracker -p 6969 >&2 &"); 93 $tracker->waitForOpenPort(6969); 94 95 # Start the initial seeder. 96 my $pid = $tracker->succeed("transmission-cli /tmp/test.torrent -M -w /tmp/data >&2 & echo \$!"); 97 98 # Now we should be able to download from the client behind the NAT. 99 $tracker->waitForUnit("httpd"); 100 $client1->waitForUnit("network.target"); 101 $client1->succeed("transmission-cli http://tracker/test.torrent -w /tmp >&2 &"); 102 $client1->waitForFile("/tmp/test.tar.bz2"); 103 $client1->succeed("cmp /tmp/test.tar.bz2 ${file}"); 104 105 # Bring down the initial seeder. 106 $tracker->succeed("kill -9 $pid"); 107 108 # Now download from the second client. This can only succeed if 109 # the first client created a NAT hole in the router. 110 $client2->waitForUnit("network.target"); 111 $client2->succeed("transmission-cli http://tracker/test.torrent -M -w /tmp >&2 &"); 112 $client2->waitForFile("/tmp/test.tar.bz2"); 113 $client2->succeed("cmp /tmp/test.tar.bz2 ${file}"); 114 ''; 115 116})