#!/usr/bin/env python
""" Example: Simple Packet Printer """
from __future__ import print_function
import os
import sys
import argparse
import itertools

# Local imports
from chains.utils import signal_utils, compat
from chains.sources import packet_streamer
from chains.links import packet_meta, reverse_dns, transport_meta, flows, http_meta, tls_meta


def run(iface_name=None, max_packets=10000):
    """Run the Simple URL Watcher Script"""

    # Create the classes
    streamer = packet_streamer.PacketStreamer(iface_name=iface_name, max_packets=max_packets)
    meta = packet_meta.PacketMeta()
    rdns = reverse_dns.ReverseDNS()
    tmeta = transport_meta.TransportMeta()
    fmeta = flows.Flows()
    hmeta = http_meta.HTTPMeta()
    tlsmeta = tls_meta.TLSMeta()

    # Set up chain
    meta.link(streamer)
    rdns.link(meta)
    tmeta.link(rdns)
    fmeta.link(tmeta)

    # Put in a tee as incoming data may be HTTP or TLS/HTTPS
    flow1, flow2 = itertools.tee(fmeta.output_stream)
    hmeta.link(flow1)
    tlsmeta.link(flow2)

    # Print out the URIs
    for http_output, tls_output in compat.izip(hmeta.output_stream, tlsmeta.output_stream):

        # Check for Empty Payload
        if not http_output['payload']:
            continue

        # HTTP
        if http_output['http']:
            if http_output['http']['type'] == 'HTTP_REQUEST':
                uri = http_output['http']['data'].get('uri')
                headers = http_output['http']['data']['headers']
                referer = headers.get('referer') or '-'
                print(http_output['http']['type'])
                print('\tPayload Size: %d' % len(http_output['payload']))
                print('\t%s --> Host: %s \n\tURI: %s \n\tReferer: %s \n\tAgent: %s\n' % (http_output['src'], headers['host'], uri,
                                                                                         referer, headers['user-agent']))

                if http_output['http'].get('weird'):
                    print('\tWEIRD %s' % http_output['http']['weird'])
            else: # Response
                headers = http_output['http']['data']['headers']
                uri = headers.get('application-url') or '-'
                print(http_output['http']['type'])
                print('\tPayload Size: %d' % len(http_output['payload']))
                print('\t%s --> %s \n\tURI: %s \n\tHeaders: %s\n' % (http_output['src'], http_output['dst'], uri, repr(headers)))
                if http_output['http'].get('weird'):
                    print('\tWEIRD %s' % http_output['http']['weird'])

        # TLS/HTTPS
        elif tls_output['tls']:
            tls_records = tls_output['tls']['data']['tls_records']
            if tls_output['tls']['type'] == 'TLS_CTS':
                print('HTTPS_REQUEST')
                print('\t%s --> %s (%s) tls_records(%d)\n' % (tls_output['src'], tls_output['dst'], tls_output['dst_domain'], len(tls_records)))
            else:
                print('HTTPS_RESPONSE')
                print('\t%s (%s) --> %s tls_records(%d)\n' % (tls_output['src'], tls_output['src_domain'], tls_output['dst'], len(tls_records)))
            #for record in tls_records:
            #    print repr(record)[:100]+'...'
            #print

def test():
    """Test the Simple URL Watcher Script"""
    from chains.utils import file_utils

    # For the test we grab a file, but if you don't specify a
    # it will grab from the first active interface
    data_path = file_utils.relative_dir(__file__, '../data/https.pcap')
    run(iface_name = data_path)

def my_exit():
    """Exit on Signal"""
    print('Goodbye...')
    sys.exit()

if __name__ == '__main__':

    # Collect args from the command line
    parser = argparse.ArgumentParser()
    parser.add_argument('-m','--max-packets', type=int, default=10000, help='How many packets to process (0 for infinity)')
    parser.add_argument('-p','--pcap', type=str, help='Specify a pcap file instead of reading from live network interface')
    args, commands = parser.parse_known_args()
    if commands:
        print('Unrecognized args: %s' % commands)
    try:
        # Pcap file may have a tilde in it
        if args.pcap:
            args.pcap = os.path.expanduser(args.pcap)

        with signal_utils.signal_catcher(my_exit):
            run(iface_name=args.pcap, max_packets=args.max_packets)
    except KeyboardInterrupt:
        print('Goodbye...')
