Exemple #1
0
 def deserialize(self, raw_data):
     if len(raw_data) < self.HEADER_LENGTH:
         return None
     self.message_id, self.payload_descriptor, self.ttl, self.hops, self.payload_length = unpack(self.fmt, raw_data[:self.HEADER_LENGTH])
     # Check for error heuristically in connection stream
     if not (self.payload_descriptor == GnutellaBodyId.PING or 
             self.payload_descriptor == GnutellaBodyId.PONG or 
             self.payload_descriptor == GnutellaBodyId.PUSH or 
             self.payload_descriptor == GnutellaBodyId.QUERY or 
             self.payload_descriptor == GnutellaBodyId.QUERYHIT):
         raise ValueError
     if self.hops + self.ttl > self.MAXIMUM_SUM_TTL_HOPS:
         raise ValueError
     # shorten the raw_data to body
     raw_data = raw_data[self.HEADER_LENGTH:]
     # if check raw_data has enough data for payload
     if len(raw_data) < self.payload_length:
         return None
     # deserialize the body
     if self.payload_descriptor == GnutellaBodyId.PING:
         self.body = PingBody(self)
     elif self.payload_descriptor == GnutellaBodyId.PONG:
         self.body = PongBody(self)
     elif self.payload_descriptor == GnutellaBodyId.PUSH:
         self.body = PushBody(self)
     elif self.payload_descriptor == GnutellaBodyId.QUERY:
         self.body = QueryBody(self)
     elif self.payload_descriptor == GnutellaBodyId.QUERYHIT:
         self.body = QueryHitBody(self)
     else:
         raise ValueError('message type is not one of PING, PONG, QUERY, QUERYHIT, PUSH')
     # final check if deserialize correctly with payload_length given in the header
     if self.body.deserialize(raw_data[:self.payload_length]) == None:
         raise ValueError("body should be able to deserialize")
     return self.payload_length + self.HEADER_LENGTH
Exemple #2
0
class Message:
    # count in byte
    MAXIMUM_SUM_TTL_HOPS = 7
    
    def __init__(self, message_id = None, ttl = 7):
        if message_id:
            self.message_id = message_id
        else:
            # automatically generate one
            self.message_id = uuid.uuid4().bytes
        self.ttl = ttl
        self.hops = 0
        self.body = None
        self.payload_length = None
        self.payload_descriptor = None
        self.fmt = '!16sBBBI'
        self.HEADER_LENGTH = calcsize(self.fmt)
            
    def decrease_ttl(self, value=1):
        self.ttl = self.ttl - value
        self.hops = self.hops + value
    
    def serialize(self):
        assert self.body != None
        assert self.payload_descriptor != None
        payload = self.body.serialize()
        self.payload_length = len(payload)
        header = pack(self.fmt, self.message_id, self.payload_descriptor, self.ttl, self.hops, self.payload_length)        
        return header + payload
    
    def deserialize(self, raw_data):
        if len(raw_data) < self.HEADER_LENGTH:
            return None
        self.message_id, self.payload_descriptor, self.ttl, self.hops, self.payload_length = unpack(self.fmt, raw_data[:self.HEADER_LENGTH])
        # Check for error heuristically in connection stream
        if not (self.payload_descriptor == GnutellaBodyId.PING or 
                self.payload_descriptor == GnutellaBodyId.PONG or 
                self.payload_descriptor == GnutellaBodyId.PUSH or 
                self.payload_descriptor == GnutellaBodyId.QUERY or 
                self.payload_descriptor == GnutellaBodyId.QUERYHIT):
            raise ValueError
        if self.hops + self.ttl > self.MAXIMUM_SUM_TTL_HOPS:
            raise ValueError
        # shorten the raw_data to body
        raw_data = raw_data[self.HEADER_LENGTH:]
        # if check raw_data has enough data for payload
        if len(raw_data) < self.payload_length:
            return None
        # deserialize the body
        if self.payload_descriptor == GnutellaBodyId.PING:
            self.body = PingBody(self)
        elif self.payload_descriptor == GnutellaBodyId.PONG:
            self.body = PongBody(self)
        elif self.payload_descriptor == GnutellaBodyId.PUSH:
            self.body = PushBody(self)
        elif self.payload_descriptor == GnutellaBodyId.QUERY:
            self.body = QueryBody(self)
        elif self.payload_descriptor == GnutellaBodyId.QUERYHIT:
            self.body = QueryHitBody(self)
        else:
            raise ValueError('message type is not one of PING, PONG, QUERY, QUERYHIT, PUSH')
        # final check if deserialize correctly with payload_length given in the header
        if self.body.deserialize(raw_data[:self.payload_length]) == None:
            raise ValueError("body should be able to deserialize")
        return self.payload_length + self.HEADER_LENGTH
    
    def __repr__(self):        
        return "<Message: %s %s %s %s>" % (self.message_id.encode('hex_codec'), GnutellaBodyId.get_str_id(self.payload_descriptor), self.ttl, self.hops)