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. |