about summary refs log tree commit diff
path: root/nixpkgs/nixos/tests/bittorrent.nix
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/nixos/tests/bittorrent.nix')
-rw-r--r--nixpkgs/nixos/tests/bittorrent.nix149
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}");
+    '';
+
+})