Index: /branch/BTSniff/PM_copy/umit/pm/backend/bt_sniffer/sniffer.py
===================================================================
--- /branch/BTSniff/PM_copy/umit/pm/backend/bt_sniffer/sniffer.py (revision 5397)
+++ /branch/BTSniff/PM_copy/umit/pm/backend/bt_sniffer/sniffer.py (revision 5423)
@@ -1,3 +1,4 @@
 import struct, re
+from threading import Timer
 
 import btlayers
@@ -5,5 +6,5 @@
 from btsniff import * 
 from sniffcommon import *
-from handlers import CollectHandler
+from handlers import CollectHandler, PinCrackCollectHandler
 
 # Additional data types
@@ -119,9 +120,40 @@
 class BtCollectPinCrackRunner(BtCollectRunner):
     
-    def __init__(self, device_name, master_add, slave_add):
+    def __init__(self, device_name, master_add, slave_add, check_interval = 5):
         super(BtCollectPinCrackRunner, self).__init__(device_name)
         self._master_add, self._slave_add = master_add, slave_add
+        
         self._handler =  PinCrackCollectHandler(self._master_add, 
                                                 self._slave_add)
+        # This handler should be run every check_interval seconds to check if 
+        # pin crack is done. 
+        self._callback = None
+        self._timer, self._interval = None, check_interval
+        
+    
+    def register_pincrack_handler(self, handler):
+        '''
+           @param handler Handler signature should be func(str)
+        '''
+        self._callback = handler
+        self.__set_interval_actions()
+    
+    def __set_interval_actions(self):
+        log.debug('__set_interval: _handler is %s' % str(self._handler.is_done()))
+        if self._handler.is_done():
+            self._callback(self._handler.getpin())
+        else:
+            self._timer = Timer(self._interval, self.__set_interval_actions)
+            self._timer.start()
+    
+    def stop_capture(self):
+        super(BtCollectPinCrackRunner, self).stop_capture()
+        self.terminate()
+    
+    def terminate(self):
+        if self._timer is not None: self._timer.cancel()
+        self._handler.close()
+    
+## UTILITY FUNCTIONS
 
 def parse_macs(mac_add):
@@ -179,5 +211,5 @@
 
 def run(handler = None, state = None):
-    print "Sniffer run"
+    log.debug("Sniffer run")
     if not handler:
         handler = handlers.BTSniffHandler()
@@ -197,5 +229,5 @@
     
     if options.timer:
-        print "Timer: %x" % btsniff.get_timer(state, options.device)
+        log.debug("Timer: %x" % btsniff.get_timer(state, options.device))
     
     if options.filter and options.filter >  -1:
Index: /branch/BTSniff/PM_copy/umit/pm/backend/bt_sniffer/sniffcommon.py
===================================================================
--- /branch/BTSniff/PM_copy/umit/pm/backend/bt_sniffer/sniffcommon.py (revision 5397)
+++ /branch/BTSniff/PM_copy/umit/pm/backend/bt_sniffer/sniffcommon.py (revision 5423)
@@ -1,6 +1,11 @@
+'''
+Created on 06-Jul-2009
+
+@author: quekshuy
+'''
 
 MAX_SNIFF_TYPES = 16
 
-# Frontline specific constants
+#Frontline specific constants
 FP_CLOCK_MASK = 0xFFFFFFF
 FP_SLAVE_MASK = 0x02
@@ -20,4 +25,5 @@
 _FILTER_ALL = 7
 
+
 try:
     from PM.Core.Logger import log
@@ -29,4 +35,19 @@
             print debug_str
 
+#class SniffSession(object):
+#    """
+#        Stores the state of the sniff session.
+#        Attributes:
+#            state (State), master (list), slave (list), 
+#            device (string), dump (string), filter (int)
+#            pindata (PinCrackData)
+#    """
+#    def __init__(self, state, master, slave, 
+#                 device, dump, filter = _FILTER_ALL):
+#        self.state = state
+#        self.master, self.slave = master, slave
+#        self.device, self.dump = device, dump        
+#        self.filter = filter
+#        self.pindata = None
 
 
Index: /branch/BTSniff/PM_copy/umit/pm/backend/bt_sniffer/__init__.py
===================================================================
--- /branch/BTSniff/PM_copy/umit/pm/backend/bt_sniffer/__init__.py (revision 5397)
+++ /branch/BTSniff/PM_copy/umit/pm/backend/bt_sniffer/__init__.py (revision 5423)
@@ -5,6 +5,7 @@
 from sniffcommon import *
 from sniffer import *
