def test_decode_amf0(self):
        stream = util.BufferedByteStream(
            '\x11\n\x07Cflex.messaging.io.ArrayCollection\t\x03\x01\x06\teggs')
        decoder = amf0.Decoder(stream)
        x = decoder.readElement()

        self.assertEqual(x.__class__, flex.ArrayCollection)
        self.assertEqual(x, ['eggs'])
Beispiel #2
0
    def next(self):
        """ Read one RTMP message from the stream and return it. """
        if self.stream.at_eof():
            raise StopIteration
        # Read the message into body_stream. The message may span a number of
        # chunks (each one with its own header).
        message_body = []
        msg_body_len = 0
        _header = header.decode(self.stream)
        log.debug('header %s' % _header)

        # FIXME: this should really be implemented inside header_decode
        if _header.data_type == rtmp_type.DT_NONE:
            _header = self.prv_header
        self.prv_header = _header

        while True:
            # NOTE: this whole loop section needs to be looked at.
            read_bytes = min(_header.body_length - msg_body_len,
                             self.chunk_size)

            message_body.append(self.stream.read(read_bytes))
            msg_body_len += read_bytes
            if msg_body_len >= _header.body_length:
                break
            next_header = header.decode(self.stream)
            # WORKAROUND: even though the RTMP specification states that the
            # extended timestamp field DOES NOT follow type 3 chunks, it seems
            # that Flash player 10.1.85.3 and Flash Media Server 3.0.2.217 send
            # and expect this field here.
            if _header.timestamp >= 0x00ffffff:
                self.stream.read_ulong()
            assert next_header.stream_id == -1, (_header, next_header)
            assert next_header.data_type == -1, (_header, next_header)
            assert next_header.timestamp == -1, (_header, next_header)
            assert next_header.body_length == -1, (_header, next_header)
        assert _header.body_length == msg_body_len, (_header, msg_body_len)
        body_stream = pyamf.util.BufferedByteStream(''.join(message_body))

        # Decode the message based on the datatype present in the header
        ret = {'msg': _header.data_type}

        if ret['msg'] == rtmp_type.DT_NONE:
            log.warning('WARNING: message with datatype None received: %s' %
                        _header)
            return self.next()

        elif ret['msg'] == rtmp_type.DT_USER_CONTROL:
            ret['event_type'] = body_stream.read_ushort()
            ret['event_data'] = body_stream.read()

        elif ret['msg'] == rtmp_type.DT_WINDOW_ACK_SIZE:
            ret['window_ack_size'] = body_stream.read_ulong()

        elif ret['msg'] == rtmp_type.DT_SET_PEER_BANDWIDTH:
            ret['window_ack_size'] = body_stream.read_ulong()
            ret['limit_type'] = body_stream.read_uchar()

        elif ret['msg'] == rtmp_type.DT_SHARED_OBJECT:
            decoder = amf0.Decoder(body_stream)
            obj_name = decoder.readString()
            curr_version = body_stream.read_ulong()
            flags = body_stream.read(8)
            # A shared object message may contain a number of events.
            events = []
            while not body_stream.at_eof():
                event = self.read_shared_object_event(body_stream, decoder)
                events.append(event)

            ret['obj_name'] = obj_name
            ret['curr_version'] = curr_version
            ret['flags'] = flags
            ret['events'] = events

        elif ret['msg'] == rtmp_type.DT_AMF3_SHARED_OBJECT:
            decoder = amf3.Decoder(body_stream)
            obj_name = decoder.readString()
            curr_version = body_stream.read_ulong()
            flags = body_stream.read(8)
            # A shared object message may contain a number of events.
            events = []
            while not body_stream.at_eof():
                event = self.read_shared_object_event(body_stream, decoder)
                events.append(event)

            ret['obj_name'] = obj_name
            ret['curr_version'] = curr_version
            ret['flags'] = flags
            ret['events'] = events

        elif ret['msg'] == rtmp_type.DT_COMMAND:
            decoder = amf0.Decoder(body_stream)
            commands = []
            while not body_stream.at_eof():
                commands.append(decoder.readElement())
            ret['command'] = commands

        elif ret['msg'] == rtmp_type.DT_AMF3_COMMAND:
            decoder = amf3.Decoder(body_stream)
            commands = []
            while not body_stream.at_eof():
                commands.append(decoder.readElement())
            ret['command'] = commands

        elif ret['msg'] == rtmp_type.DT_SET_CHUNK_SIZE:
            ret['chunk_size'] = body_stream.read_ulong()
        else:
            assert False, _header

        log.debug('recv %r', ret)
        return ret
Beispiel #3
0
    def setUp(self):
        ClassCacheClearingTestCase.setUp(self)

        self.buf = util.BufferedByteStream()
        self.decoder = amf0.Decoder(self.buf)
        self.context = self.decoder.context