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 = rtmp_protocol_base.header_decode(self.stream) while True: read_bytes = min(header.bodyLength - msg_body_len, self.chunk_size) message_body.append(self.stream.read(read_bytes)) msg_body_len += read_bytes if msg_body_len >= header.bodyLength: break next_header = rtmp_protocol_base.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 header.bodyLength == 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.datatype} if ret['msg'] == DataTypes.NONE: return self.next() elif ret['msg'] == DataTypes.UNKNOWN: # ret['stream_id'] = header.streamId # contextual information use # try: # ret['unknown_type_char'] = body_stream.read_uchar() # except: # pass # try: # ret['unknown_type_long'] = body_stream.read_ulong() # except: # pass # try: # ret['unknown_type_short'] = body_stream.read_ushort() # except: # pass # ret['unknown_data'] = body_stream.read() pass elif ret['msg'] == DataTypes.USER_CONTROL: ret['stream_id'] = header.streamId # contextual information use # ret['event_data_long'] = body_stream.read_ulong() # ret['event_data_char'] = body_stream.read_uchar() ret['event_type'] = body_stream.read_ushort() ret['event_data'] = body_stream.read() elif ret['msg'] == DataTypes.ACK: # ret['stream_id'] = header.streamId # contextual information use # try: # ret['ack_type_char'] = body_stream.read_uchar() # except: # pass # try: # ret['ack_type_long'] = body_stream.read_ulong() # except: # pass # try: # ret['ack_type_short'] = body_stream.read_ushort() # except: # pass # ret['ack_data'] = body_stream.read() pass elif ret['msg'] == DataTypes.WINDOW_ACK_SIZE: ret['window_ack_size'] = body_stream.read_ulong() elif ret['msg'] == DataTypes.SET_PEER_BANDWIDTH: ret['window_ack_size'] = body_stream.read_ulong() ret['limit_type'] = body_stream.read_uchar() elif ret['msg'] == DataTypes.SHARED_OBJECT: decoder = pyamf.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) event = RtmpReader.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'] == DataTypes.COMMAND: ret['stream_id'] = header.streamId # contexutal information decoder = pyamf.amf0.Decoder(body_stream) commands = [] while not body_stream.at_eof(): commands.append(decoder.readElement()) ret['command'] = commands elif ret['msg'] == DataTypes.SET_CHUNK_SIZE: ret['chunk_size'] = body_stream.read_ulong() elif ret['msg'] == DataTypes.DATA: ret['stream_id'] = header.stream_id ret['metadata'] = message_body elif ret['msg'] == DataTypes.AUDIO: # ret['stream_id'] = header.streamId # ret['control'] = body_stream.read_uchar() # ret['data'] = body_stream.read() # ret['timestamp'] = header.timestamp # View individual header information # print(':RTMP HEADER:', '<type:>', header.datatype, '<channel id>:', header.channelId, '<stream id>:', header.streamId, # '<bodylength>:', header.bodyLength, '<timestamp>:', header.timestamp) # View individual body information # print(':RTMP BODY:', '<control>', ret['control'], '<audio data>', '...') # ret['data'] is the raw audio data pass elif ret['msg'] == DataTypes.VIDEO: # ret['stream_id'] = header.streamId # ret['control'] = body_stream.read_uchar() # ret['data'] = body_stream.read() # ret['timestamp'] = header.timestamp # View individual header information # print(':RTMP HEADER:', '<type:>', header.datatype, '<channel id>:', header.channelId, '<stream id>:', header.streamId, # '<bodylength>:', header.bodyLength, '<timestamp>:', header.timestamp) # print("Control", ret['control']) # View individual body information # print(':RTMP BODY:', '<control>', ret['control'], '<video data>', '...') # ret['data'] is the raw video data pass else: assert False, header # logging.debug('recv %r', ret) return ret
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 = rtmp_protocol_base.header_decode(self.stream) # FIXME: this should be really implemented inside header_decode if header.datatype == DataTypes.NONE: header = self.prv_header self.prv_header = header while True: read_bytes = min(header.bodyLength - msg_body_len, self.chunk_size) message_body.append(self.stream.read(read_bytes)) msg_body_len += read_bytes if msg_body_len >= header.bodyLength: break next_header = rtmp_protocol_base.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.streamId == -1, (header, next_header) assert next_header.datatype == -1, (header, next_header) assert next_header.timestamp == -1, (header, next_header) assert next_header.bodyLength == -1, (header, next_header) assert header.bodyLength == 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.datatype} if ret['msg'] == DataTypes.USER_CONTROL: ret['event_type'] = body_stream.read_ushort() ret['event_data'] = body_stream.read() elif ret['msg'] == DataTypes.WINDOW_ACK_SIZE: ret['window_ack_size'] = body_stream.read_ulong() elif ret['msg'] == DataTypes.SET_PEER_BANDWIDTH: ret['window_ack_size'] = body_stream.read_ulong() ret['limit_type'] = body_stream.read_uchar() elif ret['msg'] == DataTypes.SHARED_OBJECT: decoder = pyamf.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'] == DataTypes.COMMAND: decoder = pyamf.amf0.Decoder(body_stream) commands = [] while not body_stream.at_eof(): commands.append(decoder.readElement()) ret['command'] = commands #elif ret['msg'] == DataTypes.NONE: # print 'WARNING: message with no datatype received.', header # return self.next() elif ret['msg'] == DataTypes.SET_CHUNK_SIZE: ret['chunk_size'] = body_stream.read_ulong() else: assert False, header logging.debug('recv %r', ret) return ret
def next(self): """ Read one RTMP message from the stream and return it. """ if self.stream.at_eof(): raise StopIteration # superDebugNotice("rtmp reader, reading incoming rtmp message from stream") # 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 = rtmp_protocol_base.header_decode(self.stream) # FIXME: this should be really implemented inside header_decode if header.datatype == DataTypes.NONE: header = self.prv_header self.prv_header = header # superDebug("header", header) while True: read_bytes = min(header.bodyLength - msg_body_len, self.chunk_size) # superDebug("read_bytes", read_bytes) message_body.append(self.stream.read(read_bytes)) msg_body_len += read_bytes if msg_body_len >= header.bodyLength: break next_header = rtmp_protocol_base.header_decode(self.stream) # superDebug("next_header", next_header) # 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. # superDebug("header.timestamp", header.timestamp) # superDebug("header.timestamp >= 0x00ffffff", header.timestamp >= 0x00ffffff) if header.timestamp >= 0x00ffffff: self.stream.read_ulong() assert next_header.streamId == -1, (header, next_header) assert next_header.datatype == -1, (header, next_header) assert next_header.timestamp == -1, (header, next_header) assert next_header.bodyLength == -1, (header, next_header) assert header.bodyLength == msg_body_len, (header, msg_body_len) body_stream = pyamf.util.BufferedByteStream(''.join(message_body)) # superDebug("body_stream_contents", ''.join(message_body)) # superDebug("message_body", message_body) # superDebug("msg_body_len", msg_body_len) # Decode the message based on the datatype present in the header ret = {'msg':header.datatype} # superDebug("ret", ret) if ret['msg'] == DataTypes.USER_CONTROL: # superDebug("header.datatype enum", "USER_CONTROL") ret['event_type'] = body_stream.read_ushort() ret['event_data'] = body_stream.read() # superDebug("event_type", ret['event_type']) # superDebug("event_data", ret['event_data']) elif ret['msg'] == DataTypes.WINDOW_ACK_SIZE: # superDebug("header.datatype enum", "WINDOW_ACK_SIZE") ret['window_ack_size'] = body_stream.read_ulong() # superDebug("window_ack_size", ret['window_ack_size']) elif ret['msg'] == DataTypes.SET_PEER_BANDWIDTH: # superDebug("header.datatype enum", "SET_PEER_BANDWIDTH") ret['window_ack_size'] = body_stream.read_ulong() ret['limit_type'] = body_stream.read_uchar() # superDebug("window_ack_size", ret['window_ack_size']) # superDebug("limit_type", ret['limit_type']) elif ret['msg'] == DataTypes.SHARED_OBJECT: # superDebug("header.datatype enum", "SHARED_OBJECT") decoder = pyamf.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 # superDebug("obj_name", ret['obj_name']) # superDebug("curr_version", ret['curr_version']) # superDebug("flags", ret['flags']) # superDebug("events", ret['events']) elif ret['msg'] == DataTypes.COMMAND: # superDebug("header.datatype enum", "COMMAND") decoder = pyamf.amf0.Decoder(body_stream) commands = [] while not body_stream.at_eof(): commands.append(decoder.readElement()) ret['command'] = commands elif ret['msg'] == DataTypes.SET_CHUNK_SIZE: # superDebug("header.datatype enum", "SET_CHUNK_SIZE") ret['chunk_size'] = body_stream.read_ulong() # superDebug("chunk_size", ret['chunk_size']) elif ret['msg'] == DataTypes.NONE: print('WARNING: message with no datatype received.', header) return self.next() # superDebug("command", ret['command']) else: # Raise assertion exception with header object. assert False, header # superDebugFooter() logging.debug('recv %r', ret) return ret
def next(self): """ Read one RTMP message from the stream and return it. """ if self.stream.at_eof(): raise StopIteration # superDebugNotice("rtmp reader, reading incoming rtmp message from stream") # 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 = rtmp_protocol_base.header_decode(self.stream) self.prv_header = header # superDebug("header", header) while True: read_bytes = min(header.bodyLength - msg_body_len, self.chunk_size) # superDebug("read_bytes", read_bytes) message_body.append(self.stream.read(read_bytes)) msg_body_len += read_bytes if msg_body_len >= header.bodyLength: break next_header = rtmp_protocol_base.header_decode(self.stream) # superDebug("next_header", next_header) # 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. # superDebug("header.timestamp", header.timestamp) # superDebug("header.timestamp >= 0x00ffffff", header.timestamp >= 0x00ffffff) if header.timestamp >= 0x00ffffff: self.stream.read_ulong() # assert next_header.streamId == -1, (header, next_header) # assert next_header.datatype == -1, (header, next_header) # assert next_header.timestamp == -1, (header, next_header) # assert next_header.bodyLength == -1, (header, next_header) assert header.bodyLength == msg_body_len, (header, msg_body_len) body_stream = pyamf.util.BufferedByteStream(''.join(message_body)) # superDebug("body_stream_contents", ''.join(message_body)) # superDebug("message_body", message_body) # superDebug("msg_body_len", msg_body_len) # Decode the message based on the datatype present in the header ret = {'msg': header.datatype} # superDebug("ret", ret) if ret['msg'] == DataTypes.USER_CONTROL: # superDebug("header.datatype enum", "USER_CONTROL") ret['event_type'] = body_stream.read_ushort() ret['event_data'] = body_stream.read() # superDebug("event_type", ret['event_type']) # superDebug("event_data", ret['event_data']) elif ret['msg'] == DataTypes.WINDOW_ACK_SIZE: # superDebug("header.datatype enum", "WINDOW_ACK_SIZE") ret['window_ack_size'] = body_stream.read_ulong() # superDebug("window_ack_size", ret['window_ack_size']) elif ret['msg'] == DataTypes.SET_PEER_BANDWIDTH: # superDebug("header.datatype enum", "SET_PEER_BANDWIDTH") ret['window_ack_size'] = body_stream.read_ulong() ret['limit_type'] = body_stream.read_uchar() # superDebug("window_ack_size", ret['window_ack_size']) # superDebug("limit_type", ret['limit_type']) elif ret['msg'] == DataTypes.SHARED_OBJECT: # superDebug("header.datatype enum", "SHARED_OBJECT") decoder = pyamf.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 # superDebug("obj_name", ret['obj_name']) # superDebug("curr_version", ret['curr_version']) # superDebug("flags", ret['flags']) # superDebug("events", ret['events']) elif ret['msg'] == DataTypes.COMMAND: # superDebug("header.datatype enum", "COMMAND") decoder = pyamf.amf0.Decoder(body_stream) commands = [] while not body_stream.at_eof(): commands.append(decoder.readElement()) ret['command'] = commands elif ret['msg'] == DataTypes.DATA_MESSAGE: # superDebug("header.datatype enum", "COMMAND") ret['event_data'] = body_stream.read() elif ret['msg'] == DataTypes.SET_CHUNK_SIZE: # superDebug("header.datatype enum", "SET_CHUNK_SIZE") ret['chunk_size'] = body_stream.read_ulong() # print ret['chunk_size'] self.chunk_size = ret['chunk_size'] # superDebug("chunk_size", ret['chunk_size']) elif ret['msg'] == DataTypes.VIDEO_MESSAGE: ret['streamid'] = header.streamId ret['control'] = body_stream.read_uchar() # print ret['control'] ret['video'] = body_stream.read() elif ret['msg'] == DataTypes.NONE: print('WARNING: message with no datatype received.', header) return self.next() # superDebug("command", ret['command']) else: # Raise assertion exception with header object. assert False, header # superDebugFooter() logging.debug('recv %r', ret) return ret
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 = rtmp_protocol_base.header_decode(self.stream) log.debug('header %s' % header) # FIXME: this should really be implemented inside header_decode if header.data_type == types.DT_NONE: header = self.prv_header self.prv_header = header while True: 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 = rtmp_protocol_base.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'] == types.DT_USER_CONTROL: ret['event_type'] = body_stream.read_ushort() ret['event_data'] = body_stream.read() elif ret['msg'] == types.DT_WINDOW_ACK_SIZE: ret['window_ack_size'] = body_stream.read_ulong() elif ret['msg'] == types.DT_SET_PEER_BANDWIDTH: ret['window_ack_size'] = body_stream.read_ulong() ret['limit_type'] = body_stream.read_uchar() elif ret['msg'] == types.DT_SHARED_OBJECT: decoder = pyamf.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'] == types.DT_AMF3_SHARED_OBJECT: decoder = pyamf.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'] == types.DT_COMMAND: decoder = pyamf.amf0.Decoder(body_stream) commands = [] while not body_stream.at_eof(): commands.append(decoder.readElement()) ret['command'] = commands elif ret['msg'] == types.DT_AMF3_COMMAND: decoder = pyamf.amf3.Decoder(body_stream) commands = [] while not body_stream.at_eof(): commands.append(decoder.readElement()) ret['command'] = commands elif ret['msg'] == types.DT_NONE: log.warning('WARNING: message with no datatype received: %s' % header) return self.next() elif ret['msg'] == types.DT_SET_CHUNK_SIZE: ret['chunk_size'] = body_stream.read_ulong() else: assert False, header log.debug('recv %r', ret) return ret
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 = rtmp_protocol_base.header_decode(self.stream) while True: read_bytes = min(header.bodyLength - msg_body_len, self.chunk_size) message_body.append(self.stream.read(read_bytes)) msg_body_len += read_bytes if msg_body_len >= header.bodyLength: break next_header = rtmp_protocol_base.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 header.bodyLength == 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.datatype} if ret['msg'] == DataTypes.NONE: return self.next() elif ret['msg'] == DataTypes.UNKNOWN: # ret['stream_id'] = header.streamId # contextual information use # try: # ret['unknown_type_char'] = body_stream.read_uchar() # except: # pass # try: # ret['unknown_type_long'] = body_stream.read_ulong() # except: # pass # try: # ret['unknown_type_short'] = body_stream.read_ushort() # except: # pass # ret['unknown_data'] = body_stream.read() pass elif ret['msg'] == DataTypes.USER_CONTROL: ret['stream_id'] = header.streamId # contextual information use # ret['event_data_long'] = body_stream.read_ulong() # ret['event_data_char'] = body_stream.read_uchar() ret['event_type'] = body_stream.read_ushort() ret['event_data'] = body_stream.read() elif ret['msg'] == DataTypes.ACK: # ret['stream_id'] = header.streamId # contextual information use # try: # ret['ack_type_char'] = body_stream.read_uchar() # except: # pass # try: # ret['ack_type_long'] = body_stream.read_ulong() # except: # pass # try: # ret['ack_type_short'] = body_stream.read_ushort() # except: # pass # ret['ack_data'] = body_stream.read() pass elif ret['msg'] == DataTypes.WINDOW_ACK_SIZE: ret['window_ack_size'] = body_stream.read_ulong() elif ret['msg'] == DataTypes.SET_PEER_BANDWIDTH: ret['window_ack_size'] = body_stream.read_ulong() ret['limit_type'] = body_stream.read_uchar() elif ret['msg'] == DataTypes.SHARED_OBJECT: decoder = pyamf.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) event = RtmpReader.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'] == DataTypes.COMMAND: ret['stream_id'] = header.streamId # contexutal information decoder = pyamf.amf0.Decoder(body_stream) commands = [] while not body_stream.at_eof(): commands.append(decoder.readElement()) ret['command'] = commands elif ret['msg'] == DataTypes.SET_CHUNK_SIZE: ret['chunk_size'] = body_stream.read_ulong() elif ret['msg'] == DataTypes.DATA: ret['stream_id'] = header.stream_id ret['metadata'] = message_body elif ret['msg'] == DataTypes.AUDIO: # ret['stream_id'] = header.streamId # ret['control'] = body_stream.read_uchar() # ret['data'] = body_stream.read() # ret['timestamp'] = header.timestamp # View individual header information # print(':RTMP HEADER:', '<type:>', header.datatype, '<channel id>:', header.channelId, '<stream id>:', header.streamId, # '<bodylength>:', header.bodyLength, '<timestamp>:', header.timestamp) # View individual body information # print(':RTMP BODY:', '<control>', ret['control'], '<audio data>', '...') # ret['data'] is the raw audio data pass elif ret['msg'] == DataTypes.VIDEO: # ret['stream_id'] = header.streamId # ret['control'] = body_stream.read_uchar() # ret['data'] = body_stream.read() # ret['timestamp'] = header.timestamp # View individual header information # print(':RTMP HEADER:', '<type:>', header.datatype, '<channel id>:', header.channelId, '<stream id>:', header.streamId, # '<bodylength>:', header.bodyLength, '<timestamp>:', header.timestamp) # print("Control", ret['control']) # View individual body information # print(':RTMP BODY:', '<control>', ret['control'], '<video data>', '...') # ret['data'] is the raw video data pass else: assert False, header # logging.debug('recv %r', ret) return ret