-
-
-
-
+# packet only exists in the context of PM
+try:
+    from packet import *
+except ImportError:
+    log.debug('Unable to find packet module.')
Index: /branch/BTSniff/PM_copy/umit/pm/backend/bt_sniffer/handlers.py
===================================================================
--- /branch/BTSniff/PM_copy/umit/pm/backend/bt_sniffer/handlers.py (revision 5397)
+++ /branch/BTSniff/PM_copy/umit/pm/backend/bt_sniffer/handlers.py (revision 5423)
@@ -11,17 +11,5 @@
 
 from sniffcommon import * 
-
-
-## This code for taking out of PM, so we do not need to change any code
-try:
-    from packet import BtMetaPacket
-except ImportError:
-    class BtMetaPacket(object):
-        
-        def _init__(self, unit):
-            self.pkt = unit 
-
-        def __getattr__(self, name):
-            return getattr(self.pkt, name)
+from packet import BtMetaPacket
 
 class CollectHandler(btsniff.SniffHandler):
@@ -55,10 +43,10 @@
     
     def recvlmp(self, unit):
-         super(PinCrackCollectHandler, self).recvlmp(unit)
-         # Optimize for more speed
-         lmp = unit.payload
-         if lmp.header.op1 in crack.LMP_PINCRACK_OPCODES \
-            and self._pcr.try_crack(lmp):
-             self._pin = self._pcr.getpin()
+        super(PinCrackCollectHandler, self).recvlmp(unit)
+        lmp = unit.payload
+        log.debug('PinCrackCollectHandler: op1 = %s' % str(lmp.header.op1))
+        if lmp.header.op1 in crack.LMP_PINCRACK_OPCODES \
+            and self._pcr.try_crack(lmp, unit.is_src_master):
+            self._pin = self._pcr.getpin()
     
     def is_done(self):
@@ -85,5 +73,5 @@
         self._state = btsniff.CaptureState()
         if do_pin:
-            print 'do_pin'
+            log.debug('do_pin')
             self._state.pinstate = 1
             self._pcr = crack.PinCrackRunner(master_add, slave_add)
@@ -124,5 +112,5 @@
         length = packet.payload_len
         
-        print 'PL 0x%.2X Ch %.2d %c Clk 0x%.7X Status 0x%.1X Hdr0 0x%.2X [type: %d addr: %d] LLID %d Len %d' \
+        log.debug('PL 0x%.2X Ch %.2d %c Clk 0x%.7X Status 0x%.1X Hdr0 0x%.2X [type: %d addr: %d] LLID %d Len %d' \
                         % (header_len, 
                             channel,
@@ -134,8 +122,8 @@
                             address,
                             llid,
-                            length),
+                            length))
 
     def _printpayload(self, payload):
-        print ' '.join(['%.2x' % d for d in payload.rawdata])
+        log.debug(' '.join(['%.2x' % d for d in payload.rawdata]))
     
     def recvlmp(self, packet):
@@ -143,27 +131,16 @@
         lmp = packet.payload
         if lmp:
-            print 'LMP Tid %d, Op1 %d' % (lmp.header.tid, lmp.header.op1),
+            log.debug('LMP Tid %d, Op1 %d' % (lmp.header.tid, lmp.header.op1))
             if lmp.header.op1 >= 124 and lmp.header.op1 <= 127:
-                print ', Op2 %d' % (lmp.header.op2),
-            print ' '.join(['%.2x' % d for d in lmp.payload.rawdata])
+                log.debug(', Op2 %d' % (lmp.header.op2))
+            log.debug(' '.join(['%.2x' % d for d in lmp.payload.rawdata]))
             
             if self._pcr and self._pcr.try_crack(lmp):
-                print 19 * '='
-                print 'Pin: ', self._pcr.getpin()
-                print 19 * '='
+                log.debug(19 * '=')
+                log.debug('Pin: ', self._pcr.getpin())
+                log.debug(19 * '=')
             
         else:
-            print
-        
-#            pcd = crack._gen_pincrackdata(self._state, lmp.header.op1, lmp.payload.rawdata,
-#                                 self._session.master, self._session.slave)
-#            print '============== pindata state ============'
-#            print self._session.state.pindata
-#            print '========================================='
-#            if pcd:
-#                if pcd.ready_to_crack():
-#                    print 'Pin: ', self.getpin(pcd)
-#                else:
-#                    raise StandardError('recvlmp: dopin: pairing process complete but no pin crack.')
+            log.debug('')
     
     def getpin(self, pincrackdata):
