[pkg-fso-commits] [SCM] FSO frameworkd Debian packaging branch, master, updated. milestone4-368-g700ab82

Michael 'Mickey' Lauer mickey at vanille-media.de
Mon Feb 2 18:51:35 UTC 2009


The following commit has been merged in the master branch:
commit 93d20c6f52f77644cc47da698e5802b63927693c
Author: Michael 'Mickey' Lauer <mickey at vanille-media.de>
Date:   Thu Dec 11 22:01:08 2008 +0100

    ogsmd: channel/parser: fix an embarrasing bug in the low-level AT parser that
    has been here from day one. Basically we were always assuming that 'haveCommand'
    [which is used to decide whether a response is solicited or unsolicited] was
    vaild for the whole bunch of bytes that were fed to the parser. This is wrong!
    (Of course, since we may retrieve lots of lines in one row that can refer to
    a number of commands). This may also have been the cause for the hard lock upon
    sending +CGACT=0 (which may actually have been a hang in the parser) that triggered
    an intermediate response concatenated to the OK response: \r\nOK\r\n\r\nNO CARRIER\r\n
    I'm actually very surprised that this could've been undetected for so long...

diff --git a/framework/subsystems/ogsmd/gsm/channel.py b/framework/subsystems/ogsmd/gsm/channel.py
index 4982b2e..df898b5 100644
--- a/framework/subsystems/ogsmd/gsm/channel.py
+++ b/framework/subsystems/ogsmd/gsm/channel.py
@@ -14,7 +14,7 @@ This module provides communication channel abstractions that
 transport their data over a (virtual) serial line.
 """
 
-__version__ = "0.9.9.1"
+__version__ = "0.9.9.2"
 
 from ogsmd.gsm.decor import logged
 import parser
@@ -435,6 +435,7 @@ class QueuedVirtualChannel( VirtualChannel ):
         Called, when an unsolicited response has been parsed.
         """
         self.handleUnsolicitedResponse( response )
+        return not self.q.empty() # parser needs to know the current status
 
     #@logged
     def _handleResponseToRequest( self, response ):
@@ -451,6 +452,7 @@ class QueuedVirtualChannel( VirtualChannel ):
         # relaunch
         if not self.watchReadyToSend:
             self.watchReadyToSend = gobject.io_add_watch( self.serial.fd, gobject.IO_OUT, self._readyToSend )
+        return not self.q.empty() # parser needs to know the current status
 
     #@logged
     def _handleCommandTimeout( self ):
diff --git a/framework/subsystems/ogsmd/gsm/parser.py b/framework/subsystems/ogsmd/gsm/parser.py
index e797cf3..c5f2d30 100644
--- a/framework/subsystems/ogsmd/gsm/parser.py
+++ b/framework/subsystems/ogsmd/gsm/parser.py
@@ -8,10 +8,12 @@ GPLv2 or later
 
 Package: ogsmd.gsm
 Module: parser
