SF.net SVN: fclient: [17] trunk/fclient/fclient_lib/fcp/fcp2_0.py
Status: Pre-Alpha
Brought to you by:
jurner
|
From: <jU...@us...> - 2007-10-28 09:43:18
|
Revision: 17
http://fclient.svn.sourceforge.net/fclient/?rev=17&view=rev
Author: jUrner
Date: 2007-10-28 02:43:20 -0700 (Sun, 28 Oct 2007)
Log Message:
-----------
combed over message object ++ some bug fixes
Modified Paths:
--------------
trunk/fclient/fclient_lib/fcp/fcp2_0.py
Modified: trunk/fclient/fclient_lib/fcp/fcp2_0.py
===================================================================
--- trunk/fclient/fclient_lib/fcp/fcp2_0.py 2007-10-27 20:59:45 UTC (rev 16)
+++ trunk/fclient/fclient_lib/fcp/fcp2_0.py 2007-10-28 09:43:20 UTC (rev 17)
@@ -328,8 +328,12 @@
"""
if fpath is not None:
if os.path.isfile(fpath):
- os.remove(fpath)
- return True
+ try:
+ os.remove(fpath)
+ except Exception, d:
+ pass
+ else:
+ return True
return False
@@ -465,6 +469,8 @@
class Message(object):
"""Class wrapping a freenet message"""
+ __slots__ = ('name', 'data', 'params')
+
# client messages
ClientHello = 'ClientHello'
ListPeer = 'ListPeer' # (since 1045)
@@ -527,12 +533,11 @@
UnknownPeerNoteType = 'UnknownPeerNoteType'
SubscribedUSKUpdate = 'SubscribedUSKUpdate'
-
# client messages (internal use only)
ClientSocketTimeout = 0
ClientSocketDied = 1
+
-
def __init__(self, name, data=None, **params):
"""
@param name: messge name
@@ -545,70 +550,102 @@
self.params = params
+ @classmethod
+ def bytesFromSocket(clss, socketObj, n):
+ """Reads n bytes from socket
+ @param socketObj: socket to read bytes from
+ @param n: (int) number of bytes to read
+ @return: (tuple) error-message or None, bytes read or None if an error occured
+ or no bytes could be read
+ """
+ error = p = None
+ try:
+ p = socketObj.recv(n)
+ if not p:
+ p = None
+ raise socket.error('Socket shut down by node')
+ except socket.timeout, d: # no new messages in queue
+ error = clss(clss.ClientSocketTimeout)
+ except socket.error, d:
+ error = clss(clss.ClientSocketDied, Exception=socket.error, Details=d)
+ return error, p
+
+
+ @classmethod
+ def fromSocket(clss, socketObj):
+ """Reads a message from a socket
+ @param socketObj: socket to read a message from
+ @return: L{Message} next message from the socket. If the socket dies
+ unexpectedly a L{ClientSocketDied} message is returned containing the parameters
+ 'Exception' and 'Details'. If the socket times out a L{MessageClientSocketTimout}
+ message is returned.
+ """
+
+ msg = clss(None)
+ buf = []
+
+ #TODO: to buffer or not to buffer?
+ while True:
+
+ # get next line from socket
+ error, p = clss.bytesFromSocket(socketObj, 1)
+ if error:
+ return error
+
+ if p != '\n':
+ buf.append(p)
+ continue
+ #TODO: check if '\r\n' is allowed in freenet client protocol
+ else:
+ if buf[-1] == '\r':
+ del buf[-1]
+
+ line = ''.join(buf)
+ buf = []
+ if line == 'EndMessage':
+ break
+
+ # first line == message name
+ if msg.name is None:
+ msg.name = line
+
+ # get data member
+ elif line == 'Data':
+ remaining = int(msg.params['DataLength'])
+ msg.data = ''
+ while remaining > 0:
+ error, p = clss.bytesFromSocket(socketObj, remaining)
+ if error:
+ return error
+ remaining -= len(p)
+ msg.data += p
+ break
+
+ # get next paramater
+ else:
+ head, sep, tail = line.partition('=')
+ msg.params[head] = tail
+ # TODO: errorchek params?
+ #if not sep: pass
+
+ return msg
+
+
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
- @classmethod
- def fromSocket(clss, socketObj):
- msg = clss(None)
- buf = []
- while True:
-
- try:
- p = socketObj.recv(1)
- if not p: raise ValueError('Socket is dead')
- except socket.timeout, d: # no new messages in queue
- msg.name = clss.ClientSocketTimeOut
- return msg
- except Exception, d:
- msg.name = clss.ClientSocketDied
- msg['Exception'] = Exception
- msg['Details'] = d
- return msg
-
- if p == '\r': # ignore
- continue
-
- if p != '\n':
- buf.append(p)
- continue
-
- line = ''.join(buf)
- if line in ('End', "EndMessage"):
- break
- buf = []
-
- if msg.name is None:
- msg.name = line
- elif line == 'Data':
- n = int(msg.params['DataLength'])
- try:
- msg.data = socketObj.recv(n)
- if not msg.data: raise ValueError('Socket is dead')
- except Exception, d:
- msg.name = clss.ClientSocketDied
- msg['Exception'] = Exception
- msg['Details'] = d
- return msg
-
- else:
- head, sep, tail = line.partition('=')
- msg.params[head] = tail
- if not sep:
- # TODO: chek for invalid messages or not
- pass
-
- return msg
-
+
def pprint(self):
"""Returns the message as nicely formated human readable string"""
out = ['', '>>' + self.name, ]
@@ -617,6 +654,14 @@
out.append('>>EndMessage')
return '\n'.join(out)
+
+ def send(self, socketObj):
+ """Dumps the message to a socket
+ @param socketObj: socket to dump the message to
+ """
+ socketObj.sendall(self.toString())
+
+
def toString(self):
"""Returns the message as formated string ready to be send"""
# TODO: "Data" not yet implemented
@@ -625,7 +670,18 @@
out = [self.name, ]
for param, value in self.params.items():
out.append('%s=%s' % (param, value))
- out.append('EndMessage\n')
+ if self.data:
+ assert 'DataLength' in self.params, 'DataLength member required'
+ n = None
+ try:
+ n = int(self['DataLength'])
+ except ValueError: pass
+ assert n is not None, 'DataLength member must be an integer'
+ assert n == len(self.data), 'DataLength member must corrospond to lenght of data'
+ out.append('Data')
+ out.append(self.data)
+ else:
+ out.append('EndMessage\n')
return '\n'.join(out)
@@ -1448,7 +1504,7 @@
"""
self._log.debug(self._logMessages.MessageSend + msg.pprint())
try:
- self._socket.sendall(msg.toString())
+ msg.send(self._socket)
except socket.error, d:
self._log.info(self._logMessages.SocketDead)
self.close()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|