@@ -179,5 +156,5 @@
     def recvl2cap(self, packet):
         self._printpktdetails(packet)
-        print "L2CAP:",
+        log.debug("L2CAP:")
 #        self._printgenpkt(packet.payload)
         self._printpayload(packet.payload)
@@ -185,5 +162,5 @@
     def recvdv(self, packet):
         self._printpktdetails(packet)
-        print 'DV:',
+        log.debug('DV:')
         self._printgenpkt(packet.payload)
         
Index: /branch/BTSniff/PM_copy/umit/pm/backend/bt_sniffer/crack.py
===================================================================
--- /branch/BTSniff/PM_copy/umit/pm/backend/bt_sniffer/crack.py (revision 5397)
+++ /branch/BTSniff/PM_copy/umit/pm/backend/bt_sniffer/crack.py (revision 5423)
@@ -8,5 +8,4 @@
 from btsniff import CaptureState
 
-## BIG CRACK CHANGES
 
 BTPINCRACKDIR = 'btpincrack-v0.3'
@@ -77,5 +76,5 @@
             not self._is_started and not self._pcd:
             
-            log.debug("Gencrack\n")
+            log.debug("Gencrack")
             self._pcd = _gen_pincrackdata(self._capstate, 
                               lmppkt.header.op1, 
@@ -83,5 +82,5 @@
                               self._master_add, 
                               self._slave_add, isPktFromMaster)
-            
+        log.debug("PinCrackRunner: checking that self_pcd is not None")
         if self._pcd and not self._is_started:
             log.debug("Running crack!!!\n")
@@ -99,5 +98,6 @@
     
     def terminate(self):
-        self._pcr.terminate()
+        if self._pcr:
+            self._pcr.terminate()
     
     def get_pcd(self):
@@ -152,5 +152,7 @@
         self._pcd = pincrackdata
         self._master, self._slave = master_add, slave_add
-        print '_pincrackrunner: master', self._master, 'slave: ', self._slave
+        log.debug('_pincrackrunner: master: %s\tslave: %s'\
+                   % (str(self._master), str(self._slave)))
+        
         if not tmpfile:
             import tempfile
@@ -253,38 +255,13 @@
 #######################################
 
-__au_rand_from_master = True
-
-def _gen_pincrackdata(state, op, data_list, master_add, slave_add, from_master):
-    """
-        Returns None when pin not ready. Otherwise return a PinCrackData
-        object, that stores info relevant for pin cracking.
-        
-        @param state     State object
-        @param op        LMP op1 code
-        @data_list       List of integers representing LMP payload
-        @master_add      Master device address
-        @slave_add       Slave device address
-    """
-    
-     ## Check for first cracking packet and remember its source.
-     ## This is very important, so that state does not need to always
-     ## be updated with the source of the latest packet like in the old
-     ## implementation.
-    
-    if op == LMP_OP1_IN_RAND:
-        __au_rand_from_master = from_master    
-        
-    _crack._setpindata(state, op, data_list, from_master)
-    
-    if not state.pinstate == 0xff:
-        return None
-    else:
-        state.pinstate = 1
-        return _create_pincrackdata(state, __au_rand_from_master)
+__originates_master = True
 
 def _create_pincrackdata(state, is_pin_master):
+    log.debug('1')
     pcd = PinCrackData(is_pin_master)
+    log.debug('2')
     type_d = {0:'in_rand', 1:'m_comb_key', 2:'s_comb_key', 3:'m_au_rand', 4:
               's_au_rand', 5:'m_sres', 6:'s_sres'}
+    log.debug('3')
     for i in range(7):
         length = 4 if i >= 5 else 16
@@ -293,5 +270,34 @@
             keyintlist.append(state.pindata[i][j])
         pcd.__setattr__(type_d[i], keyintlist)
-    # print 'create_pincrackdata:\n', str(pcd)
+    log.debug('create_pincrackdata: %s' % str(pcd))
     return pcd
 
