[Nym3-commit] r32 - trunk

nym3-devel@lists.noreply.org nym3-devel@lists.noreply.org
Wed, 28 Jul 2004 18:12:14 +0200


Author: jr
Date: 2004-07-28 18:12:13 +0200 (Wed, 28 Jul 2004)
New Revision: 32

Modified:
   trunk/message.py
Log:
commands from the client to the server :
	the classes are implanted and we can build objects
	from program data or from a string being read with StrReader.
	it compiles but has not been tested
	
Todo : next things to be done in message.py


Modified: trunk/message.py
===================================================================
--- trunk/message.py	2004-07-27 09:55:49 UTC (rev 31)
+++ trunk/message.py	2004-07-28 16:12:13 UTC (rev 32)
@@ -1,4 +1,4 @@
-class BadMessage(Exception):
+class ParseError(Exception):
         def __init__(self,value):
                 self.value=value
         def __str__(self):
@@ -10,64 +10,387 @@
         def __str__(self):
                 return repr(self.value)
 
-        
+def strToIntBE(s):
+	"""return the Int coded by the string s with the big endian convention"""
+	def aux(s,ac):
+		if(s == ""):
+			return ac
+		else:
+			return aux(s[1:],256*ac+ord(s[0]))
+	return aux(s,0)
+
+def intToStrBE(n,mod):
+	"""return a string coding the n modulo 256^mod in big endian"""
+	def aux(n,ac,mod):
+		if(mod == 0):
+			return ac
+		else:
+			return aux(n/256,chr(n%256)+ac,mod-1)
+	return aux(n,"",mod)
+
+def isMsgIdList(l):
+	def isMsgId(e):
+		if(len(e)==20): # et son type str?
+			return True
+		else:
+			return False
+	lb=map(isMsgId,l)
+	if(reduce(lambda x,y : x and y,lb)):
+		return True
+	else:
+		return False
+
+surbLength = 2104        
 sigLength = 256
 seqNoLength = 20
+msgIdLength = 20
 
 class StrReader:
+	"""wraps a string and gives method to read it chunk by chunk"""
         def __init__(self,s):
+	    """initialize by wrapping a string"""	
             self.s = s
             self.a = 0
             self.b = 0
-        def sub(self):
-            return self.s[self.a:self.b]
+	def isEnd(self):
+		return (b == len(s))
         def next(self,n):
-                self.a = self.b
+		"""return the next n characters"""
+		if(n<0):
+			raise BadArgument("StrReader.next : n < 0")
+		self.a = self.b
                 self.b = self.b + n
