#!/usr/bin/env python2.7

import sys
import dbus
import dbus.service
import dbus.glib
import gobject
import socket
import string
import struct
import threading
from threading import Thread
import time
from dbus.mainloop.glib import DBusGMainLoop

# IDs specific to Linux nfc
AF_NFC = 39
SOL_NFC = 280
NFC_LLCP_MIUX = 1

# Sample test code - compliant with nfcpy phdc test agent
thermometer_assoc_req = \
    "E200 0032 8000 0000" \
    "0001 002A 5079 0026" \
    "8000 0000 A000 8000" \
    "0000 0000 0000 0080" \
    "0000 0008 3132 3334" \
    "3536 3738 0320 0001" \
    "0100 0000 0000"

thermometer_assoc_res = \
    "E300 002C 0003 5079" \
    "0026 8000 0000 8000" \
    "8000 0000 0000 0000" \
    "8000 0000 0008 3837" \
    "3635 3433 3231 0000" \
    "0000 0000 0000 0000" \

assoc_release_req = "E40000020000"
assoc_release_res = "E50000020000"

#========================================
# Display helper
def hexdump( chars, sep, width ):
	while chars:
		line = chars[:width]
		chars = chars[width:]
		line = line.ljust( width, '\000' )
		print "%s%s%s" % ( sep.join( "%02x" % ord(c) for c in line ),
			 sep, quotechars( line ))


def quotechars( chars ):
	return ''.join( ['.', c][c.isalnum()] for c in chars )

#========================================
class PhdcPeerManager:
    def __init__(self, agent_fd):
	#Grab the agent ....
	print 'Init PhdcPeerManager thread'
	self.r_fd = agent_fd.take()
	print 'Agent fd:', str(self.r_fd)

    def run( self):
	print 'Run PhdcPeerManager thread: ', str(self.r_fd)
	self.sock = socket.fromfd(self.r_fd, AF_NFC, socket.SOCK_STREAM)
        try:
            while True:
		miu = self.sock.getsockopt(SOL_NFC, NFC_LLCP_MIUX)
		print 'MIU=', miu

                while True:
                    data = self.sock.recv(16)
                    if data == None:
		       print 'no data'
		       break

                   #analyze frame
                    print 'analyze'
                    size = struct.unpack(">H", data[0:2])[0]
                    apdu = data[2:]

                    #should i read more data ?
                    while len(apdu) < size:
                        data = self.sock.recv(10)
                        if data == None: break
                        hexdump(data, ':', 16)
                        apdu += data
                    print "[ieee] <<< {0}".format(str(apdu).encode("hex"))
                    if apdu.startswith("\xE2\x00"):
                        apdu = bytearray.fromhex(thermometer_assoc_res)
                    elif apdu.startswith("\xE4\x00"):
                        apdu = bytearray.fromhex(assoc_release_res)
                    else:
                        apdu = apdu[::-1]
                    time.sleep(0.2)
                    print "[ieee] >>> {0}".format(str(apdu).encode("hex"))
                    data = struct.pack(">H", len(apdu)) + apdu
                    for i in range(0, len(data), miu):
                        self.sock.send(str(data[i:i+miu]))

                print "remote peer {0} closed connection".format(agent_fd)
                print "leaving ieee manager"
                self.sock.close()

        except IOError as e:
		if e.errno == errno.EPIPE:
			print 'Remote disconnect'
		else:
			print "I/O error({0}): {1}".format(e.errno, e.strerror)
        finally:
		print 'Finally exit'
		stop()

	def stop(self):
		print 'Stop PhdcPeerManager:', str(self.r_fd)
		self._Thread__stop()

#===================================================
''' Phdc Manager Class
'''
class SimplePhdcManager(dbus.service.Object):

	@dbus.service.method('org.neard.PHDC.Manager',
					in_signature='',
					out_signature='')
	def Release(self):
		print 'Release'
		mainloop.quit()


	''' Called on incoming agents
	'''
	@dbus.service.method('org.neard.PHDC.Manager',
					in_signature='h',
					out_signature='')
	def NewConnection(self, agent_fd):
		print'Launch Phdc Manager thread for fd:', str(agent_fd)
		self.server = PhdcPeerManager(agent_fd)
		print'Run Server'
		self.server.run()
		print'Leave Server'
		return

	''' Called when the agent ends (from phdc_close)
	'''
	@dbus.service.method('org.neard.PHDC.Manager',
					in_signature='hi', out_signature='')
	def Disconnection(self,agent_fd, i_err):
		print'Stop Phdc Manager thread'
		self.server.stop()
		return

''' Main loop
This sample installs two PHDC Managers:
	* Simple: simulates a thermometer data exchange
	* Validation: Validation Manager for NFC Forum PHDC)
'''
if "__main__" == __name__:
	dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

	print 'PHDC Simple Manager Test'
	bus = dbus.SystemBus()
	obj = bus.get_object("org.neard", "/org/neard");
	neard_manager = dbus.Interface(obj, "org.neard.PHDC")

	simple_path = '/Simple'
	valid_path = '/Validation'

	print 'Creating & registering PHDC Simple Manager'
	simpleobject = SimplePhdcManager(bus, simple_path)

	d = dbus.Dictionary({'Role': 'Manager', 'Path': simple_path,
			'ServiceName': 'urn:nfc:sn:phdc' }, signature='sv')
	neard_manager.RegisterAgent(d)

	print 'Creating & Registering Validation Manager'

	validationobj= SimplePhdcManager(bus, valid_path)
	d = dbus.Dictionary({'Role': 'Manager', 'Path': valid_path,
		'ServiceName': 'urn:nfc:xsn:nfc-forum.org:phdc-validation' },
		 signature='sv')
	neard_manager.RegisterAgent(d)

	mainloop = gobject.MainLoop()

try:
        mainloop.run()

except(KeyboardInterrupt):
	#Call for unregister...
        neard_manager.UnregisterAgent(simple_path, 'Manager')
        neard_manager.UnregisterAgent(valid_path, 'Manager')
