Index: tooltron.py
===================================================================
--- tooltron.py	(revision 260)
+++ tooltron.py	(revision 261)
@@ -126,8 +126,10 @@
           while not self.stop_thread:
              # hang until we either get keyboard input or are told to stop
              [active,a,b] = select.select([sys.stdin,self.rpipe],[],[])
+
              if not self.stop_thread:
                 l = raw_input()
+
                 cv.acquire()
                 try:
                    id = re.search('%([0-9]*)=.*', l)
@@ -146,9 +148,9 @@
            cv.acquire()
            idready = True
            lastid=None
+           threadDoneExcp=ctrlDException("thread exiting cleanly")
            cv.notify()
            cv.release()
-           threadDoneExcp=ctrlDException("thread exiting cleanly")
        except Exception, e:
           threadDoneExcp = e #TODO: provide a line number or something?
        finally:
@@ -215,7 +217,13 @@
           raise threadDoneExcp
 
        print ">>> wait"
-       cv.wait()
+       try:
+          cv.wait()
+       # if the user hits ctrl-c, cleanly exit
+       except KeyboardInterrupt:
+          print "cv.wait() got a keyboard interupt!"
+          cv.release()
+          return None
 
     print ">>> idready set"
 
@@ -278,13 +286,40 @@
          if id != None:
             print "\--------------------\n",strftime("%Y.%m.%d %H:%M:%S \n"),"id# ", id.group(1)
 
-            # If we can't get through to the cardbox, restart the loop
-            if common.sendKeyRequest() == False:
-               print "ERROR: timeout waiting for key ack"
-               logMessage("ERROR: exceeded max retries waiting for cardbox")
+
+            # Send a key request
+            common.sendMessage(2, common.TT_GET_KEY, "")
+            
+            # listen for an ACK or a key response
+            msg = common.readMessage()
+            if msg == None:
+               print "ERROR: Timeout waiting for response from key request!"
                continue
+
+            # resp hols the key response, so set it to None since we don't have one yet
+            resp = None
+
+            [src,dest,cmd,data] = msg
+            #TODO: no magic number '2' for cardbox or '1' for server
+            if src == 2 and dest == 1:
+               if cmd == common.TT_ACK:
+                  print "got ACK from cardbox"
+               elif cmd == common.TT_SEND_KEY:
+                  print "got key response instead of ACK from cardbox"
+                  print "using key: ", data
+                  resp = data[0]
+               else:
+                  print "ERROR: got some other packet type: ", cmd, " (data = {", data, "})"
+                  continue
+            else:
+               print "ERROR: got confusing packet. Excpecting something from cardbox (2) but got:"
+               common.printMsg(msg)
+               continue
+
+            # start the timer so we can timeout if we are still waiting for a key response
             startTime = time.time()
 
+            # while we are (or might be) waiting for a key response, do the MySQL stuff
             if cursor != None:
                cursor.close()
 
@@ -343,8 +378,8 @@
 
             print user
 
-
-            resp = None
+            # while we don't have a valid response
+            # Note that this might already be set above when we were heoping for an ACK
             while resp==None:
                try:
                   resp = common.readKey()
@@ -361,48 +396,49 @@
                   common.sendMessage(2,common.TT_TIMEOUT,'')
                   break
 
-               #if we have a valid response
-               #sometimes the FTDI chip seems to give a zero as a string when power is reset
-               if resp != None and ord(resp) != 0 and resp != common.TT_TIMEOUT:
+            #if we have a valid response
+            #sometimes the FTDI chip seems to give a zero as a string when power is reset
+            if resp != None and ord(resp) != 0 and resp != common.TT_TIMEOUT:
 
-                  toolName = reverseTool(resp)
-                  toolNameLong = toolName + " (k="+str(resp)+"("+str(ord(resp))+"), t="+str(keypad2toolID(resp))+")"
-                  print "request:",resp,"(",ord(resp),") ",toolNameLong
+               toolName = reverseTool(resp)
+               toolNameLong = toolName + " (k="+str(resp)+"("+str(ord(resp))+"), t="+str(keypad2toolID(resp))+")"
+               print "request:",resp,"(",ord(resp),") ",toolNameLong
 
-                  if acl.count(resp) > 0:
-                     common.sendAck(2)
-                     time.sleep(0.5)
-                     sendTool(resp)
-                     print "ACCESS GRANTED"
-                     logMessage(user+" ACCESSED tool "+toolNameLong)
-                     if common.checkAck(resp):
-                        print "ACK"
-                        toolFails[toolName] = 0
-                     else:
-                        print "NO ACK!!!!"
-                        logMessage("tool "+toolNameLong+" did not ACK")
-                        toolFails[toolName] += 1
-                        if toolFails[toolName] > common.MAX_TOOL_FAILS:
-                           #TODO: send email
-                           logMessage("WARNING: tool "+toolNameLong+
-                                      " has failed to ACK "+
-                                      str(common.MAX_TOOL_FAILS)+" times in a row.")
-
+               if acl.count(resp) > 0:
+                  common.sendAck(2)
+                  time.sleep(0.5)
+                  sendTool(resp)
+                  print "ACCESS GRANTED"
+                  logMessage(user+" ACCESSED tool "+toolNameLong)
+                  if common.checkAck(resp):
+                     print "ACK"
+                     toolFails[toolName] = 0
                   else:
-                     common.sendNack(2)
-                     print "ACCESS DENIED!!"
-                     logMessage(user + " DENIED on tool "+toolNameLong)
+                     print "NO ACK!!!!"
+                     logMessage("tool "+toolNameLong+" did not ACK")
+                     toolFails[toolName] += 1
+                     if toolFails[toolName] > common.MAX_TOOL_FAILS:
+                        #TODO: send email
+                        logMessage("WARNING: tool "+toolNameLong+
+                                   " has failed to ACK "+
+                                   str(common.MAX_TOOL_FAILS)+" times in a row.")
 
-                  clear_id()
+               else:
+                  common.sendNack(2)
+                  print "ACCESS DENIED!!"
+                  logMessage(user + " DENIED on tool "+toolNameLong)
 
-               elif resp == common.TT_TIMEOUT:
-                  print "TIMEOUT sent from keypad"
-                  continue
-               else:
-                  break
+               clear_id()
+
+            elif resp == common.TT_TIMEOUT:
+               print "TIMEOUT sent from keypad"
+               continue
+            else:
+               break
    except ctrlDException:
       print "got a ctrl-D, exiting cleanly"
       logMessage("NOTICE: tooltron going down because of ctrl-D press")
+      
    finally:
       if not threadDone:
          print "stopping id reader thread..."
