#!/usr/bin/env python3

# A very basic example of how to create a python-native extension to Kismet
# that interfaces over the external API
#
# This uses the python_tools/KismetExternal python module.

import argparse
import os
import time
import sys
import threading

# Pretty-print the failure
try:
    import kismetexternal
except ImportError:
    print("ERROR:  Kismet external Python tools require the kismetexternal python ")
    print("        library; you can find it in the kismetexternal git or via pip")
    sys.exit(1)

class KismetProxyTest(object):
    def __init__(self):
        # Try to parse the arguments to find the descriptors we need to give to 
        # the kismet external tool; Kismet calls external helpers with a pre-made
        # set of pipes on --in-fd and --out-fd
        self.parser = argparse.ArgumentParser(description='Kismet External Python Example')

        self.parser.add_argument('--in-fd', action="store", type=int, dest="infd")
        self.parser.add_argument('--out-fd', action="store", type=int, dest="outfd")

        self.results = self.parser.parse_args()

        if self.results.infd is None or self.results.outfd is None:
            print("ERROR:  Kismet external python tools are (typically) launched by ")
            print("        Kismet itself; running it on its own won't do what you want")
            sys.exit(1)

        print("ProxyTest loaded KismetExternal {}".format(kismetexternal.__version__))

        # Initialize our external interface
        self.kei = kismetexternal.ExternalInterface(self.results.infd, self.results.outfd)

        # self.kei.debug = True

        # Start the external handler BEFORE we register our handlers, since we need to be
        # connected to send them!
        self.kei.start()

        # External tools can request a HTTP authentication token; this can be used as the
        # 'KISMET' session cookie to perform administrative actions against the Kismet
        # server
        self.kei.request_http_auth(self.handle_web_auth_token)

        # Add a URI handler; it doesn't need a login, and it returns HTML
        self.kei.add_uri_handler("GET", "/proxytest/python.html", self.handle_web_python)

        # Add a GET var test
        self.kei.add_uri_handler("GET", "/proxytest/python_get.html", self.handle_web_python_get)

        # Add a POST var test
        self.kei.add_uri_handler("POST", "/proxytest/python_post.html", self.handle_web_python_post)

        # Add a streaming handler
        self.kei.add_uri_handler("GET", "/proxytest/stream.raw", self.handle_web_stream)

        self.kei.send_message("Hello from python!  This is sent over the IPC message bus.")

        # Start the IO loops running
        self.kei.run()

    # Callback for when we've gotten back our auth token for the webserver
    def handle_web_auth_token(self):
        print("ProxyTest got HTTP auth token", self.kei.auth_token)

    # Callback function for handling a req of our python.html endpoint
    def handle_web_python(self, externalhandler, request):
        print("PYTHON - Handle web req {} {} {}".format(request.req_id, request.method, request.uri))
        # Print a static response
        externalhandler.send_http_response(request.req_id, bytes("<html><body><b>This is from python!</b></body></html>", "UTF-8"))

    # Callback function for handling a req of our variabls.html endpoint
    def handle_web_python_get(self, externalhandler, request):
        print("PYTHON - Handle web req {} {} {}".format(request.req_id, request.method, request.uri))
        print("PYTHON - GET variables ")
        for i in request.variable_data:
            print("PYTHON - GET {}:{}".format(i.field, i.content))

        externalhandler.send_http_response(request.req_id, bytes("<html><body><b>This is from python!</b></body></html>", "UTF-8"))

    # Callback function for handling a req of our variabls.html endpoint
    def handle_web_python_post(self, externalhandler, request):
        print("PYTHON - Handle web req {} {} {}".format(request.req_id, request.method, request.uri))
        for i in request.variable_data:
            print("PYTHON - POST {}:{}".format(i.field, i.content))

        externalhandler.send_http_response(request.req_id, bytes("<html><body><b>This is from python!</b></body></html>", "UTF-8"))

    # Callback function to demonstrate streaming
    def handle_web_stream(self, externalhandler, request):
        externalhandler.send_http_response(request.req_id, "Stream starting\n", stream = True, finished = False)
        # Make a thread that streams data out this request
        webthread = threading.Thread(target=self.stream_web_data, args=(externalhandler, request))
        webthread.start()

    # Thread that streams a counter
    def stream_web_data(self, externalhandler, request):
        counter = 0
        while self.kei.is_running:
            externalhandler.send_http_response(request.req_id, bytes("Stream {}\n".format(counter), "UTF-8"), stream = True, finished = False)
            counter += 1
            time.sleep(0.5)

    # Loop forever
    def loop(self):
        while self.kei.is_running():
            self.kei.send_ping()
            time.sleep(1)

        self.kei.kill()


if __name__ == "__main__":
    # Make a proxytest and loop forever
    pt = KismetProxyTest()

    # Loop in a detached process
    pt.loop()