+		return self.s[self.a:self.b]
+	def readHeader(self):
+		return Header.read(self)
+	def readCommandCToS(self):
+		try:
+			ct = ord(self.next(1))
+			cs = strToIntBE(self.next(3))
+			if (ct == 0):
+				a=Create()
+			elif (ct == 1):
+				a=Create2()
+			elif (ct == 2):
+				a=Surb()
+			elif (ct == 3):
+				a=Newpk()
+			elif (ct == 4):
+				a=Relay()
+			elif (ct == 5):
+				a=Get()
+			elif (ct == 6):
+				a=Summarize()
+			elif (ct == 7):
+				a=Delete()
+			elif (ct == 8):
+				a=Policy()
+			else:
+				raise ParseError("Undefined Command Type")
+			a.fromStrReader(self,cs)
+			return a
+		except IndexError:
+			raise ParseError("Bad Formed Command")
+	def readNym(self,start,cs):
+		nl = ord (self.next(1))
+		if(self.b + nl - start > cs):
+			raise ParseError("Bad Formed Command")
+		return self.next(nl)
+	def readNymList(self,start,cs):
+		try:
+			l = []
+			while(self.b < start + cs):
+				l.append(self.readNym(start,cs))
+			return l
+		except ParseError: #is it really necessary?
+			raise
+	def readMsgId(self,start,cs):
+		if(self.b + msgIdLength - start > cs):
+			raise ParseError("Bad Formed Command")
+		return self.next(msgIdLength)
+	def readMsgIdList(self,start,cs):
+		try:
+			l = []
+			while(self.b < start + cs):
+				l.append(self.readMsgId(start,cs))
+			return l
+		except ParseError: #is it really necessary?
+			raise
+	
+class Header:
+	def __init__(self):
+		"""Build a Header empty object"""
+		pass
+	def fromData(self,nym,seqNo,sig=""):
+		"""Fill a Header Object from a nym and sequence number and sig if provided
+		sig : signature
+		nl : nym length
+		nym : nym
+		seqNo : sequence number which identifies the message
+		length : header length"""
+		if(len(seqNo) != seqNoLength):
+			raise BadArgument("Buildheader.__init__ : seqNo length doesn't match seqNoLength")  
+		if(sig == ""):
+			self.sig = chr(0) * sigLength
+		else:
+			if(len(sig) != sigLength):
+				raise BadArgument("Buildheader.__init__ : sig length doesn't match sigLength")  
+		self.nl = len(nym)
+		self.nym = nym
+		self.seqNo = seqNo
+		#self.length = sigLength + 1 + self.nl + seqNoLength
+	def __str__(self):
+		return self.sig + chr(self.nl) + self.nym + self.seqNo
+	def fromStrReader(self,sr):
+		"""Fill a Header from a StrReader 
+		sig : signature
+		nl : nym length
+		nym : nym
+		seqNo : sequence number which identifies the message
+		length : header length"""
+		try:
+			self.sig = sr.next(sigLength)
+			self.nl = ord(sr.next(1))
+			self.nym = sr.next(nl)
+			self.seqNo = sr.next(seqNoLength)
+		except IndexError:
+			raise ParseError("Header too short")
 
 
-class Header:
-    def __str__(self):
-        return self.sig + chr(self.nl) + self.nym + self.seqNo
+## class ReadHeader(Header):
+##     def __init__(self,sr):
+##         """builds a header from a StrReader 
+##         sig : signature
+##         nl : nym length
+##         nym : nym
+##         seqNo : sequence number which identifies the message
+##         length : header length"""
+##         try:
+##             self.sig = sr.next(sigLength)
+##             self.nl = ord(sr.next(1))
+##             self.nym = sr.next(nl)
+##             self.seqNo = sr.next(seqNoLength)
+##             self.length = sr.b
+##         except IndexError:
+##             raise ParseError("Parse Error : Header too short")
+        
+## class BuiltHeader(Header):
+##     def __init__(self,nym,seqNo):
+##         """Builds a header from a nym and and sequence number
+##         sig : signature
+##         nl : nym length
+##         nym : nym
+##         seqNo : sequence number which identifies the message
+##         length : header length"""
+##         if(len(seqNo) != seqNoLength):
+##             raise BadArgument("Buildheader.__init__ : seqNo length doesn't match seqNoLength")  
+##         self.sig = chr(0) * sigLength
+##         self.nl = len(nym)
+##         self.nym = nym
+##         self.seqNo = seqNo
+##         self.length = sigLength + 1 + self.nl + seqNoLength
 