-
 """
 
-DEBUG = False
+__version__ = "0.8.0"
+
+import os
+DEBUG = os.environ.get( "FSO_DEBUG_PARSER", False )
 
 #=========================================================================#
 class StateBasedLowlevelAtParser( object ):
@@ -42,6 +44,7 @@ class StateBasedLowlevelAtParser( object ):
         self.lines = []
         self.curline = ""
         self.hasPdu = False
+        self.haveCommand = False
         return self.state_start
 
     def feed( self, bytes, haveCommand ):
@@ -50,6 +53,8 @@ class StateBasedLowlevelAtParser( object ):
         # we better keep the state. We could also enhance the signature
         # to support handing a haveContinuation parameter over to here.
 
+        self.haveCommand = haveCommand
+
         if bytes == "\r\n> ":
             if DEBUG: print "PARSER DEBUG: got continuation character. sending empty response"
             self.response( [] )
@@ -57,35 +62,35 @@ class StateBasedLowlevelAtParser( object ):
             return
 
         for b in bytes:
-            if DEBUG: print "PARSER DEBUG: [%s] feeding %s to %s" % ( ( "solicited" if haveCommand else "unsolicited" ), repr(b), self.state )
+            if DEBUG: print "PARSER DEBUG: [%s] feeding %s to %s" % ( ( "solicited" if self.haveCommand else "unsolicited" ), repr(b), self.state )
 
-            nextstate = self.state( b, haveCommand )
+            nextstate = self.state( b )
             if nextstate is None:
                 print "PARSER DEBUG: WARNING: UNDEFINED PARSER STATE!"
                 print "previous bytes were:", repr(bytes)
                 print "current byte is:", repr(b)
                 print "lines:", repr(self.lines)
                 print "curline:", repr(self.curline)
-                print "solicited:", haveCommand
+                print "solicited:", self.haveCommand
                 self.state = self.reset()
                 break
             else:
                 self.state = nextstate
 
-    def state_start( self, b, s ):
+    def state_start( self, b ):
         if b == '\r':
             return self.state_start_r
         # this is unusal, but we are forgiving
         if b == '\n':
             return self.state_inline
         # this is even more unusual, but we are _really_ forgiving
-        return self.state_inline( b, s )
+        return self.state_inline( b )
 
-    def state_start_r( self, b, s ):
+    def state_start_r( self, b ):
         if b == '\n':
             return self.state_inline
 
-    def state_inline( self, b, s ):
+    def state_inline( self, b ):
         # FIXME checking the number of " in self.curline violates
         # the state machine layer and slows down the parser.
         # We better map this to the state machine instead.
@@ -97,31 +102,30 @@ class StateBasedLowlevelAtParser( object ):
                 return self.state_inline_r
             # usually this should not happen, but some SMS are badly formatted
             if b == '\n':
-                if s:
-                    return self.solicitedLineCompleted()
-                else:
-                    return self.unsolicitedLineCompleted()
+                return self.lineCompleted()
 
-    def state_inline_r( self, b, s ):
+    def state_inline_r( self, b ):
         if b == '\r':
             return self.state_inline_multipleR
         if b == '\n':
-            if s:
-                return self.solicitedLineCompleted()
-            else:
-                return self.unsolicitedLineCompleted()
+            return self.lineCompleted()
 
-    def state_inline_multipleR( self, b, s ):
+    def state_inline_multipleR( self, b ):
         if b == '\r':
             return self.state_inline_multipleR
         if b == '\n':
             if s:
-                return self.solicitedLineCompleted( True )
-            else:
-                return self.unsolicitedLineCompleted( True )
+                return self.lineCompleted( True )
+
+    def lineCompleted( self, multipleR = False ):
+        # FIXME update self.haveCommand for next command
+        if self.haveCommand:
+            return self.solicitedLineCompleted( multipleR )
+        else:
+            return self.unsolicitedLineCompleted( multipleR )
 
     def solicitedLineCompleted( self, multipleR = False ):
-        if DEBUG: print "PARSER DEBUG: solicited line completed, line=", repr(self.curline), "previous lines=", self.lines
+        if DEBUG: print "PARSER DEBUG: [solicited] line completed, line=", repr(self.curline), "previous lines=", self.lines
         if self.curline:
             self.lines.append( self.curline )
             # check for termination
@@ -135,8 +139,8 @@ class StateBasedLowlevelAtParser( object ):
             or self.curline.startswith( "NO ANSWER" ) \
             or self.curline.startswith( "NO CARRIER" ) \
             or self.curline.startswith( "NO DIALTONE" ):
-                if DEBUG: print "PARSER DEBUG: solicited response completed"
-                self.response( self.lines )
+                if DEBUG: print "PARSER DEBUG: [solicited] response completed"
+                self.haveCommand = self.response( self.lines )
                 return self.reset()
             else:
                 self.curline = ""
@@ -147,18 +151,18 @@ class StateBasedLowlevelAtParser( object ):
             return self.state_inline
 
     def unsolicitedLineCompleted( self, multipleR = False ):
-        if DEBUG: print "PARSER DEBUG: unsolicited line completed"
+        if DEBUG: print "PARSER DEBUG: [unsolicited] line completed, line=", repr(self.curline)
         self.lines.append( self.curline )
 
         if self.hasPdu:
-            if DEBUG: print "PARSER DEBUG: unsolicited line pdu completed, sending."
+            if DEBUG: print "PARSER DEBUG: [unsolicited] line pdu completed, sending."
             if not self.curline:
                 if DEBUG: print "Empty line before PDU, ignoring"
                 # We have some cases where there is an empty line before the pdu
                 self.lines.pop()
                 return self.state_inline
             self.hasPdu = False
-            self.unsolicited( self.lines )
+            self.haveCommand = self.unsolicited( self.lines )
             return self.reset()
 
         # Now this is slightly suboptimal. I tried hard to prevent even more protocol knowledge
@@ -174,11 +178,11 @@ class StateBasedLowlevelAtParser( object ):
                 self.curline = ""
                 return self.state_inline
             else:
-                self.unsolicited( self.lines )
+                self.haveCommand = self.unsolicited( self.lines )
                 return self.reset()
 
         else:
-            if DEBUG: print "PARSER DEBUG: unsolicited message with empty line. Ignoring."
+            if DEBUG: print "PARSER DEBUG: [unsolicited] message with empty line. Ignoring."
             return self.state_inline
 
 #=========================================================================#

-- 
FSO frameworkd Debian packaging



More information about the pkg-fso-commits mailing list