#!/usr/bin/env python2

# Copyright 2017 Google Inc. All Rights Reserved.
#
# 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.
"""Send a link to a process running LinkReceiver.

If a Starboard implementation instantiates
starboard::shared::starboard::LinkReceiver, then it will write a file containing
the port to the configured temporary directory. This script finds that file and
sends the specified link to that service. It is up to the application to
interpret that link content.

Note that LinkReceiver generally runs on the loopback interface, so this script
should be run from the same device running the application.

"""

import argparse
from contextlib import closing
import logging
import os
import socket
import sys
import tempfile
import textwrap


def _Uncase(text):
  return text.upper().lower()


def _GetPids(executable):
  if sys.platform in ('win32', 'cygwin'):
    raise NotImplementedError('Implement me for Windows!')
  elif sys.platform.startswith('linux') or sys.platform == 'darwin':
    pids = []
    executable = _Uncase(executable)
    for pid in os.listdir('/proc'):
      if pid == 'curproc':
        continue

      pid_path = '/proc/' + pid
      if not os.path.isdir(pid_path):
        continue

      try:
        cmdline_path = os.path.join(pid_path, 'cmdline')
        with open(cmdline_path, mode='rb') as cmdline:
          content = cmdline.read().decode().split('\x00')
      except IOError:
        continue

      if os.path.basename(_Uncase(content[0])).startswith(executable):
        pids += [pid]
    return pids


def _FindTemporaryFile(prefix, suffix):
  directory = tempfile.gettempdir()
  for entry in os.listdir(directory):
    caseless_entry = _Uncase(entry)
    if caseless_entry.startswith(prefix) and caseless_entry.endswith(suffix):
      return os.path.join(directory, entry)

  return None


def _SendLink(executable, link):
  """Sends a link to the process starting with the given executable name."""

  pids = _GetPids(executable)

  if not pids:
    logging.error('No PIDs found for %s', executable)
    return 1

  if len(pids) > 1:
    logging.error('Multiple PIDs found for %s: %s', executable, pids)
    return 1

  pid = pids[0]
  temporary_directory = _FindTemporaryFile(_Uncase(executable), _Uncase(pid))
  if not os.path.isdir(temporary_directory):
    logging.error('Not a directory: %s', temporary_directory)
    return 1

  port_file_path = os.path.join(temporary_directory, 'link_receiver_port')
  if not os.path.isfile(port_file_path):
    logging.error('Not a file: %s', port_file_path)
    return 1

  try:
    with open(port_file_path, mode='rb') as port_file:
      port = int(port_file.read().decode())
  except IOError:
    logging.exception('Could not open port file: %s', port_file_path)
    return 1

  try:
    with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s:
      s.connect(('localhost', port))
      terminated_link = link + '\x00'
      bytes_sent = 0
      while bytes_sent < len(terminated_link):
        sent = s.send(terminated_link[bytes_sent:])
        if sent == 0:
          raise RuntimeError('Connection terminated by remote host.')
        bytes_sent += sent
  except (RuntimeError, IOError):
    logging.exception('Could not connect to port: %d', port)
    return 1

  logging.info('Link "%s" sent to %s at pid %s on port %d.', link, executable,
               pid, port)

  return 0


def main():
  parser = argparse.ArgumentParser(
      formatter_class=argparse.ArgumentDefaultsHelpFormatter,
      description=textwrap.dedent(__doc__))
  parser.add_argument(
      'executable',
      type=str,
      help='Name of the running executable to send a link to.')
  parser.add_argument(
      'link', type=str, help='The link content to send to the executable.')
  arguments = parser.parse_args()
  return _SendLink(arguments.executable, arguments.link)


if __name__ == '__main__':
  logging.basicConfig(level=logging.INFO, format='[%(levelname)5s] %(message)s')
  sys.exit(main())
