#!/usr/bin/python
# -*- mode: python-mode; py-indent-tabs-mode: nil -*-

import sys,os, random
from optparse import OptionParser
import socket
import struct

verbose = False

def prefix_ipa_ctrl_header(data):
	return struct.pack(">HBB", len(data)+1, 0xee, 0) + data

def ipa_ctrl_header(header):
        (plen, ipa_proto, osmo_proto) = struct.unpack(">HBB", header)
        return None if (ipa_proto != 0xee or osmo_proto != 0) else plen

def remove_ipa_ctrl_header(data):
	if (len(data) < 4):
		raise BaseException("Answer too short!")
        plen = ipa_ctrl_header(data[:4])
        if (None == plen):
                raise BaseException("Wrong protocol in answer!")
	if (plen + 3 > len(data)):
		print "Warning: Wrong payload length (expected %i, got %i)" % (plen, len(data) - 3)
	return data[4:plen+3], data[plen+3:]

def connect(host, port):
        if verbose:
                print "Connecting to host %s:%i" % (host, port)

        sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sck.setblocking(1)
        sck.connect((host, port))
        return sck

def send(sck, data):
	if verbose:
		print "Sending \"%s\"" %(data)
	data = prefix_ipa_ctrl_header(data)
	sck.send(data)

def do_set(var, value, op_id, sck):
	setmsg = "SET %s %s %s" %(op_id, var, value)
	send(sck, setmsg)

def do_get(var, op_id, sck):
	getmsg = "GET %s %s" %(op_id, var)
	send(sck, getmsg)

def do_set_get(sck, var, value = None):
        r = random.randint(1, sys.maxint)
        if (value != None):
                s = 'SET_REPLY'
                do_set(var, value, r, sck)
        else:
                s = 'GET_REPLY'
                do_get(var, r, sck)
        (answer, data) = remove_ipa_ctrl_header(sck.recv(4096))
        x  = answer.split()
        if (s == x[0] and str(r) == x[1] and var == x[2]):
                return None if ('SET_REPLY' == s and value != x[3]) else x[3]
        return None

def set_var(sck, var, val):
        return do_set_get(sck, var, val)

def get_var(sck, var):
        return do_set_get(sck, var)

if __name__ == '__main__':
        random.seed()

        parser = OptionParser("Usage: %prog [options] var [value]")
        parser.add_option("-d", "--host", dest="host",
                          help="connect to HOST", metavar="HOST")
        parser.add_option("-p", "--port", dest="port", type="int",
                          help="use PORT", metavar="PORT", default=4249)
        parser.add_option("-g", "--get", action="store_true",
                          dest="cmd_get", help="perform GET operation")
        parser.add_option("-s", "--set", action="store_true",
                          dest="cmd_set", help="perform SET operation")
        parser.add_option("-i", "--id", dest="op_id", default=random.randint(1, sys.maxint),
                          help="set id manually", metavar="ID")
        parser.add_option("-v", "--verbose", action="store_true",
                          dest="verbose", help="be verbose", default=False)
        parser.add_option("-m", "--monitor", action="store_true",
                          dest="monitor", help="monitor the connection for traps", default=False)

        (options, args) = parser.parse_args()

        verbose = options.verbose

        if options.cmd_set and options.cmd_get:
                parser.error("Get and set options are mutually exclusive!")

        if not (options.cmd_get or options.cmd_set or options.monitor):
                parser.error("One of -m, -g, or -s must be set")

        if not (options.host):
                parser.error("Destination host and port required!")

        sock = connect(options.host, options.port)

        if options.cmd_set:
                if len(args) < 2:
                        parser.error("Set requires var and value arguments")
	        do_set(args[0], ' '.join(args[1:]), options.op_id, sock)

        if options.cmd_get:
                if len(args) != 1:
                        parser.error("Get requires the var argument")
	        do_get(args[0], options.op_id, sock)

        data = sock.recv(1024)
        while (len(data)>0):
	        (answer, data) = remove_ipa_ctrl_header(data)
	        print "Got message:", answer

        if options.monitor:
                while True:
                        data = sock.recv(1024)
                        if len(data) == 0:
                                print "Connection is gone."
                                break

                        while len(data) > 0:
                                (answer, data) = remove_ipa_ctrl_header(data)
                                print "Got message:", answer

        sock.close()