-class ReadHeader(Header):
-    def __init__(self,header):
-        """builds a header from the beginning of a string 
-        sig : signature
-        nl : nym length
-        nym : nym
-        seqNo : sequence number which identifies the message
-        length : header length"""
-        try:
-            sr = StrReader(header)
-            sr.next(sigLength)
-            self.sig = sr.sub()
-            sr.next(1)
-            self.nl = ord(sr.sub())
-            sr.next(nl)
-            self.nym = sr.sub()
-            sr.next(seqNoLength)
-            self.seqNo = sr.sub()
-            self.length = sr.b
-        except IndexError:
-            raise BadMessage("Bad formed message : header too short")
-        
-class BuiltHeader(Header):
-    def __init__(self,nym,seqNo):
-        """Builds a header from a nym and and sequence number
-        sig : signature
-        nl : nym length
-        nym : nym
-        seqNo : sequence number which identifies the message
-        length : header length"""
-        if(len(seqNo) != seqNoLength):
-            raise BadArgument("Buildheader.__init__ : seqNo length doesn't match seqNoLength")  
-        self.sig = chr(0) * sigLength
-        self.nl = len(nym)
-        self.nym = nym
-        self.seqNo = seqNo
-        self.length = sigLength + 1 + self.nl + seqNoLength
-        
-        
-H= BuiltHeader("JR","01234567890123456789")
+class CommandCToS:
+	pass
+
+class Create(CommandCToS):
+	"""Create command"""
+	def __init__(self):
+		"""Build a Create empty object"""
+		pass
+	def fromData(self,l,pw=""):
+		"""Fill a Create Object from a list of nyms and a proof of work"""
+		self.list=l
+		self.pw=pw
+	def fromStrReader(self,sr,cs):
+		"""Fill a Create command from a StrReader
+		raise ParseError if it is malformed"""
+		start=sr.b
+		nNym = ord(sr.next(1))
+		self.pW = "" #what is a proof of work?
+		try:
+			self.nymList = sr.readNymList(start,cs)
+		except ParseError:
+			raise ParseError("Bad Formed Command : Create")
+		#nNym is redundant, we use it to make sure the message is well formed
+		if(nNym != len(self.nymList)):
+		   raise ParseError("Bad Formed Command : Create")
+			
+
+class Create2(CommandCToS):
+	"""Create2 command"""
+	def __init__(self):
+		"""Build a Create2 empty object"""
+		pass
+	def fromData(self,cr):
+		"""Fill Create2 from a string containing the response to a challenge"""
+		self.cr=cr
+	def fromStrReader(self,sr,cs):
+		"""Fill a Create2 command from a StrReader
+		raise ParseError if it is malformed"""
+		self.cr=sr.next(cs)
+		
+class Surb(CommandCToS):
+	"""Surb command"""
+	def __init__(self):
+		"""Build a Surb empty object"""
+		pass
+	def fromData(self,s):
+		"""Fill a Surb Object from a string containing Surbs"""
+		self.surbs=s
+	def fromStrReader(self,sr,cs):
+		"""Fill a Surb Object from a StrReader
+		raise ParseError if it is malformed"""
+		if(cs%surbLength != 0):
+			raise ParseError("Bad Formed Command : Surb")
+		self.surbs=sr.next(cs)
+
+class Newpk(CommandCToS):
+	"""Newpk command"""
+	def __init__(self):
+		"""Build a Newpk empty object"""
+		pass
+	def fromData(self,sid,senc):
+		"""Fill a Newpk Object from 2 strings containing an ASN-1 encoded RSA key"""
+		self.kid=sid
+		self.kenc=senc
+	def fromStrReader(self,sr,cs):
+		"""Fill a Newpk Object from a StrReader
+		raise ParseError if it is malformed"""
+		try:
+			id_l=strToIntBE(sr.next(2))
+			if( (id_l != 128) and (id_l != 256)):
+				raise ParseError("Bad Formed Command : Newpk")
+			idl_2=cs-2-id_l
+			if( (id_l2 != 128) and (id_l2 != 256)):
+				raise ParseError("Bad Formed Command : Newpk")
+			self.kid=sr.next(id_l)
+			self.kenc=sr.next(id_l2)
+		except IndexError:
+			raise ParseError("Bad Formed Command : Newpk")
+class Relay(CommandCToS):
+	"""Relay command"""
+	def __init__(self):
+		"""Build a Relay empty object"""
+		pass
+	def fromData(self,rt,ri,body):
+		"""Fill a Relay Object from a 3 strings : routing type(2 octets) routing info and body"""
+		if(len(rt) !=2):
+			raise BadArgument("Relay.fromData : RT size isn't 2 bytes")
+		self.rt=rt
+		self.rs=len(ri)
+		self.ri=ri
+		self.body=body
+	def fromStrReader(self,sr,cs):
+		"""Fill a Relay Object from a StrReader
+		raise ParseError if it is malformed"""
+		try:
+			self.rs=strToIntBE(sr.next(2))
+			self.rt=sr.next(2)
+			self.ri=sr.next(self.rs)
+			self.body=sr.next(cs-4-self.rs)
+		except (BadArgument, IndexError):
+			raise ParseError("Bad Formed Command : Relay")
+		
+class Get(CommandCToS):
+	"""Get command"""
+	def __init__(self):
+		"""Build a Get empty object"""
+		pass
+	def fromData(self,li):
+		"""Fill a Get Object from a list of message id (=string of len 20)"""
+		#check that each element of the list has 20 bytes
+		if( not isMsgIdList(li)):
+			raise BadArgument("Get.fromData : li is not a list of message id")
+		self.l=li
+	def fromStrReader(self,sr,cs):
+		"""Fill a Get Object from a StrReader
+		raise ParseError if it is malformed"""
+		start=sr.b
+		try:
+			self.l=sr.readMsgIdList(self,start,cs)
+		except (ParseError,IndexError):
+			raise ParseError("Bad Formed Command : Get")
+		
+class Summarize(CommandCToS):
+	"""Summarize command"""
+	def __init__(self):
+		"""Build a Summarize empty object"""
+		pass
+	def fromData(self,n,m):
+		"""Fill a Summarize Object from the max number of synopsis to retrieve (int)  and the message id of a message older than the messages we want the synopsis from (string of len 20)
+		the int is considered modulo 256^2"""
+		n_mod=n % (256*256)
+		self.num=n_mod
+		if(len(m)!=msgIdLength): # or m is not a str
+			raise BadArgument(" Summarize.fromData : m is not a valid message ID")
+		self.after=m
+	def fromStrReader(self,sr,cs):
+		"""Fill a Summarize Object from a StrReader
+		raise ParseError if it is malformed"""
+		if(cs != 2+msgIdLength):
+			raise ParseError("Bad Formed Command : Summarize")
+		try:
+			self.num=strToIntBE(sr.next(2))
+			self.after=sr.next(msgIdLength)
+		except IndexError:
+			raise ParseError("Bad Formed Command : Summarize")
+		
+class Delete(CommandCToS):
+	"""Delete command"""
+	def __init__(self):
+		"""Build a Delete empty object"""
+		pass
+	def fromData(self,):
+		"""Fill a Delete Object from a list of message ID (string of length msgIdLength"""
+		#check that each element of the list has 20 bytes
+		if( not isMsgIdList(li)):
+			raise BadArgument("Delete.fromData : li is not a list of message id")
+		self.l=li
+	def fromStrReader(self,sr,cs):
+		"""Fill a Delete Object from a StrReader
+		raise ParseError if it is malformed"""
+		start=sr.b
+		try:
+			self.l=sr.readMsgIdList(self,start,cs)
+		except (ParseError,IndexError):
+			raise ParseError("Bad Formed Command : Delete")
+		
+class Policy(CommandCToS):
+	"""Policy command"""
+	def __init__(self):
+		"""Build a Policy empty object"""
+		pass
+	def fromData(self,opt,val):
+		"""Fill a Policy Object from 2 str : the option name and its value
+		It is the caller work to convert adequatly into a string the value he wants to be sent"""
+		#do we check the option names' validity?
+		self.opt=opt
+		self.val=val
+	def fromStrReader(self,sr,cs):
+		"""Fill a Policy Object from a StrReader
+		raise ParseError if it is malformed"""
+		try:
+			le=ord(sr.next(1))
+			self.opt=sr.next(le)
+			self.val=sr.next(cs-1-le)
+		except (IndexError,BadArgument):
+			raise ParseError("Bad Formed Command : Policy")
+		
+#empty class will be used as a framework fo CommandSToC classes
+class Frame(CommandCToS):
+	"""command"""
+	def __init__(self):
+		"""Build a empty object"""
+		pass
+	def fromData(self,):
+		"""Fill a Object from """
+	def fromStrReader(self,sr,cs):
+		"""Fill a Object from a StrReader
+		raise ParseError if it is malformed"""
+
+
+H= Header()
+H.fromData("JR","01234567890123456789")
 print H
+del H