+def _gen_pincrackdata(state, op, data_list, master_add, slave_add, from_master):
+    """
+        Returns None when pin not ready. Otherwise return a PinCrackData
+        object, that stores info relevant for pin cracking.
+        
+        @param state           State object
+        @param op              LMP op1 code
+        @param data_list       List of integers representing LMP payload
+        @param master_add      Master device address
+        @param slave_add       Slave device address
+    """
+    
+     ## Check for first cracking packet and remember its source.
+     ## This is very important, so that state does not need to always
+     ## be updated with the source of the latest packet like in the old
+     ## implementation.
+    
+    if op == LMP_OP1_IN_RAND:
+        state.pinmaster = from_master
+            
+    _crack._setpindata(state, op, data_list, from_master)
+    if not state.pinstate == 0xff:
+        return None
+    else:
+        state.pinstate = 1
+        return _create_pincrackdata(state, state.pinmaster)
+
+
+
Index: /branch/BTSniff/PM_copy/umit/pm/backend/bt_sniffer/packet.py
===================================================================
--- /branch/BTSniff/PM_copy/umit/pm/backend/bt_sniffer/packet.py (revision 5423)
+++ /branch/BTSniff/PM_copy/umit/pm/backend/bt_sniffer/packet.py (revision 5423)
@@ -0,0 +1,109 @@
+"""
+    Implementation of the MetaPacket class for BTSniffing.
+    Only used in the context of PM.
+
+"""
+
+from tagger import get_summary
+
+ROLE_STRING_MASTER  = 'M'
+ROLE_STRING_SLAVE   = 'S'
+
+try:
+    from umit.pm.core.logger import log
+except ImportError: 
+    from sniffcommon import log
+    
+try: 
+    from umit.pm.backend.scapy import MetaPacket
+except ImportError:
+    log.debug('Packet.py: not in PM Context')
+    class BtMetaPacket(object):
+        
+        def __init__(self, unit):
+            self.pkt = unit 
+
+        def __getattr__(self, name):
+            return getattr(self.pkt, name)
+else:
+    
+    ###
+    ### Only if we are in the context of PM 
+    ### do we formally define BtMetaPacket
+    ###
+    
+    class BtMetaPacket(MetaPacket):
+        """
+            SniffPacket wrapper. Contains application level information as well. 
+        """
+        
+        NOT_IMPLEMENTED = ['hashret', 'answers', 'insert', 
+                           'complete', 'remove', 'get_datetime',
+                           'get_time', 'get_source', 'get_dest',
+                           'reset', 'get_protocol_bounds', 'haslayer',
+                           'getlayer', 'get_raw_layer',
+                           'rebuild_from_raw_payload', 'get_datalink',
+                           'copy' ]
+        
+        def __init__(self, sniffunit, cfields = None):
+            super(BtMetaPacket, self).__init__(cfields)
+            self.sniffunit = sniffunit
+    #    def __init__(self, proto=None, cfields=None):
+    #        self.root = proto
+    #        self.cfields = cfields or {}
+    
+        def __div__(self, other):
+            """
+                Implemented to maintain consistency with original implementation
+                of MetaPacket. Only manipulate custom fields
+            """
+            cfields = self.cfields.copy()
+            cfields.update(other.cfields)
+            self.cfields = cfields
+            
+            return self
+            
+        def __getattr__(self, name):
+            if name in self.NOT_IMPLEMENTED:
+                log.debug('BTMetaPacket call to %s' % name)
+                raise NotImplementedError('Not required as yet with BTMetaPackets')
+        
+        @classmethod
+        def new(cls, proto_name):
+            """ Keep. For future use when attacking is possible"""
+            raise NotImplementedError('Incompatible with BTMetaPackets')
+        
+        def get_channel(self):
+            return str(self.sniffunit.chan)
+        
+        def get_clock(self):
+            return str(self.sniffunit.clock)
+        
+        def get_role(self):
+            return ROLE_STRING_MASTER if self.sniffunit.is_src_master else ROLE_STRING_SLAVE
+    
+        def get_raw(self):
+            return self.sniffunit.payload.rawdata
+        
+        def summary(self):
+            # TODO: Implement packet tagging
+            return get_summary(self.sniffunit.payload)
+    
+        def get_protocol_str(self):
+            return ''
+    
+        def get_protocols(self):
+            "@returns a list containing the name of protocols"
+            log.debug('BTMetaPacket: call to get_protocols')
+            return []
+        
+        # Custom fields
+    
+        def get_cfield(self, name):
+            return self.cfields[name]
+    
+        def set_cfield(self, name, val):
+            self.cfields[name] = val
+    
+        def unset_cfield(self, name):
+            del self.cfields[name]
