#!/usr/bin/env python
# -*- Mode: Python -*-

import argparse
import struct
import sys
import time
from coro.asn1.python import decode

class Sync:
    
    magic = '%\xf1\xbfB'
    def __init__ (self):
        self.state = 0
        self.last = None
    def feed (self, ch):
        #sys.stderr.write ('[%d ch=%r]' % (self.state, ch))
        if ch == self.magic[self.state]:
            self.state += 1
            if self.state == 4:
                return True
            else:
                return False
        else:
            self.state = 0
            self.last = ch
            return False
    def resync (self, fdin):
        sys.stderr.write ('resync...')
        self.state = 0
        while 1:
            ch = fdin.read (1)
            if ch == '':
                raise EOFError
            else:
                if self.feed (ch):
                    break

def is_binary (ob):
    if type(ob) is not bytes:
        return False
    else:
        return '\x00' in ob

# note: this is application-specific - remove before putting this file into shrapnel.
def frob(ob):
    if type(ob) is bytes:
        if is_binary (ob):
            if len(ob) < 500 or args.big:
                return ob.encode ('hex')
            else:
                return '<large>'
        elif len(ob) == 32:
            return ob[::-1].encode ('hex')
        return ob
    else:
        return ob

def main():
    global args
    p = argparse.ArgumentParser (description='caesure asn1 log processor')
    p.add_argument ('-b', '--big', action='store_true', help="show large strings", default=False)
    p.add_argument ('-nb', '--no_blocks', action='store_true', help="ignore 'block' packets [only present if packet logging was enabled]", default=False)
    p.add_argument ('file', help="input file", nargs="?", metavar="FILE")
    args = p.parse_args()

    if args.file is None:
        file = sys.stdin
    else:
        file = open (args.file, 'rb')

    s = Sync()

    s.resync (file)

    while 1:
        size, = struct.unpack ('>I', file.read (4))
        block = file.read (size)
        if len(block) != size:
            break
        (timestamp, info), size = decode (block)
        timestamp /= 1000000.0
        if args.no_blocks and len(info) > 3 and info[2] == 'block':
            pass
        else:
            info = [frob(x) for x in info]
            print time.ctime (timestamp), info
        magic = file.read (4)
        if not magic:
            break
        elif magic != Sync.magic:
            s.resync (file)

if __name__ == '__main__':
    main()
