PERFORCE change 166949 for review
Zachariah Riggle
zjriggl at FreeBSD.org
Mon Aug 3 02:53:55 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=166949
Change 166949 by zjriggl at zjriggl_tcpregression on 2009/08/03 02:53:10
Periodic submit
Affected files ...
.. //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/echoServer.py#5 edit
.. //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/loggable.py#5 edit
.. //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/logging.conf#5 edit
.. //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/pcsextension/StringField.py#3 edit
.. //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/pcsextension/__init__.py#8 edit
.. //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/pcsextension/backup.tar#3 edit
.. //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/pcsextension/checksum.py#2 edit
.. //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/pcsextension/decorators.py#4 edit
.. //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/pcsextension/field.py#2 edit
.. //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/pcsextension/hwAddress.py#4 edit
.. //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/pcsextension/ipAddress.py#5 edit
.. //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/pcsextension/networkPort.py#4 edit
.. //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/pcsextension/payload.py#4 edit
.. //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/pcsextension/pseudoipv4.py#3 edit
.. //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/segmentBuffer.py#3 edit
.. //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/sniffLocalhost.py#5 edit
.. //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/tcpConstructor.py#6 edit
.. //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/tcpFilter.py#7 edit
.. //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/tcprecvdaemon.py#3 edit
.. //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/tcpstatemachine.py#8 edit
.. //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/test.html#5 edit
.. //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/testconfig.py#7 edit
Differences ...
==== //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/echoServer.py#5 (text+ko) ====
==== //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/loggable.py#5 (text+ko) ====
@@ -6,12 +6,13 @@
logging.config.fileConfig( "logging.conf" )
( logging.FIELD_CHANGE,
- logging.RESPONSE_GENERATION,
- logging.PACKET_TRANSMIT,
+ logging.RESPONSE_GENERATION ) = range( logging.DEBUG - 2, logging.DEBUG )
+
+( logging.PACKET_TRANSMIT,
logging.PACKET_RECEIVED,
logging.PACKET_SENT,
logging.VALIDATE,
- logging.STATE_CHANGE ) = range( logging.INFO - 7, logging.INFO )
+ logging.STATE_CHANGE ) = range( logging.INFO - 5, logging.INFO )
logging.addLevelName( logging.FIELD_CHANGE, "FIELD" )
logging.addLevelName( logging.RESPONSE_GENERATION, "\033[1;36mGENERATE\033[1;m" )
@@ -19,7 +20,9 @@
logging.addLevelName( logging.PACKET_RECEIVED, "\033[1;31mRECVD\033[1;m" )
logging.addLevelName( logging.PACKET_SENT, "\033[1;31mSENT\033[1;m" )
logging.addLevelName( logging.VALIDATE, "VALIDATE" )
-logging.addLevelName( logging.STATE_CHANGE, "STATE" )
+logging.addLevelName( logging.STATE_CHANGE, "\033[1;37;44mSTATE\033[1;m" )
+
+# 1;37;44
# print '\033[1;36mGENERATE\033[1;m'
# print '\033[1;36mCyan like Caribbean\033[1;m'
==== //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/logging.conf#5 (text+ko) ====
==== //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/pcsextension/StringField.py#3 (text+ko) ====
==== //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/pcsextension/__init__.py#8 (text+ko) ====
@@ -3,7 +3,7 @@
import struct
import socket
import sys
-
+import re
from pcs.packets.ipv4 import ipv4
from pcs.packets.tcp import tcp
from pcs.packets.tcpv6 import tcpv6
@@ -41,3 +41,14 @@
def inet_atol( ipString ):
return inet_ntol( socket.inet_aton( ipString ) )
+
+def wireSharkFormatBytes(x):
+ twoBits = r"(\w\w)"
+ octet = "((%s ){8})" % twoBits
+ twoBytes = "((%s ){2})" % octet
+
+ x = re.sub(twoBits,r"\1 ",x)
+ x = re.sub(octet,r"\1 ",x)
+ x = re.sub(twoBytes,r"\1\n",x)
+ return x
+
==== //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/pcsextension/backup.tar#3 (binary) ====
==== //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/pcsextension/checksum.py#2 (text+ko) ====
==== //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/pcsextension/decorators.py#4 (text+ko) ====
@@ -186,7 +186,7 @@
'''
ops = func() or {}
- name=ops.get('prefix','_')+func.__name__ # property name
+ name=ops.get('name') or ops.get('prefix','_')+func.__name__ # property name
fget=ops.get('fget',lambda self:getattr(self, name))
fset=ops.get('fset',lambda self,value:setattr(self,name,value))
fdel=ops.get('fdel',lambda self:delattr(self,name))
@@ -241,7 +241,7 @@
return property (fget, fset, fdel, func.__doc__)
-def uint(max=2**32):
+def uint(limit=2**32):
'''
>>> from pcsextension.decorators import *
>>> lim = 5
@@ -272,4 +272,4 @@
fset = lambda self,value: setattr(self, name, (value % max))
fdel = lambda self: delattr(self, value)
return property(fget, fset, fdel)
- return unsignedInteger
+ return unsignedInteger
==== //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/pcsextension/field.py#2 (text+ko) ====
@@ -5,69 +5,118 @@
'''
class Field( object ):
+ '''
+ Base class for an extensible field class. Allows the field to be represented
+ in various formats with ease, as needed by the developer. This allows byte-
+ order and representation issues to be alleviated, as well as string-of-bytes
+ representation to be simplified for any byte order.
+ '''
name = ""
value = None
width = 8
networkByteOrder = False
- def __init__( self, default = 0, width = None, networkByteOrder = False ):
+ def __init__( self, default = 0, width = 8, networkByteOrder = False ):
self.width = width
self.networkByteOrder = networkByteOrder
+
if isinstance( default, int ):
self.setInteger( default )
if isinstance( default, str ):
self.setAscii( default )
+ if isinstance( default, Field):
+ self.setNetworkBytes(default.getNetworkBytes())
def setAscii( self, x ):
+ '''
+ Set the value, given its textual representation, e.g. '12345' or '127.0.0.1'
+ '''
pass
def getAscii( self ):
+ '''
+ @see setAscii
+ '''
return ""
def setInteger( self, x ):
+ '''
+ Set the value, given its numeric representation in host-byte-order, e.g. 12345.
+ '''
pass
def getInteger( self ):
+ '''
+ @see setInteger
+ '''
return 0
def setNetworkInteger( self, x ):
+ '''
+ Set the value, given its numeric representation in network-byte-order, e.g. 14640
+ '''
pass
def getNetworkInteger( self ):
+ '''
+ @see setNetworkInteger
+ '''
return 0
def setBytes( self, x ):
+ '''
+ Set the value as a string of bytes in host-byte-order, e.g. '\x30\x39'
+ '''
pass
def getBytes( self ):
+ '''
+ @see setBytes
+ '''
return ""
- def getBytesShifted( self, shiftedBits ):
- pass
-
def setNetworkBytes( self, x ):
+ '''
+ Sets the value as a string of bytes in network-byte-order, e.g. '\x39\x30'
+ '''
pass
def getNetworkBytes( self ):
+ '''
+ @see setNetworkBytes
+ '''
return ""
- def getNetworkBytesShifted( self, shiftedBits ):
- return getNetworkBytes()
-
def setPCS( self, x ):
+ '''
+ Sets the value in the format native to the PCS (Packet Construction
+ Set) library. For example, network-byte-order integer for TCP ports,
+ or byte-string for Ethernet addresses.
+ '''
pass
- def getPCS( self, x ):
+ def getPCS( self ):
+ '''
+ @see setPCS
+ '''
return self.getNetworkBytes()
def encode( self ):
+ '''
+ Returns the same value as getBytes/getNetworkBytes as instructed by
+ __init__ or the networkByteOrder property.
+ '''
if self.networkByteOrder:
return self.getNetworkBytes()
else:
return self.getBytes()
def decode( self, bytes ):
+ '''
+ Calls setBytes/setNetworkBytes as instructed by __init__ or the
+ networkByteOrder property.
+ '''
if self.networkByteOrder:
self.setNetworkBytes( bytes )
else:
@@ -88,41 +137,15 @@
return False
def bound( self ):
- if width == None:
+ '''
+ Ensures that the value returned by getBytes() is no longer than
+ self.width bits and that the value returned by getInteger is no
+ larger than an integer of self.width bits would allow.
+ '''
+ if self.width == None:
return
- elif width == 8:
- if ( width == 8 and len( self.getBytes() ) > width * 8 ) or \
- ( getInteger() > ( ( 2 ** self.width ) - 1 ) ):
- raise Exception, "Value exceeds bit-width"
-
- def __add__( self, x ):
-
- if isinstance( x, Field ):
- f = Field( width = self.width + x.width )
- bytes = self.getNetworkBytes()
- nextBytes = x.getNetworkBytes()
-
- # If either of the widths are NOT even mod 8
- # ord
- # chr
- if self.width % 8 != 0:
-
- lastByte = bytes[:-1]
-
- # Will the field fit in the remaining bits of the last byte
- # In the below example 'X' = the appended bytes, 'O' = existing, current bytes
- # Bit 1 2 3 4 5 6 7 8
- # O O O
- # X X X X X
- # O O O X X X X X
- if x.width <= ( 8 - self.width ):
- nextBits = ord( nextBytes[0] ) >> self.width
- nextBits = nextBits | ord( lastByte )
- joined = struct.pack( "!B%d", nextBits )
- f.setNetworkBytes( self.getNetworkBytes()[:-1] + joined )
-
- # The field will not fit in the remaining space
-
- else:
- f.setNetworkBytes( self.getNetworkBytes() + x.getNetworkBytes() )
+ elif self.width == 8:
+ if ( self.width == 8 and len( self.getBytes() ) > self.width * 8 ) or \
+ ( self.getInteger() > ( ( 2 ** self.width ) - 1 ) ):
+ raise Exception, "Value exceeds bit-width %i" % self.width
==== //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/pcsextension/hwAddress.py#4 (text+ko) ====
==== //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/pcsextension/ipAddress.py#5 (text+ko) ====
@@ -20,6 +20,12 @@
def __init__( self, default = 0, width = None, networkByteOrder = False, version = AF_INET ):
self.version = version
Field.__init__( self, width = width, default = default, networkByteOrder = networkByteOrder )
+
+ # Override the default Field.__init__ behavior. If the string's length is 4, it is obviously
+ # a byte-string as opposed to an IP address.
+ if type(default) == str:
+ if len(default) == 4:
+ self.nbo = default
def setAscii( self, x ):
self.nbo = inet_pton( self.version, x )
==== //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/pcsextension/networkPort.py#4 (text+ko) ====
@@ -30,10 +30,10 @@
return str( self.ho )
def setBytes( self, bytes ):
- self.ho = unpack( "H", bytes )
+ self.ho = unpack( "H", bytes )[0]
def setNetworkBytes( self, bytes ):
- self.ho = unpack( "!H", bytes )
+ self.ho = unpack( "!H", bytes )[0]
def getBytes( self ):
return pack( "H", self.ho )
@@ -51,7 +51,11 @@
self.ho = ntohs( x )
def getNetworkInteger( self ):
+ print "%s %s" % (type(self.ho), self.ho)
return htons( self.ho )
+
+ def getPCS(self):
+ return self.getInteger()
def __eq__( self, x ):
if isinstance( x, int ):
==== //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/pcsextension/payload.py#4 (text+ko) ====
==== //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/pcsextension/pseudoipv4.py#3 (text+ko) ====
==== //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/segmentBuffer.py#3 (text+ko) ====
@@ -4,7 +4,9 @@
@author: zach
'''
-class segmentBuffer(list):
+from pcsextension.decorators import prop
+
+class segmentBuffer(object):
'''
The segmentBuffer class allows pseudo-random access to a list, given an
initial offset, and maximum offset. The benefit of this is that we get
@@ -14,103 +16,219 @@
using 4GB+ of memory, or use the segmentBuffer class.
Example:
- >>> x = segmentBuffer(base=100,max=110)
- >>> x += ['a','b','c']
- >>> len(x)
- 3
- >>> x[100:102]
- ['a','b','c']
-
- >>> y = segmentBuffer(base = 5, max=10)
- >>> y += range(0,10)
- >>> y
- [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
- >>> y[5]
+ >>> from segmentBuffer import *
+ >>> sb = segmentBuffer(base=10, limit=15)
+ >>> sb += range(8)
+ >>> sb[10] # The first item is at [10]
0
- >>> y[5:4]
- [0, 1, 2, 3, 4, 5, 6, 7, 8]
- >>> y[5:5]
- [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
-
-
+ >>> sb[11] # The second item is at [11]
+ 1
+ >>> sb # However, the items are in the proper order
+ [0, 1, 2, 3, 4, 5, 6, 7]
+ >>> sb[10:] # And are properly sliced
+ [0, 1, 2, 3, 4, 5, 6, 7]
+ >>> sb[10:2] # And the slices wrap-around at limit
+ [0, 1, 2, 3, 4, 5, 6]
+ >>> sb[2:10] # And slices stop when it hits a gap.
+ [7]
+ >>> sb == sb[10:] # Truth works just fine.
+ True
+ >>> sb += 2 # The offset is incremented easily
+ >>> sb # Notice that the first two items are deleted
+ [2, 3, 4, 5, 6, 7]
+ >>> len(sb) # The length indeed goes down 8->2
+ 6
+ >>> sb += range(100,200)
+ >>> len(sb) # Adding 100 items keeps the correct length
+ 15
+ >>> sb # Only items up to the limit are added
+ [2, 3, 4, 5, 6, 7, 100, 101, 102, 103, 104, 105, 106, 107, 108]
+ >>> sb2 = sb + range(300,400)
+ >>> sb is sb2 # Addition operator returns a new object.
+ False
+ >>> sb2 += 3 # The other object can be incremented
+ >>> [i for i in sb if i not in sb2]
+ [2, 3, 4] # Just an example to show the difference
+ >>> sb[12:15] # This shows that the items were taken off the front
+ [2, 3, 4]
+ >>> sb[12:2]
+ [2, 3, 4, 5, 6]
+ >>> sb2[12:2] # The indexes for the remaining items do not change
+ [5, 6] # Although the deleted items are gone.
+ >>> sb
+ [2, 3, 4, 5, 6, 7, 100, 101, 102, 103, 104, 105, 106, 107, 108]
+ >>> sb2
+ [5, 6, 7, 100, 101, 102, 103, 104, 105, 106, 107, 108]
'''
__MAX = (2**31) - 1
+ limit = __MAX
+ buffer = []
+
+ @prop
+ def base():
+ '''
+ Base index. Advancing the base index will remote items from the front of the list.
+ The base can only be incremented in value, and will be wrapped at 'limit'.
+
+ '''
+ return {'fset': lambda self,x: self.setBase(x)}
_base = 0
- _max = __MAX
+
+ @prop
+ def nextIndex():
+ return {'fget': lambda self: self.getNextIndex(),# (len(self) + self.base),
+ 'fset': None}
+
+ def getNextIndex(self):
+ return len(self)+self.base
+
+ def setBase(self, x):
+ '''
+ Modifies the base. Erases any existing items up to, but excluding, the
+ new base.
+ '''
+ # print "Setting base to %i" % x
+ # print "... %s if %s < %s else %s" % (self._getIndex(x), x, len(self), len(self))
+ # deleteUpToOffset = self._getIndex(x) if x < len(self) else len(self)
+ deleteUpToOffset = min(self._getIndex(x),len(self))
+ # print "Deleting up to offset %s" % deleteUpToOffset
+ self._base = x % self.limit
+ # print "_base is now %i" % self._base
+ # print "Buffer before delete: %s" % self.buffer
+ del self.buffer[0:deleteUpToOffset]
+ # print "Buffer after delete: %s" % self.buffer
+
+ def __contains__(self,x):
+ return self.buffer.__contains__(x)
+
+ def __iadd__(self,x):
+ '''
+ Adding an integer has the effect of advancing the 'base', and
+ deleting the leading elements. 'base' is modulo'd by 'limit' so
+ that it will properly wrap around to zero if needed, while retaining
+ the same indexes for items that are not deleted.
+
+ NOTE: If the list is full, no more items can be 'added'.
+ '''
+ if type(x) in (int,long):
+ self.base += x
+ elif type(x) in (list,tuple,segmentBuffer):
+
+ self.buffer += x
+
+ # Prevent the list from being extended too long.
+ if len(self) > self.limit:
+ # Note that we are referring to the 'limit'th item directly, not
+ # its redirected index. This is because we are actually deleting
+ # items beyond the boundary that should not exist.
+ del self.buffer[self.limit:self.__MAX]
+
+
+ # retVal = segmentBuffer(base=self.base, limit=self.limit)
+ # retVal.buffer = self.buffer[:]
+
+ return self
+
+ def __add__(self,x):
+ tmp = segmentBuffer(self)
+ tmp += x
+ return tmp
+
+ def __len__(self):
+ return self.buffer.__len__()
def __eq__(self, x):
- if not isinstance(x,list) and not isinstance(x,tuple):
+ '''
+ Compares to a list or tuple object.
+ For whatever reason, list.__eq__ doesn't evaluate properly.
+ '''
+ # Only compare to list, tuples, or the same class
+ if type(x) not in (list,tuple,type(self)):
return False
+ # If we're not the same length, DEF not the same.
if len(self) != len(x):
return False
- for i in range(0,len(self)):
- if self[i] != x[i]:
+ # If we are comparing against a list or tuple, compare it to
+ # our internal buffer.
+ comparisonList = self.buffer
+
+ # Otherwise, we are comparing against a segmentBuffer. Compare
+ # it to ourself.
+ if type(x) == type(self):
+
+ # Check the other fields
+ if x.limit != self.limit or x.base != self.base:
+ return False
+
+ comparisonList = self
+
+ # Iterate over each item
+ for i in range(len(self)):
+ if comparisonList[i] != x[i]:
return False
-
+
+ # Haven't found any differences.
return True
- def __init__(self, base=None, max=None):
- list.__init__(self)
+ def __init__(self, copyList=None, base=0, limit=2**32):
+ if type(copyList) == segmentBuffer:
+ self.buffer = copyList.buffer[:]
+ self.base = copyList.base
+ self.limit = copyList.limit
+
+ # Don't proceed to set other values below. Just use the
+ # copied values.
+ return
+ elif type(copyList) in (list,tuple):
+ self.buffer = copyList
+ else:
+ self.buffer = []
- if base > 0:
- self._base = base
- if max > 0:
- self._max = max
+ if base >= 0:
+ self.base = base
+ if limit >= 0:
+ self.limit = limit
def __delslice__(self, i, j):
- # print "delslice(%s,%s)" % (i,j)
- for item in range(i,j):
- del self[item]
+ for (ii,jj) in self._getIndices(i, j):
+ self.buffer.__delslice__(ii,jj)
def __delitem__(self,i):
- # print "delitem(%s)" % (i)
-
index = self._getIndex(i)
- if index is None:
- raise IndexError, "list index out of range"
-
- list.__delitem__(self, index)
+ self.buffer.__delitem__(index)
def __getslice__(self, i, j):
- # # print "getslice(%s,%s)" % (i,j)
# return [list.__getitem__(self,item) for item in self._getIndices(i, j)]
# return [self[item] for item in range(i,j) ]
- retVal = []
- for (a,b) in self._getIndices(i, j):
- retVal += list.__getslice__(self, a, b)
- return retVal
+ retVal = []
+ for (a,b) in self._getIndices(i, j):
+ retVal += self.buffer.__getslice__(a, b)
+ return retVal
def __getitem__(self,i):
index = self._getIndex(i)
if index is None: index = self.__MAX
- return list.__getitem__(self,index)
+ return self.buffer.__getitem__(index)
def __setslice__(self, i, j, k):
- # print "setslice(%s,%s,%s)" % (i,j,k)
- #for x,i in enumerate(self._getIndices(i, j)):
- # self.__setitem__(x,k[i])
-
indices = self._getIndices(i, j)
-
offset = 0
- print indices
-
for (a,b) in indices:
num = b-a
- list.__setslice__(self, a, b, k[offset:offset+num])
+ self.buffer.__setslice__(a, b, k[offset:offset+num])
offset += num
def __setitem__(self, i, x):
index = self._getIndex(i)
if index is None: index = self.__MAX
- list.__setitem__(self, index, x)
+ self.buffer.__setitem__(index, x)
def _getIndices(self, i, j):
@@ -133,7 +251,7 @@
# else:
# jj = self._getIndex(j)
# if jj is None:
-# jj = self._max - self._base
+# jj = self.limit - self.base
retVal = ()
@@ -160,92 +278,70 @@
Retrieves the actual index of an item.
'''
- # For this method, assume that base=5, max=10.
- print "getIndex(%i)" % i
+ # For this method, assume that base=5, limit=10.
retVal = None
# Special cases defined for quickness.
# The base is always at ZERO offset.
- if i == self._base:
+ if i == self.base:
return 0
- # 'Max' is the "END" of the list, AND it is the 0th item.
+ # 'limit' is the "END" of the list, AND it is the 0th item.
# '__MAX' is the absolute maximum value, and is the value provided
# when we are given an empty-ended slice, i.e [3:]
- elif i == self._max or i == self.__MAX:
- return (self._max - self._base)
-
+ elif i == self.limit:
+ return (self.limit - self.base)
+ elif i == self.__MAX:
+ return len(self)
# elif i == self.__MAX:
-# return self._getIndex(self._max)
+# return self._getIndex(self.limit)
# i.e. self[12], should refer to self[2].
# i.e. self[10], should refer to self[0]
- elif self._max < i:
- return self._getIndex(i - self._max)
- # retVal = self._getIndex(i - self._max)
+ elif self.limit < i:
+ return self._getIndex(i - self.limit)
+ # retVal = self._getIndex(i - self.limit)
# i.e. self[6] is stored at [1], or i-base.
- elif self._base < i < self._max:
- retVal = i - self._base
+ elif self.base < i < self.limit:
+ retVal = i - self.base
- # i.e. self[2] is stored at [10+2], or max+i
- elif 0 <= i < self._base:
- retVal = self._getIndex(self._max) + i
+ # i.e. self[2] is stored at [10+2], or limit+i
+ elif 0 <= i < self.base:
+ retVal = self._getIndex(self.limit) + i
# i.e. self[-1] is stored at the real self[-1].
elif i < 0:
- retVal = self._getIndex(self._max + i) # Note we are adding a negative
+ retVal = len(self) + i
+
+ if retVal > len(self):
+ return None
return retVal
-#
-# if i == self.__MAX:
-# # return self._getIndex(self._max - 1) + 1
-# return len(self)
-#
-# if i == self._max:
-# return self._max - self._base
-#
-# # Negative indices count from the back...
-# if i < 0:
-# # Make sure it's not TOO negative...
-# if abs(i) > self._max:
-# retVal = self._getIndex(i + self._max)
-# else:
-# retVal = len(self) + i # Note that we "add" a negative
-#
-# elif self._max <= i:
-# # retVal = None # Still none...
-# return
-#
-# # If it's less than the base, then the index 0 is the max'th item, and
-# # go from there.
-# elif i < self._base:
-# # Wrap...
-# retVal = self._getIndex(self._max) + i
-#
-# # If it's over the max, decrement and re-do.
-# # elif self._max <= i:
-# # retVal = self._getIndex(i - self._max)
-#
-# # The N'th item is offset from the base.
-# elif self._base <= i < self._max:
-# retVal = i - self._base
-#
-# else:
-# print 'error: could not calculate index for %s' % i
-# # print "%s -> %s" % (i,retVal)
-#
-# # Don't return an out-of-bounds index...
-# if retVal >= len(self):
-# # print "OOB"
-# return None
-#
-# return retVal
+ #def __repr__(self):
+ # # return str( [self[i] for i in self._getIndices(0,len(self))] )
+ # return str( self.buffer[:] )
+ # # return self.__repr__()
+
def __repr__(self):
- print 'repr!!'
- # return str( [self[i] for i in self._getIndices(0,len(self))] )
- return str( self[:] )
+ return '%s(limit=%i,base=%i,copyList=%s+%s)' % \
+ (self.__class__.__name__, self.limit, self.base, self[self.base:0], self[self.limit:] if self._getIndex(0) is not None else [])
+
+ def __iter__(self):
+ return self.buffer.__iter__()
+
+ def update(self, newBuffer):
+
+ if newBuffer is self:
+ return self
+
+ if type(newBuffer) == type(self):
+ # return '... is new buffer'
+ return newBuffer
- def __str__(self):
- print 'str!!'
- return self.__repr__()+ if type(newBuffer) in (list,tuple):
+ # return '... is just a list or tuple'
+ self.buffer = newBuffer[:]
+
+ return self
+
==== //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/sniffLocalhost.py#5 (text+ko) ====
==== //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/tcpConstructor.py#6 (text+ko) ====
==== //depot/projects/soc2009/zjriggl_tcpregression/src/tcpregression/tcpFilter.py#7 (text+ko) ====
@@ -10,23 +10,31 @@
from pcs.packets.tcp import tcp
from pcs.packets.tcpv6 import tcpv6
from pcs.packets.ethernet import ethernet
+from pcsextension import wireSharkFormatBytes
from pcsextension.ipAddress import IpAddress
from pcsextension.networkPort import NetworkPort
from pcsextension import findIpLayer, findTcpLayer
+from pcsextension.decorators import prop
import pprint
+import binascii
+from threading import RLock
class tcpFilter( object ):
log = None
pcapHandle = None
doRead = False
-
+ lock = RLock()
+
@prop
def interface():
- return {'doc': 'Interface used with the TCP Filter. If this interface is different from the'
- ' current interface, the current one is closed, and the new one is opened automatically.',
- 'fset': lambda self, x: self.openInterface( x ) }
- self._interface = None
-
+ '''
+ Interface used with the TCP Filter. If this interface is different
+ from the current interface, the current one is closed, and the new
+ one is opened automatically.
+ '''
+ return {'fset': lambda self, x: self.openInterface( x ) }
+ _interface = None
+
def __init__( self, interfaceName ):
self.log = tcplog( self )
self.interface = interfaceName
@@ -34,73 +42,143 @@
def openInterface( self, interfaceName ):
# Is it already opened with this interface?
if self.interface is interfaceName:
- log.info( 'Tried to re - open same interface: % s' % self.interface )
- return
- else:
- self._interface = interfaceName
+ self.log.debug( 'Tried to re-open same interface: % s' % self.interface )
# Open the interface
try:
- self.pcapHandle = PcapConnector( self.interface )
- self.log.info( "Opened %s" % self.interface )
- # self.pcapHandle = IP4Connector();
+ self.pcapHandle = PcapConnector( interfaceName )
+ self.log.info( "Opened %s" % interfaceName )
+ self._interface = interfaceName
except:
- self.log.error( "Could not open interface %s" % self.interface )
+ self.log.error( "Could not open interface %s" % interfaceName )
+
+ def getPcapConnector(self):
+ '''
+ Returns the PCAP handle.
+ '''
+ return self.pcapHandle
def read( self ):
+ '''
+ Reads a packet in the form of a string of bytes from the PCAP handle.
+ '''
return self.pcapHandle.readpkt()
def write( self, bytes ):
- self.log.pktsent( pprint.pformat( bytes ) )
- self.pcapHandle.write( bytes, len( bytes ) )
+ '''
+ Writes a string of bytes to the PCAP handle.
+ '''
+ return self.pcapHandle.write( bytes, len( bytes ) )
+
+ def setBlocking(self, block=False):
+ '''
+ Sets the blocking mode on the PCAP handle.
+ '''
+ self.log.debug("Setting blocking mode to %s" % block)
+ self.pcapHandle.file.setnonblock(block)
+
+ def packetDestinedForIP(self, packet, ip):
+ '''
+ Returns True if the provided packet has a IP layer and its destination
+ is the provided IP address.
+ Returns False otherwise.
+ '''
+ # If the IP address is a string ("127.0.0.1") or byte array ('\x7f\x00\x00\x01')
+ # we need to convert it into an integer representation of the same.
+ ip = IpAddress(ip).getPCS()
+
+ ipLayer = findIpLayer(packet)
+ if ipLayer is None:
+ return False
+
+ if ip == ipLayer.dst:
+ return True
+
+ return False
+
+ def packetDestinedForPort(self, packet, port):
+ '''
+ Returns True if the provided packet has a TCP layer and its destination
+ is the provided port.
+ Returns False otherwise.
+ '''
+ port = NetworkPort( port ).getPCS()
+
+ tcpLayer = findTcpLayer( packet )
+ if tcpLayer is None:
+ return False
+
+ if port == tcpLayer.dport:
+ return True
+
+ return False
+
- def readFilteredByIP( self, ip ):
+ def readFilteredByIP( self, ip, block=True ):
"""
- Reads packets until a packet is found going either to or from the specified IP address
- is discovered. Returns the first matching packet.
+ Reads packets until a packet is found that is destined to the specified
+ IP address is discovered. Returns the first matching packet.
@param ip IpAddress or dotted-quad string
- @return A pcs.Packet object
+ @return A pcs.Packet object, or None if there are no packets on the
+ queue and non-blocking IO is used.
"""
-
-# if isinstance(ipAddress,int):
-# ipAddress = intToBytes(ipAddress)
-
- # If the IP address is a string ("127.0.0.1") or byte array ('\x7f\x00\x00\x01')
- # we need to convert it into an integer representation of the same.
- if isinstance( ip, str ):
- tmp = IpAddress()
- tmp.setAscii( ip )
- ip = tmp
-
+
+ self.log.debug("Waiting on lock")
+ self.lock.acquire(blocking=True)
+ self.log.debug("Have lock")
+ self.setBlocking(block)
+
+ packet = None
+
while True:
+ print "loop"
packet = self.read()
+
+ # None will only return [1] on error or [2] if using asynchronous
+ # I/O and there are no waiting packets.
+ if packet is None or self.packetDestinedForIP(packet, ip):
+ break
+
+ self.lock.release()
+ self.log.debug("Released lock")
+
+ if packet is None:
+ self.log.debug("Returning NONE")
+
+ return packet
- ipLayer = findIpLayer( packet )
-
- if ipLayer == None:
- continue
-
- # srcIP.setPCS( ipLayer.src )
- # dstIP.setPCS( ipLayer.dst )
-
- if ipLayer.src == ip.getPCS() or ipLayer.dst == ip.getPCS():
- return packet
-
- def readFilteredByTuple( self, ipAddress, port ):
+ def readFilteredByTuple( self, ipAddress, port, block=True ):
"""
- Reads packets until a packet is found going either to or from [1] the specified
- IP address and [2] the specified port. Returns the first matching packet.
+ Reads packets until a packet is found that is destined to:
+ [1] the specified IP address
+ [2] the specified port.
+ Returns the first matching packet.
+
@param IpAddress object or dotted-quad string ('127.0.0.1')
@param NetworkPort object or integer port number.
- @return A pcs.Packet object.
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list