[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