#!/usr/bin/env python3
#
# Copyright 2017, The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
A python program that simulates the plugin side of the dt_fd_forward transport for testing.

This program will invoke a given java language runtime program and send down debugging arguments
that cause it to use the dt_fd_forward transport. This will then create a normal server-port that
debuggers can attach to.
"""

import argparse
import array
from multiprocessing import Process
import contextlib
import ctypes
import os
import select
import socket
import subprocess
import sys
import time

NEED_HANDSHAKE_MESSAGE = b"HANDSHAKE:REQD\x00"
LISTEN_START_MESSAGE   = b"dt_fd_forward:START-LISTEN\x00"
LISTEN_END_MESSAGE     = b"dt_fd_forward:END-LISTEN\x00"
ACCEPTED_MESSAGE       = b"dt_fd_forward:ACCEPTED\x00"
HANDSHAKEN_MESSAGE     = b"dt_fd_forward:HANDSHAKE-COMPLETE\x00"
CLOSE_MESSAGE          = b"dt_fd_forward:CLOSING\x00"

libc = ctypes.cdll.LoadLibrary("libc.so.6")
def eventfd(init_val, flags):
  """
  Creates an eventfd. See 'man 2 eventfd' for more information.
  """
  return libc.eventfd(init_val, flags)

@contextlib.contextmanager
def make_eventfd(init):
  """
  Creates an eventfd with given initial value that is closed after the manager finishes.
  """
  fd = eventfd(init, 0)
  yield fd
  os.close(fd)

@contextlib.contextmanager
def make_sockets():
  """
  Make a (remote,local) socket pair. The remote socket is inheritable by forked processes. They are
  both linked together.
  """
  (rfd, lfd) = socket.socketpair(socket.AF_UNIX, socket.SOCK_SEQPACKET)
  yield (rfd, lfd)
  rfd.close()
  lfd.close()

def send_fds(sock, remote_read, remote_write, remote_event):
  """
  Send the three fds over the given socket.
  """
  sock.sendmsg([NEED_HANDSHAKE_MESSAGE],  # We want the transport to handle the handshake.
               [(socket.SOL_SOCKET,  # Send over socket.
                 socket.SCM_RIGHTS,  # Payload is file-descriptor array
                 array.array('i', [remote_read, remote_write, remote_event]))])


def HandleSockets(host, port, local_sock, finish_event):
  """
  Handle the IO between the network and the runtime.

  This is similar to what we will do with the plugin that controls the jdwp connection.

  The main difference is it will keep around the connection and event-fd in order to let it send
  ddms packets directly.
  """
  listening = False
  with socket.socket() as sock:
    sock.bind((host, port))
    sock.listen()
    while True:
      sources = [local_sock, finish_event, sock]
      print("Starting select on " + str(sources))
      (rf, _, _) = select.select(sources, [], [])
      if local_sock in rf:
        buf = local_sock.recv(1024)
        print("Local_sock has data: " + str(buf))
        if buf == LISTEN_START_MESSAGE:
          print("listening on " + str(sock))
          listening = True
        elif buf == LISTEN_END_MESSAGE:
          print("End listening")
          listening = False
        elif buf == ACCEPTED_MESSAGE:
          print("Fds were accepted.")
        elif buf == HANDSHAKEN_MESSAGE:
          print("Handshake completed.")
        elif buf == CLOSE_MESSAGE:
          # TODO Dup the fds and send a fake DDMS message like the actual plugin would.
          print("Fds were closed")
        else:
          print("Unknown data received from socket " + str(buf))
          return
      elif sock in rf:
        (conn, addr) = sock.accept()
        with conn:
          print("connection accepted from " + str(addr))
          if listening:
            with make_eventfd(1) as efd:
              print("sending fds ({}, {}, {}) to target.".format(conn.fileno(), conn.fileno(), efd))
              send_fds(local_sock, conn.fileno(), conn.fileno(), efd)
          else:
            print("Closing fds since we cannot accept them.")
      if finish_event in rf:
        print("woke up from finish_event")
        return

def StartChildProcess(cmd_pre, cmd_post, jdwp_lib, jdwp_ops, remote_sock, can_be_runtest):
  """
  Open the child java-language runtime process.
  """
  full_cmd = list(cmd_pre)
  os.set_inheritable(remote_sock.fileno(), True)
  jdwp_arg = jdwp_lib + "=" + \
             jdwp_ops + "transport=dt_fd_forward,address=" + str(remote_sock.fileno())
  if can_be_runtest and cmd_pre[0].endswith("run-test"):
    print("Assuming run-test. Pass --no-run-test if this isn't true")
    full_cmd += ["--with-agent", jdwp_arg]
  else:
    full_cmd.append("-agentpath:" + jdwp_arg)
  full_cmd += cmd_post
  print("Running " + str(full_cmd))
  # Start the actual process with the fd being passed down.
  proc = subprocess.Popen(full_cmd, close_fds=False)
  # Get rid of the extra socket.
  remote_sock.close()
  proc.wait()

def main():
  parser = argparse.ArgumentParser(description="""
                                   Runs a socket that forwards to dt_fds.

                                   Pass '--' to start passing in the program we will pass the debug
                                   options down to.
                                   """)
  parser.add_argument("--host", type=str, default="localhost",
                      help="Host we will listen for traffic on. Defaults to 'localhost'.")
  parser.add_argument("--debug-lib", type=str, default="libjdwp.so",
                      help="jdwp library we pass to -agentpath:. Default is 'libjdwp.so'")
  parser.add_argument("--debug-options", type=str, default="server=y,suspend=y,",
                      help="non-address options we pass to jdwp agent, default is " +
                           "'server=y,suspend=y,'")
  parser.add_argument("--port", type=int, default=12345,
                      help="port we will expose the traffic on. Defaults to 12345.")
  parser.add_argument("--no-run-test", default=False, action="store_true",
                      help="don't pass in arguments for run-test even if it looks like that is " +
                           "the program")
  parser.add_argument("--pre-end", type=int, default=1,
                      help="number of 'rest' arguments to put before passing in the debug options")
  end_idx = 0 if '--' not in sys.argv else sys.argv.index('--')
  if end_idx == 0 and ('--help' in sys.argv or '-h' in sys.argv):
    parser.print_help()
    return
  args = parser.parse_args(sys.argv[:end_idx][1:])
  rest = sys.argv[1 + end_idx:]

  with make_eventfd(0) as wakeup_event:
    with make_sockets() as (remote_sock, local_sock):
      invoker = Process(target=StartChildProcess,
                        args=(rest[:args.pre_end],
                              rest[args.pre_end:],
                              args.debug_lib,
                              args.debug_options,
                              remote_sock,
                              not args.no_run_test))
      socket_handler = Process(target=HandleSockets,
                               args=(args.host, args.port, local_sock, wakeup_event))
      socket_handler.start()
      invoker.start()
    invoker.join()
    # Write any 64 bit value to the wakeup_event to make sure that the socket handler will wake
    # up and exit.
    os.write(wakeup_event, b'\x00\x00\x00\x00\x00\x00\x01\x00')
    socket_handler.join()

if __name__ == '__main__':
  main()
