labtunnel: Add tunnel operation for btpeers

Creating tunnels to bluetooth peers can be cumbersome to do manually,
so this change adds support for a new "btpeers" tunnel operation to
do to automatically like it does other tunnels. The README and usage
has been updated to describe this new feature as well.

BUG=None
TEST=Manually tested running the new tunnel operation and all of its
new related options.

Change-Id: I8d7ae6c7c8b78827cbb9c8470b078f5dafb6cab8
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crostestutils/+/3692167
Commit-Queue: Jared Bennett <jaredbennett@google.com>
Auto-Submit: Jared Bennett <jaredbennett@google.com>
Reviewed-by: Shijin Abraham <shijinabraham@google.com>
Tested-by: Jared Bennett <jaredbennett@google.com>
diff --git a/provingground/labtunnel/README.md b/provingground/labtunnel/README.md
index eafbc4d..73c6261 100644
--- a/provingground/labtunnel/README.md
+++ b/provingground/labtunnel/README.md
@@ -135,6 +135,47 @@
 Killing child processes...
 ```
 
+### btpeers
+```text
+$ labtunnel btpeers chromeos1-dev-host6
+Creating SSH tunnel BTPEER1-CHAMELEOND: localhost:9992 -> chromeos1-dev-host6-btpeer1 -> localhost:9992...
+Successfully created tunnels
+ BTPEER1-CHAMELEOND: localhost:9992 -> chromeos1-dev-host6-btpeer1 -> localhost:9992
+
+To shut down tunnels and sub-processes, exit this process  (pid=2229798) with SIGHUP, SIGINT, or SIGQUIT
+^C
+Closing labtunnel...
+Killing child processes...
+```
+
+```text
+$ labtunnel --btpeer-count 2 btpeers chromeos1-dev-host6
+Creating SSH tunnel BTPEER1-CHAMELEOND: localhost:9992 -> chromeos1-dev-host6-btpeer1 -> localhost:9992...
+Creating SSH tunnel BTPEER2-CHAMELEOND: localhost:9993 -> chromeos1-dev-host6-btpeer2 -> localhost:9992...
+Successfully created tunnels
+ BTPEER1-CHAMELEOND: localhost:9992 -> chromeos1-dev-host6-btpeer1 -> localhost:9992
+ BTPEER2-CHAMELEOND: localhost:9993 -> chromeos1-dev-host6-btpeer2 -> localhost:9992
+
+To shut down tunnels and sub-processes, exit this process  (pid=2167706) with SIGHUP, SIGINT, or SIGQUIT
+^C
+Closing labtunnel...
+Killing child processes...
+```
+
+```text
+ $ labtunnel --btpeer-count 2 --chameleond-port 5000 btpeers chromeos1-dev-host6
+Creating SSH tunnel BTPEER1-CHAMELEOND: localhost:5000 -> chromeos1-dev-host6-btpeer1 -> localhost:5000...
+Creating SSH tunnel BTPEER2-CHAMELEOND: localhost:5001 -> chromeos1-dev-host6-btpeer2 -> localhost:5000...
+Successfully created tunnels
+ BTPEER1-CHAMELEOND: localhost:5000 -> chromeos1-dev-host6-btpeer1 -> localhost:5000
+ BTPEER2-CHAMELEOND: localhost:5001 -> chromeos1-dev-host6-btpeer2 -> localhost:5000
+
+To shut down tunnels and sub-processes, exit this process  (pid=2230142) with SIGHUP, SIGINT, or SIGQUIT
+^C
+Closing labtunnel...
+Killing child processes...
+```
+
 
 ## Debugging
 The script is designed to clean itself up if something goes wrong in most cases,
diff --git a/provingground/labtunnel/labtunnel.sh b/provingground/labtunnel/labtunnel.sh
index a57baff..3a2e0f8 100755
--- a/provingground/labtunnel/labtunnel.sh
+++ b/provingground/labtunnel/labtunnel.sh
@@ -40,6 +40,8 @@
   "-o UserKnownHostsFile=/dev/null"
   "-o LogLevel=ERROR"
 )
+BTPEER_COUNT=1
+CHAMELEOND_PORT=9992
 while [[ $# -gt 2 ]]; do
   case $1 in
     --help|help|-h)
@@ -103,6 +105,14 @@
       IFS=' ' read -r -a SSH_OPTIONS <<< "$2"
       shift 2
       ;;
+    --btpeer-count)
+      BTPEER_COUNT="$2"
+      shift 2
+      ;;
+    --chameleond-port)
+      CHAMELEOND_PORT="$2"
+      shift 2
+      ;;
     *)
       echo "Error: Invalid option '$1'"
       print_help
@@ -137,6 +147,14 @@
   exit 1
 fi
 
+RE_POSITIVE_INT='^[0-9]+$'
+if ! [[ "${CHAMELEOND_PORT}" =~ ${RE_POSITIVE_INT} ]] \
+|| [ "${CHAMELEOND_PORT}" -le 0 ]; then
+  echo "Error: --chameleond-port value must be a non-zero positive integer"
+  print_help
+  exit 1
+fi
+
 # Resolve undefined hosts where possible
 function resolve_hostname {
   local RESOLVED_NAME="$1"
@@ -337,6 +355,16 @@
       echo "DUT VNC available at localhost:5900"
     fi
     ;;
+  btpeers)
+    # Tunnel to each bluetooth peer.
+    for ((i = 1; i <= "${BTPEER_COUNT}"; i++ )); do
+      BT_HOST="${HOST_DUT}-btpeer${i}"
+      LOCAL_BT_PORT=$(("${CHAMELEOND_PORT}" + "${i}" - 1))
+      make_tunnel "BTPEER${i}-CHAMELEOND" "localhost" "${LOCAL_BT_PORT}" \
+      "${BT_HOST}" "${CHAMELEOND_PORT}"
+    done
+    echo -e "${TUNNEL_SUMMARY}"
+    ;;
   *)
     echo "Error: Invalid tunnel type '${TUNNEL_TYPE}'"
     print_help
diff --git a/provingground/labtunnel/labtunnel_usage.txt b/provingground/labtunnel/labtunnel_usage.txt
index cf41594..5b62cf9 100644
--- a/provingground/labtunnel/labtunnel_usage.txt
+++ b/provingground/labtunnel/labtunnel_usage.txt
@@ -64,6 +64,25 @@
                         VNC server with TigerVNC and then connect to
                         localhost:5900 with your preferred VNC client.
 
+    btpeers         Opens ssh tunnels to Chameleond running on bluetooth peers.
+
+                      - Specify the number of bluetooth peers to connect to
+                        with the --btpeer-count option.
+
+                      - Specify the remote Chameleond port with the
+                        --chameleond-port option. The local forwarded ports will
+                        also reflect this same port with an offset for the
+                        btpeer number.
+
+                      - This does not create a tunnel for the dut, it just
+                        uses the provided dut hostname to determine the
+                        hostnames of the btpeers. The formula for the btpeer
+                        hostname is "<dut>-btpeer<n>", where "<dut>" is the dut
+                        hostname (as used in the dut tunnel_operation) and "<n>"
+                        is the Nth bluetooth peer, starting at 1. If you need
+                        tunnel to the dut, it's suggested to just run another
+                        labtunnel process using the dut tunnel_operation.
+
 
   Supported options:
    --help|help|-h             Prints this help text and exists.
@@ -109,3 +128,10 @@
 
    --ssh-options <options>    Sets all the CLI options to <options> used for all
                               ssh commands.
+
+   --btpeer-count <n>         Specifies the number of bluetooth peers to tunnel
+                              to for the btpeers tunnel_operation. Must be a
+                              positive integer. Defaults to 1.
+
+   --chameleond-port <port>   Specifies the remote Chameleond port to tunnel to
+                              for btpeers. Defaults to 9992.