def readMessage(self, buffer): input = BytesInput(bytes=buffer, bigendian=True) length = len(buffer) state = self.state[0] # Waiting for handshake if state == STATE_WAITING_FOR_HANDSHAKE: if length < (Handshake.HANDSHAKE_SIZE + 1): return None else: Handshake.readWelcome(input) handshake = Handshake.readHandshake(input) self.writeMessage(Handshake.makeHandshakeResponse(handshake)) self.state = (STATE_WAITING_FOR_HANDSHAKE_RESPONSE,) return (Handshake.HANDSHAKE_SIZE + 1, None) # Waiting for handshake response elif state == STATE_WAITING_FOR_HANDSHAKE_RESPONSE: if length < Handshake.HANDSHAKE_SIZE: return None else: handshake = Handshake.readHandshake(input) self.state = (STATE_READY,) return (Handshake.HANDSHAKE_SIZE, None) # Ready to receive message - read header elif state == STATE_READY: header_size = Rtmp.headerSizeFromByte(input.getByte()) if length < header_size: return None else: header = self.rtmp.readHeader(input) body_length = self.rtmp.bodyLength(header, True) self.state = (STATE_WAITING_FOR_BODY, (header, body_length)) return (header_size, None) # Waiting for message body elif state == STATE_WAITING_FOR_BODY: header, body_length = self.state[1] if length < body_length: return None else: packet = self.rtmp.readPacket(header, input) message = (None, (header, packet))[packet is not None] self.state = (STATE_READY,) return (body_length, message) else: return None
def readMessage(self, buffer): input = BytesInput(bytes=buffer, bigendian=True) length = len(buffer) state = self.state[0] # Waiting for handshake if state == STATE_WAITING_FOR_HANDSHAKE: if length < (Handshake.HANDSHAKE_SIZE + 1): return None else: Handshake.readWelcome(input) handshake = Handshake.readHandshake(input) self.writeMessage(Handshake.makeHandshakeResponse(handshake)) self.state = (STATE_WAITING_FOR_HANDSHAKE_RESPONSE, ) return (Handshake.HANDSHAKE_SIZE + 1, None) # Waiting for handshake response elif state == STATE_WAITING_FOR_HANDSHAKE_RESPONSE: if length < Handshake.HANDSHAKE_SIZE: return None else: handshake = Handshake.readHandshake(input) self.state = (STATE_READY, ) return (Handshake.HANDSHAKE_SIZE, None) # Ready to receive message - read header elif state == STATE_READY: header_size = Rtmp.headerSizeFromByte(input.getByte()) if length < header_size: return None else: header = self.rtmp.readHeader(input) body_length = self.rtmp.bodyLength(header, True) self.state = (STATE_WAITING_FOR_BODY, (header, body_length)) return (header_size, None) # Waiting for message body elif state == STATE_WAITING_FOR_BODY: header, body_length = self.state[1] if length < body_length: return None else: packet = self.rtmp.readPacket(header, input) message = (None, (header, packet))[packet is not None] self.state = (STATE_READY, ) return (body_length, message) else: return None
def processBody(self, header, body): type = header[3] input = BytesInput(bytes=body, bigendian=True) # 0x01 - Chunk Size if type == RTMP_TYPE_CHUNK_SIZE: self.read_chunk_size = input.readUInt() return None # 0x03 - Bytes Read elif type == RTMP_TYPE_BYTES_READ: return (RTMP_TYPE_BYTES_READ, input.readUInt()) # 0x04 - Control elif type == RTMP_TYPE_CONTROL: control = None control_type = input.readUInt16() control_stream_id = input.readUInt() body_size = RTMP_CONTROL_SIZES[control_type] body_length = len(body) if (body_size is not None) and (body_length != (body_size + 6)): raise Exception, "Invalid control size(%s, %s)" % (type, len(body)) # 0x00 - Clear if control_type == RTMP_CONTROL_CLEAR: control = (RTMP_CONTROL_CLEAR, ) # 0x01 - Clear Play elif control_type == RTMP_CONTROL_CLEAR_PLAY: control = (RTMP_CONTROL_CLEAR_PLAY, ) # 0x03 - Client Buffer elif control_type == RTMP_CONTROL_CLIENT_BUFFER: control = (RTMP_CONTROL_CLIENT_BUFFER, input.readUInt()) # 0x04 - Reset elif control_type == RTMP_CONTROL_RESET: control = (RTMP_CONTROL_RESET, ) # 0x06 - Ping elif control_type == RTMP_CONTROL_PING: control = (RTMP_CONTROL_PING, input.readUInt()) # 0x07 - Pong elif control_type == RTMP_CONTROL_PONG: control = (RTMP_CONTROL_PONG, input.readUInt() ) #TODO - verify second value (, input.readUInt()) # Unknown else: if (body_length != 6) and (body_length != 10) and (body_length != 14): raise Exception, "Invalid control size(%s, %s)" % ( type, len(body)) value1 = None value2 = None if body_length > 6: value1 = input.readUInt() if body_length > 10: value2 = input.readUInt() control = (RTMP_CONTROL_UNKNOWN, control_type, value1, value2) return (RTMP_TYPE_CONTROL, (control_stream_id, control)) # 0x05 - Server BW elif type == RTMP_TYPE_SERVER_BW: return (RTMP_TYPE_SERVER_BW, header[1]) # 0x06 - Client BW elif type == RTMP_TYPE_CLIENT_BW: return (RTMP_TYPE_CLIENT_BW, header[1]) # 0x08 - Audio elif type == RTMP_TYPE_AUDIO: return (RTMP_TYPE_AUDIO, body) # 0x09 - Video elif type == RTMP_TYPE_VIDEO: return (RTMP_TYPE_VIDEO, body) # 0x12 - Notify elif type == RTMP_TYPE_NOTIFY: return (RTMP_TYPE_NOTIFY, body) # 0x13 - Shared elif type == RTMP_TYPE_SHARED: raise Exception, "Not implemented" #TODO -> Shared Object functions # 0x14 - Command elif type == RTMP_TYPE_COMMAND: amf_type, name = Amf.read(input) if amf_type != Amf.AMF_VALUE_STRING: raise Exception, "Invalid Command Name" amf_type, command_id = Amf.read(input) if amf_type != Amf.AMF_VALUE_NUMBER: raise Exception, "Invalid Command ID" args = [] while 1: try: byte = input.readByte() except: break else: if byte is not None: args.append(Amf.readType(input, byte)) else: break return (RTMP_TYPE_COMMAND, (name, command_id, args)) # Unknown else: return (RTMP_TYPE_UNKNOWN, (type, body))
def processBody(self, header, body): type = header[3] input = BytesInput(bytes=body, bigendian=True) # 0x01 - Chunk Size if type == RTMP_TYPE_CHUNK_SIZE: self.read_chunk_size = input.readUInt() return None # 0x03 - Bytes Read elif type == RTMP_TYPE_BYTES_READ: return (RTMP_TYPE_BYTES_READ, input.readUInt()) # 0x04 - Control elif type == RTMP_TYPE_CONTROL: control = None control_type = input.readUInt16() control_stream_id = input.readUInt() body_size = RTMP_CONTROL_SIZES[control_type] body_length = len(body) if (body_size is not None) and (body_length != (body_size + 6)): raise Exception, "Invalid control size(%s, %s)" % (type, len(body)) # 0x00 - Clear if control_type == RTMP_CONTROL_CLEAR: control = (RTMP_CONTROL_CLEAR,) # 0x01 - Clear Play elif control_type == RTMP_CONTROL_CLEAR_PLAY: control = (RTMP_CONTROL_CLEAR_PLAY,) # 0x03 - Client Buffer elif control_type == RTMP_CONTROL_CLIENT_BUFFER: control = (RTMP_CONTROL_CLIENT_BUFFER, input.readUInt()) # 0x04 - Reset elif control_type == RTMP_CONTROL_RESET: control = (RTMP_CONTROL_RESET,) # 0x06 - Ping elif control_type == RTMP_CONTROL_PING: control = (RTMP_CONTROL_PING, input.readUInt()) # 0x07 - Pong elif control_type == RTMP_CONTROL_PONG: control = (RTMP_CONTROL_PONG, input.readUInt()) #TODO - verify second value (, input.readUInt()) # Unknown else: if (body_length != 6) and (body_length != 10) and (body_length != 14): raise Exception, "Invalid control size(%s, %s)" % (type, len(body)) value1 = None value2 = None if body_length > 6: value1 = input.readUInt() if body_length > 10: value2 = input.readUInt() control = (RTMP_CONTROL_UNKNOWN, control_type, value1, value2) return (RTMP_TYPE_CONTROL, (control_stream_id, control)) # 0x05 - Server BW elif type == RTMP_TYPE_SERVER_BW: return (RTMP_TYPE_SERVER_BW, header[1]) # 0x06 - Client BW elif type == RTMP_TYPE_CLIENT_BW: return (RTMP_TYPE_CLIENT_BW, header[1]) # 0x08 - Audio elif type == RTMP_TYPE_AUDIO: return (RTMP_TYPE_AUDIO, body) # 0x09 - Video elif type == RTMP_TYPE_VIDEO: return (RTMP_TYPE_VIDEO, body) # 0x12 - Notify elif type == RTMP_TYPE_NOTIFY: return (RTMP_TYPE_NOTIFY, body) # 0x13 - Shared elif type == RTMP_TYPE_SHARED: raise Exception, "Not implemented" #TODO -> Shared Object functions # 0x14 - Command elif type == RTMP_TYPE_COMMAND: amf_type, name = Amf.read(input) if amf_type != Amf.AMF_VALUE_STRING: raise Exception, "Invalid Command Name" amf_type, command_id = Amf.read(input) if amf_type != Amf.AMF_VALUE_NUMBER: raise Exception, "Invalid Command ID" args = [] while 1: try: byte = input.readByte() except: break else: if byte is not None: args.append(Amf.readType(input, byte)) else: break return (RTMP_TYPE_COMMAND, (name, command_id, args)) # Unknown else: return (RTMP_TYPE_UNKNOWN, (type, body))