diff options
Diffstat (limited to 'nixpkgs/nixos/tests/bittorrent.nix')
-rw-r--r-- | nixpkgs/nixos/tests/bittorrent.nix | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/nixpkgs/nixos/tests/bittorrent.nix b/nixpkgs/nixos/tests/bittorrent.nix new file mode 100644 index 000000000000..3b1169a1b7f2 --- /dev/null +++ b/nixpkgs/nixos/tests/bittorrent.nix @@ -0,0 +1,149 @@ +# This test runs a Bittorrent tracker on one machine, and verifies +# that two client machines can download the torrent using +# `transmission'. The first client (behind a NAT router) downloads +# from the initial seeder running on the tracker. Then we kill the +# initial seeder. The second client downloads from the first client, +# which only works if the first client successfully uses the UPnP-IGD +# protocol to poke a hole in the NAT. + +import ./make-test.nix ({ pkgs, ... }: + +let + + # Some random file to serve. + file = pkgs.hello.src; + + internalRouterAddress = "192.168.3.1"; + internalClient1Address = "192.168.3.2"; + externalRouterAddress = "80.100.100.1"; + externalClient2Address = "80.100.100.2"; + externalTrackerAddress = "80.100.100.3"; +in + +{ + name = "bittorrent"; + meta = with pkgs.stdenv.lib.maintainers; { + maintainers = [ domenkozar eelco rob bobvanderlinden ]; + }; + + nodes = + { tracker = + { pkgs, ... }: + { environment.systemPackages = [ pkgs.transmission ]; + + virtualisation.vlans = [ 1 ]; + networking.interfaces.eth1.ipv4.addresses = [ + { address = externalTrackerAddress; prefixLength = 24; } + ]; + + # We need Apache on the tracker to serve the torrents. + services.httpd.enable = true; + services.httpd.adminAddr = "foo@example.org"; + services.httpd.documentRoot = "/tmp"; + + networking.firewall.enable = false; + + services.opentracker.enable = true; + + services.transmission.enable = true; + services.transmission.settings.dht-enabled = false; + services.transmission.settings.port-forwaring-enabled = false; + }; + + router = + { pkgs, nodes, ... }: + { virtualisation.vlans = [ 1 2 ]; + networking.nat.enable = true; + networking.nat.internalInterfaces = [ "eth2" ]; + networking.nat.externalInterface = "eth1"; + networking.firewall.enable = true; + networking.firewall.trustedInterfaces = [ "eth2" ]; + networking.interfaces.eth0.ipv4.addresses = []; + networking.interfaces.eth1.ipv4.addresses = [ + { address = externalRouterAddress; prefixLength = 24; } + ]; + networking.interfaces.eth2.ipv4.addresses = [ + { address = internalRouterAddress; prefixLength = 24; } + ]; + services.miniupnpd = { + enable = true; + externalInterface = "eth1"; + internalIPs = [ "eth2" ]; + appendConfig = '' + ext_ip=${externalRouterAddress} + ''; + }; + }; + + client1 = + { pkgs, nodes, ... }: + { environment.systemPackages = [ pkgs.transmission pkgs.miniupnpc ]; + virtualisation.vlans = [ 2 ]; + networking.interfaces.eth0.ipv4.addresses = []; + networking.interfaces.eth1.ipv4.addresses = [ + { address = internalClient1Address; prefixLength = 24; } + ]; + networking.defaultGateway = internalRouterAddress; + networking.firewall.enable = false; + services.transmission.enable = true; + services.transmission.settings.dht-enabled = false; + services.transmission.settings.message-level = 3; + }; + + client2 = + { pkgs, ... }: + { environment.systemPackages = [ pkgs.transmission ]; + virtualisation.vlans = [ 1 ]; + networking.interfaces.eth0.ipv4.addresses = []; + networking.interfaces.eth1.ipv4.addresses = [ + { address = externalClient2Address; prefixLength = 24; } + ]; + networking.firewall.enable = false; + services.transmission.enable = true; + services.transmission.settings.dht-enabled = false; + services.transmission.settings.port-forwaring-enabled = false; + }; + }; + + testScript = + { nodes, ... }: + '' + startAll; + + # Wait for network and miniupnpd. + $router->waitForUnit("network-online.target"); + $router->waitForUnit("miniupnpd"); + + # Create the torrent. + $tracker->succeed("mkdir /tmp/data"); + $tracker->succeed("cp ${file} /tmp/data/test.tar.bz2"); + $tracker->succeed("transmission-create /tmp/data/test.tar.bz2 --private --tracker http://${externalTrackerAddress}:6969/announce --outfile /tmp/test.torrent"); + $tracker->succeed("chmod 644 /tmp/test.torrent"); + + # Start the tracker. !!! use a less crappy tracker + $tracker->waitForUnit("network-online.target"); + $tracker->waitForUnit("opentracker.service"); + $tracker->waitForOpenPort(6969); + + # Start the initial seeder. + $tracker->succeed("transmission-remote --add /tmp/test.torrent --no-portmap --no-dht --download-dir /tmp/data"); + + # Now we should be able to download from the client behind the NAT. + $tracker->waitForUnit("httpd"); + $client1->waitForUnit("network-online.target"); + $client1->succeed("transmission-remote --add http://${externalTrackerAddress}/test.torrent --download-dir /tmp >&2 &"); + $client1->waitForFile("/tmp/test.tar.bz2"); + $client1->succeed("cmp /tmp/test.tar.bz2 ${file}"); + + # Bring down the initial seeder. + # $tracker->stopJob("transmission"); + + # Now download from the second client. This can only succeed if + # the first client created a NAT hole in the router. + $client2->waitForUnit("network-online.target"); + $client2->succeed("transmission-remote --add http://${externalTrackerAddress}/test.torrent --no-portmap --no-dht --download-dir /tmp >&2 &"); + $client2->waitForFile("/tmp/test.tar.bz2"); + $client2->succeed("cmp /tmp/test.tar.bz2 ${file}"); + ''; + +}) |