SF.net SVN: fclient: [347] trunk/sandbox/fcp2/message.py
Status: Pre-Alpha
Brought to you by:
jurner
|
From: <jU...@us...> - 2008-03-09 12:28:36
|
Revision: 347
http://fclient.svn.sourceforge.net/fclient/?rev=347&view=rev
Author: jUrner
Date: 2008-03-09 05:28:33 -0700 (Sun, 09 Mar 2008)
Log Message:
-----------
moved persistent params handling to message
Modified Paths:
--------------
trunk/sandbox/fcp2/message.py
Modified: trunk/sandbox/fcp2/message.py
===================================================================
--- trunk/sandbox/fcp2/message.py 2008-03-08 11:15:48 UTC (rev 346)
+++ trunk/sandbox/fcp2/message.py 2008-03-09 12:28:33 UTC (rev 347)
@@ -1,7 +1,8 @@
-"""Freennet Client Protocol message
+"""Freennet Client Protocol messages
"""
import os, sys
+import base64
import socket
#--> rel import hack
@@ -30,6 +31,7 @@
#
#********************************************************************************
MessagesAll = {}
+PersistentParamsSep = '0x01'
class MessageMeta(type):
@@ -45,105 +47,127 @@
#
#********************************************************************************
class MessageBase(object):
- """Class wrapping a Fcp message
-
- Sample use::
+ """Class wrapping a Fcp message
+
+ Sample use::
- msg = Messsage(
- consts.Message.ClientHello,
- ExpectedVersion='2.0',
- Name='MyConnectionName'
- )
- msg['Name'] = 'another'
- msg['Name']
- >> 'another'
-
- msg.send(mySocket)
-
- @ivar data: (bytes) data carried along with the message or None
- @ivar name: (str) message name
- @ivar params: (dict) message params
+ msg = Message.ClientHello(
+ ExpectedVersion='2.0',
+ Name='MyConnectionName'
+ )
+ msg['Name'] = 'another'
+ msg['Name']
+ >> 'another'
+
+
+ @ivar data: (bytes) data carried along with the message or None
+ @ivar name: (str) message name
+ @ivar params: (dict) message params
+ """
+ __metaclass__ = MessageMeta
+
+ name = ''
+ _additional_params_ = {}
+ _param_types_ = {}
+ _persistent_params_ = ()
+
+
+ @classmethod
+ def __eq__(klass, other):
+ return klass.name == other.name
+
+ @classmethod
+ def __ne__(klass, other):
+ return klass.name != other.name
+
+
+ def __init__(self, data=None, **params):
"""
- __metaclass__ = MessageMeta
+ @param data: data associated to the message
+ @param params: {field-name: value, ...} of parameters of the message
+ """
+ params.update(self._additional_params_.copy())
- name = ''
- _additional_params_ = {}
- _param_types_ = {}
-
+ self.data = data
+ self.params = params
- @classmethod
- def __eq__(klass, other):
- return klass.name == other.name
-
- @classmethod
- def __ne__(klass, other):
- return klass.name != other.name
-
-
- def __init__(self, data=None, **params):
- """
- @param data: data associated to the message
- @param params: {field-name: value, ...} of parameters of the message
- """
- params.update(self._additional_params_.copy())
- self.data = data
- self.params = params
-
-
- def get(self, name, default=None):
- """Returns the message parameter 'name' or 'default' """
- return self.params.get(name, default)
+ def get(self, name, default=None):
+ """Returns the message parameter 'name' or 'default' """
+ return self.params.get(name, default)
+
+
+ def __getitem__(self, name):
+ """Returns the message parameter 'name' """
+ return self.params[name]
+
+
+ def __setitem__(self, name, value):
+ """Sets the message parameter 'name' to 'value' """
+ self.params[name] = value
+
+ def pprint(self):
+ """Returns the message as nicely formated human readable string"""
+ out = ['', '>>' + self.name, ]
+ for param, value in self.params.items():
+ if isinstance(param, PrivateParam):
+ continue
+ out.append('>> %s=%s' % (param, value))
- def __getitem__(self, name):
- """Returns the message parameter 'name' """
- return self.params[name]
-
-
- def __setitem__(self, name, value):
- """Sets the message parameter 'name' to 'value' """
- self.params[name] = value
+ if self.data is None:
+ out.append('>>EndMessage')
+ else:
+ out.append('>>Data')
+ out.append(self.data)
+ return '\n'.join(out)
+
+
+ def toString(self):
+ """Returns the message as formated string ready to be send"""
+ out = [self.name, ]
+ for param, value in self.params.items():
+ if isinstance(param, PrivateParam):
+ continue
+ # convert python to fcp value if necessary
+ paramType = self._param_types_.get(param, None)
+ if paramType is not None:
+ value = paramType.pythonToFcp(value)
+
+ out.append('%s=%s' % (param, value))
- def pprint(self):
- """Returns the message as nicely formated human readable string"""
- out = ['', '>>' + self.name, ]
- for param, value in self.params.items():
- if isinstance(param, PrivateParam):
- continue
- out.append('>> %s=%s' % (param, value))
-
- if self.data is None:
- out.append('>>EndMessage')
- else:
- out.append('>>Data')
- out.append(self.data)
- return '\n'.join(out)
+ if self.data is None:
+ out.append('EndMessage\n')
+ else:
+ out.append('Data')
+ out.append(self.data)
+ return '\n'.join(out)
+
+
+ #TODO:
+ # 1. if one setter / getter fails no setter / getter result should assumed to be valid
+ # 2. log errors
+ #
+ #
+ def setPersistentParams(self, persistentData):
+ params = persistentData.split(PersistentParamsSep)
+ if len(params) > len(self._persistent_params_):
+ raise ValueError('Too many parameters in data')
+ elif len(params) < len(self._persistent_params_):
+ raise ValueError('Too few parameters in data')
+ for n, (getter, setter) in enumerate(self._persistent_params_):
+ setter(self, params[n])
+
+ def getPersistentParams(self):
+ out = []
+ for n, (getter, setter) in enumerate(self._persistent_params_):
+ #TODO: check if PersistentParamsSep is in data returned
+ out.append(getter(self))
+ return PersistentParamsSep.join(out)
- def toString(self):
- """Returns the message as formated string ready to be send"""
- out = [self.name, ]
- for param, value in self.params.items():
- if isinstance(param, PrivateParam):
- continue
-
- # convert python to fcp value if necessary
- paramType = self._param_types_.get(param, None)
- if paramType is not None:
- value = paramType.pythonToFcp(value)
-
- out.append('%s=%s' % (param, value))
-
- if self.data is None:
- out.append('EndMessage\n')
- else:
- out.append('Data')
- out.append(self.data)
- return '\n'.join(out)
-
#***************************************************************************************
#
# param types for config message
@@ -437,7 +461,6 @@
PrivateParam('InitTime'): 0, # when was the request started?
#TODO: not really necessary, but we need it for persistent params
- PrivateParam('FilenameCollision'): consts.FilenameCollision.HandleNever,
PrivateParam('PersistentUserData'): '', # any user defined persistent data
# non persistent params
@@ -488,18 +511,56 @@
PrivateParam('InitTime'): 0, # when was the request started?
}
+
+PersistentParamsGet = (
+ (
+ lambda msg: str(msg.__getitem__('RequestType')),
+ lambda msg, value: msg.__setitem__('Requesttype', int(value)),
+ ),
+ (
+ lambda msg: str(msg.__getitem__('InitTime')),
+ lambda msg, value: msg.__setitem__('InitTime', float(value)),
+ ),
+ (
+ lambda msg: str(msg.__getitem__('FilenameCollision')),
+ lambda msg, value: msg.__setitem__('FilenameCollision', int(value)),
+ ),
+ (
+ lambda msg: base64.b64encode(msg.__getitem__('PersistentUserData')),
+ lambda msg, value: msg.__setitem__('PersistentUserData', base64.b64decode(value)),
+ ),
+ )
+
+PersistentParamsPut = (
+ (
+ lambda msg: str(msg.__getitem__('RequestType')),
+ lambda msg, value: msg.__setitem__('Requesttype', int(value)),
+ ),
+ (
+ lambda msg: str(msg.__getitem__('InitTime')),
+ lambda msg, value: msg.__setitem__('InitTime', float(value)),
+ ),
+ (
+ lambda msg: base64.b64encode(msg.__getitem__('PersistentUserData')),
+ lambda msg, value: msg.__setitem__('PersistentUserData', base64.b64decode(value)),
+ ),
+ )
#********************************************************************************
#
#********************************************************************************
#TODO: register new message type?
-def newMessageType(name, paramTypes=None, additionalParams=None):
+def newMessageType(name, paramTypes=None, additionalParams=None, persistentParams=None):
kws = {
'name': name,
- '_additional_params_': additionalParams if additionalParams is not None else {},
- '_param_types_': paramTypes if paramTypes is not None else {},
+ '_additional_params_': {} if additionalParams is None else additionalParams,
+ '_persistent_params_': () if persistentParams is None else persistentParams,
+ '_param_types_': {} if paramTypes is None else paramTypes,
}
return type(name, (MessageBase, ), kws)
+
+#TODO: _persistent_params_ ...define in all message classes or not? Bogus for most,
+# but makes customization of individual classes harder for useres
#********************************************************************************
# some additional messages we define for uniformity
#********************************************************************************
@@ -544,6 +605,7 @@
class ClientGet(MessageBase):
name = consts.Message.ClientGet
_additional_params_ = AdditionalGetParams
+ _persistent_params_ = PersistentParamsGet
_param_types_ = {
'BinaryBlob': types.FcpTypeBool,
'DSOnly': types.FcpTypeBool,
@@ -554,6 +616,17 @@
'MaxTempSize': types.FcpTypeInt,
'Verbosity': types.FcpTypeInt,
}
+
+ def restorePersistentParams(self):
+ try:
+ MessageBase.setPersistentParams(self, self['ClientToken'])
+ except Exception, d:
+ #print Exception, d
+ return False
+ return True
+
+ def updatePersistentParams(self):
+ self['ClientToken'] = MessageBase.getPersistentParams(self)
class ClientHello(MessageBase):
@@ -567,6 +640,7 @@
class ClientPut(MessageBase):
name = consts.Message.ClientPut
_additional_params_ = AdditionalPutParams
+ _persistent_params_ = PersistentParamsPut
_param_types_ = {
'BinaryBlob': types.FcpTypeBool,
'DataLength': types.FcpTypeInt,
@@ -577,34 +651,24 @@
'MaxRetries': types.FcpTypeInt,
'Verbosity': types.FcpTypeInt,
}
+
+ def restorePersistentParams(self):
+ try:
+ MessageBase.setPersistentParams(self, self['ClientToken'])
+ except Exception, d:
+ return False
+ return True
+
+ def updatePersistentParams(self):
+ self['ClientToken'] = MessageBase.getPersistentParams(self)
-class ClientPutComplexDir(MessageBase):
+class ClientPutComplexDir(ClientPut):
name = consts.Message.ClientPutComplexDir
- _additional_params_ = AdditionalGetParams
- _param_types_ = {
- 'BinaryBlob': types.FcpTypeBool,
- 'DontCompress': types.FcpTypeBool,
- 'EarlyEncode': types.FcpTypeBool,
- 'GetCHKOnly': types.FcpTypeBool,
- 'Global': types.FcpTypeBool,
- 'MaxRetries': types.FcpTypeInt,
- 'Verbosity': types.FcpTypeInt,
- }
+
-
-class ClientPutDiskDir(MessageBase):
+class ClientPutDiskDir(ClientPut):
name = consts.Message.ClientPutDiskDir
- _additional_params_ = AdditionalGetParams
- _param_types_ = {
- 'BinaryBlob': types.FcpTypeBool,
- 'DontCompress': types.FcpTypeBool,
- 'EarlyEncode': types.FcpTypeBool,
- 'GetCHKOnly': types.FcpTypeBool,
- 'Global': types.FcpTypeBool,
- 'MaxRetries': types.FcpTypeInt,
- 'Verbosity': types.FcpTypeInt,
- }
class CloseConnectionDuplicateClientName(MessageBase):
@@ -927,7 +991,7 @@
'Build': types.FcpTypeInt,
'CompressionCodecs': types.FcpTypeInt,
'ExtBuild': types.FcpTypeInt,
- 'FcpVersion': types.FcpTypeFloat,
+ 'FCPVersion': types.FcpTypeFloat,
'Testnet': types.FcpTypeBool,
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|