def write(self, previous=None): """ Write (encoder) header to byte string. @param previous: previous header (used to compress header) @type previous: L{RTMPHeader} @return: encoded header @rtype: C{str} """ if previous is None: diff = 3 else: diff = self.diff(previous) first = self.object_id & 0x3f | ((diff ^ 3) << 6) if diff == 0: return chr(first) buf = BufferedByteStream() buf.write_uchar(first) buf.write_24bit_uint(self.timestamp) if diff > 1: buf.write_24bit_uint(self.length) buf.write_uchar(self.type) if diff > 2: buf.write_ulong(self.stream_id) buf.seek(0, 0) return buf.read()
def __init__(self, encoder, streamId, output): self.encoder = encoder self.channel = self.encoder.acquireChannel() if self.channel is None: # todo: make this better raise RuntimeError('No streaming channel available') self.type = None self.streamId = streamId self.output = output self.stream = BufferedByteStream() self._lastHeader = None self._oldStream = self.channel.stream self.channel.stream = self.stream h = header.Header(self.channel.channelId) # encode a continuation header for speed header.encode(self.stream, h, h) self._continuationHeader = self.stream.getvalue() self.stream.consume()
def sendMessage(self, msg, stream, whenDone=None): """ Sends an RTMP message to the peer. Not part of a public api, use C{stream.sendMessage} instead. @param msg: The message being sent to the peer. @type msg: L{message.IMessage} @param stream: The stream instance that is sending the message. @type stream: L{NetStream} @param whenDone: A callback fired when the message has been written to the RTMP stream. See L{BaseStream.sendMessage} """ buf = BufferedByteStream() e = self.encoder # this will probably need to be rethought as this could block for an # unacceptable amount of time. For most messages however it seems to be # fast enough and the penalty for setting up a new thread is too high. msg.encode(buf) e.send(buf.getvalue(), msg.__data_type__, stream.streamId, stream.timestamp, whenDone) if e.active and not self.encoder_task: self.startEncoding()
def test_read_short(self): for fixture in self.data: for l in xrange(len(fixture[0])-1): try: RTMPHeader.read(BufferedByteStream(fixture[0][0:l])) self.fail() except NeedBytes, (bytes,): self.failUnlessEqual(len(fixture[0])-l if l != 0 else 1, bytes)
def startStreaming(self): """ This must be called before any RTMP data is received. """ self.streamManager = self.buildStreamManager() self.controlStream = self.streamManager.getControlStream() self._decodingBuffer = BufferedByteStream() self._encodingBuffer = BufferedByteStream() self.decoder = codec.Decoder(self.getDispatcher(), self.streamManager, stream=self._decodingBuffer) self.encoder = codec.Encoder(self.getWriter(), stream=self._encodingBuffer) self.decoder_task = None self.encoder_task = None
def disassemble(self): """ Disassemble L{buffer} into packets. Returns first decoded packet or None, if no packet could be decoded at the moment. @return: decoded packet @rtype: L{Packet} """ self.buffer.seek(0) while self.buffer.remaining() > 0: try: # try to parse header from stream header = RTMPHeader.read(self.buffer) except NeedBytes, (bytes, ): # not enough bytes, return what we've already parsed return None # fill header with extra data from previous headers received # with same object_id header.fill(self.lastHeaders.get(header.object_id, RTMPHeader())) # get buffer for data of this packet buf = self.pool.get(header.object_id, BufferedByteStream()) # this chunk size is minimum of regular chunk size in this # disassembler and what we have left here thisChunk = min(header.length - len(buf), self.chunkSize) if self.buffer.remaining() < thisChunk: # we have not enough bytes to read this chunk of data return None # we got complete chunk buf.write(self.buffer.read(thisChunk)) # store packet header for this object_id self.lastHeaders[header.object_id] = header # skip data left in input buffer self.buffer.consume() # this chunk completes full packet? if len(buf) < header.length: # no, store buffer for further chunks self.pool[header.object_id] = buf else: # parse packet from header and data buf.seek(0, 0) # delete stored data for this packet if header.object_id in self.pool: del self.pool[header.object_id] return self._decode_packet(header, buf)
def setUp(self): self.patch(codec, 'ChannelDemuxer', MockChannelDemuxer) self.dispatcher = DispatchTester(self) self.stream_factory = MockStreamFactory(self) self.decoder = codec.Decoder(self.dispatcher, self.stream_factory, stream=BufferedByteStream()) self.expected_streams = None self.streams = {}
def __init__(self, chunkSize): """ Constructor. @param chunkSize: initial size of chunk @type chunkSize: C{int} """ self.lastHeaders = {} self.pool = {} self.chunkSize = chunkSize self.buffer = BufferedByteStream()
def write(self): """ Encode packet into bytes. @return: representation of packet @rtype: C{str} """ buf = BufferedByteStream() buf.write_ulong(self.bytes) self.header.length = len(buf) buf.seek(0, 0) return buf.read()
def dispatchMessage(self, stream, datatype, timestamp, data): """ Called when the RTMP decoder has read a complete RTMP message. @param stream: The L{Stream} to receive this message. @param datatype: The RTMP datatype for the message. @param timestamp: The absolute timestamp this message was received. @param data: The raw data for the message. """ m = message.classByType(datatype)() m.decode(BufferedByteStream(data)) m.dispatch(stream, timestamp)
def connectionMade(self): """ Successfully connected to peer. """ self.input = RTMPDisassembler(constants.DEFAULT_CHUNK_SIZE) self.output = RTMPAssembler(constants.DEFAULT_CHUNK_SIZE, self.transport) self.state = self.State.HANDSHAKE_SEND self.handshakeTimeout = reactor.callLater( config.getint('RTMP', 'handshakeTimeout'), self._handshakeTimedout) self.handshakeBuf = BufferedByteStream() self._beginHandshake()
def dispatchMessage(self, stream, datatype, timestamp, data): p = Packet(self.type, streamId=stream.streamId, datatype=datatype, timestamp=timestamp) self.observer.messageStart(p) e = message.classByType(datatype)() e.decode(BufferedByteStream(data)) e.dispatch(stream, timestamp) self.observer.messageComplete(p)
class BytesReadTestCase(unittest.TestCase): """ Test case for L{fmspy.rtmp.packets.BytesRead}. """ data = [ ( { 'header': RTMPHeader(object_id=2, timestamp=0, length=4, type=0x03, stream_id=0L), 'buf': BufferedByteStream('\x00\x00\x00\x89'), }, BytesRead(bytes=137, header=RTMPHeader(object_id=2, timestamp=0, length=4, type=0x03, stream_id=0L)), ), ] def test_eq(self): self.failUnlessEqual( BytesRead(bytes=5, header=RTMPHeader(object_id=3)), BytesRead(bytes=5, header=RTMPHeader(object_id=3))) self.failIfEqual(BytesRead(bytes=5, header=RTMPHeader(object_id=4)), BytesRead(bytes=5, header=RTMPHeader(object_id=3))) self.failIfEqual(BytesRead(bytes=6, header=RTMPHeader(object_id=3)), BytesRead(bytes=5, header=RTMPHeader(object_id=3))) def test_read(self): for fixture in self.data: fixture[0]['buf'].seek(0) self.failUnlessEqual(fixture[1], BytesRead.read(**fixture[0])) def test_write(self): for fixture in self.data: fixture[0]['buf'].seek(0) self.failUnlessEqual(fixture[0]['buf'].read(), fixture[1].write())
def pyamfEncode(self, obj, amf3=False, use_proxies=False): if amf3 is True: context = pyamf.get_context(pyamf.AMF3) else: context = pyamf.get_context(pyamf.AMF0) stream = BufferedByteStream() if amf3 is True: pyamf_encoder = pyamf.get_encoder(pyamf.AMF3, stream=stream, context=context) else: pyamf_encoder = pyamf.get_encoder(pyamf.AMF0, stream=stream, context=context) pyamf_encoder.writeElement(obj) return pyamf_encoder.stream.getvalue()
def start(self, uptime=None, version=None): """ Called to start the handshaking negotiations. """ if self.started: raise HandshakeError('Handshake negotiator cannot be restarted') self.started = True self.buffer = BufferedByteStream() self.peer_version = None self.my_syn = Packet(uptime, version) self.my_ack = None self.peer_syn = None self.peer_ack = None self.buildSynPayload(self.my_syn) self._writePacket(self.my_syn)
def setUp(self): self.context = pyamf.get_context(self.amf_version) self.stream = BufferedByteStream()
def setUp(self): self.output = BufferedByteStream() self.encoder = codec.Encoder(self.output)
def setUp(self): self.buffer = BufferedByteStream() self.listener = MockMessageListener()
def _writePacket(self, packet, stream=None): stream = stream or BufferedByteStream() packet.encode(stream) self.transport.write(stream.getvalue())
def test_read(self): for fixture in self.data: self.failUnlessEqual(fixture[1], RTMPHeader.read(BufferedByteStream(fixture[0])))
def __init__(self, deferred): self.deferred = deferred self.s = BufferedByteStream()
class PingTestCase(unittest.TestCase): """ Test case for L{fmspy.rtmp.packets.Ping}. """ data = [ ( { 'header': RTMPHeader(object_id=2, timestamp=0, length=6, type=0x04, stream_id=0L), 'buf': BufferedByteStream('\x00\x06\x00\x00\x00\x89'), }, Ping(event=6, data=[137], header=RTMPHeader(object_id=2, timestamp=0, length=6, type=0x04, stream_id=0L)), ), ( { 'header': RTMPHeader(object_id=2, timestamp=0, length=10, type=0x04, stream_id=0L), 'buf': BufferedByteStream('\x00\x06\x00\x00\x00\x89\x00\x00\x00\x0e'), }, Ping(event=6, data=[137, 14], header=RTMPHeader(object_id=2, timestamp=0, length=10, type=0x04, stream_id=0L)), ), ( { 'header': RTMPHeader(object_id=2, timestamp=0, length=14, type=0x04, stream_id=0L), 'buf': BufferedByteStream( '\x00\x06\x00\x00\x00\x89\x00\x00\x00\x0e\x00\x00\x03y'), }, Ping(event=6, data=[137, 14, 889], header=RTMPHeader(object_id=2, timestamp=0, length=14, type=0x04, stream_id=0L)), ), ] def test_eq(self): self.failUnlessEqual( Ping(event=5, data=[3], header=RTMPHeader(object_id=3)), Ping(event=5, data=[3], header=RTMPHeader(object_id=3))) self.failIfEqual( Ping(event=5, data=[3], header=RTMPHeader(object_id=3)), Ping(event=5, data=[3], header=RTMPHeader(object_id=4))) self.failIfEqual( Ping(event=5, data=[3], header=RTMPHeader(object_id=3)), Ping(event=5, data=[3, 4], header=RTMPHeader(object_id=3))) self.failIfEqual( Ping(event=5, data=[3], header=RTMPHeader(object_id=3)), Ping(event=6, data=[3], header=RTMPHeader(object_id=3))) def test_read(self): for fixture in self.data: fixture[0]['buf'].seek(0) self.failUnlessEqual(fixture[1], Ping.read(**fixture[0])) def test_write(self): for fixture in self.data: fixture[0]['buf'].seek(0) self.failUnlessEqual(fixture[0]['buf'].read(), fixture[1].write())
class InvokeTestCase(unittest.TestCase): """ Test case for L{fmspy.rtmp.packets.Invoke}. """ data = [ ({ 'header': RTMPHeader(object_id=3, timestamp=0, length=235, type=0x14, stream_id=0L), 'buf': BufferedByteStream( '\x02\x00\x07connect\x00?\xf0\x00\x00\x00\x00\x00\x00\x03\x00\x03app\x02\x00\x04echo\x00\x08flashVer\x02\x00\rLNX 10,0,20,7\x00\x06swfUrl\x06\x00\x05tcUrl\x02\x00\x15rtmp://localhost/echo\x00\x04fpad\x01\x00\x00\x0ccapabilities\x00@.\x00\x00\x00\x00\x00\x00\x00\x0baudioCodecs\x00@\xa8\xee\x00\x00\x00\x00\x00\x00\x0bvideoCodecs\x00@o\x80\x00\x00\x00\x00\x00\x00\rvideoFunction\x00?\xf0\x00\x00\x00\x00\x00\x00\x00\x07pageUrl\x06\x00\x0eobjectEncoding\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\t' ), }, Invoke(name=u'connect', argv=({ 'videoCodecs': 252, 'audioCodecs': 3191, 'flashVer': u'LNX 10,0,20,7', 'app': u'echo', 'tcUrl': u'rtmp://localhost/echo', 'videoFunction': 1, 'capabilities': 15, 'pageUrl': pyamf.Undefined, 'fpad': False, 'swfUrl': pyamf.Undefined, 'objectEncoding': 0 }, ), id=1, header=RTMPHeader(object_id=3, timestamp=0, length=235, type=0x14, stream_id=0L)), False), ({ 'header': RTMPHeader(object_id=3, timestamp=0, length=0, type=0x14, stream_id=0L), 'buf': BufferedByteStream( '\x02\x00\x07destroy\x00@@\x80\x00\x00\x00\x00\x00\x03\x00\x0bvideoCodecs\x00@o\x80\x00\x00\x00\x00\x00\x00\x00\t' ), }, Invoke(name=u'destroy', argv=({ 'videoCodecs': 252 }, ), id=33, header=RTMPHeader(object_id=3, timestamp=0, length=0, type=0x14, stream_id=0L)), True), ] def test_eq(self): self.failUnlessEqual( Invoke(name='a', argv=(), id=35.0, header=RTMPHeader(object_id=3)), Invoke(name='a', argv=(), id=35.0, header=RTMPHeader(object_id=3))) self.failIfEqual( Invoke(name='a', argv=(), id=35.0, header=RTMPHeader(object_id=3)), Invoke(name='b', argv=(), id=35.0, header=RTMPHeader(object_id=3))) self.failIfEqual( Invoke(name='a', argv=(), id=35.0, header=RTMPHeader(object_id=3)), Invoke(name='a', argv=('a'), id=35.0, header=RTMPHeader(object_id=3))) self.failIfEqual( Invoke(name='a', argv=(), id=35.0, header=RTMPHeader(object_id=3)), Invoke(name='a', argv=(), id=36.0, header=RTMPHeader(object_id=3))) self.failIfEqual( Invoke(name='a', argv=(), id=35.0, header=RTMPHeader(object_id=3)), Invoke(name='a', argv=(), id=35.0, header=RTMPHeader(object_id=4))) def test_repr(self): self.failUnlessEqual( "<Invoke(name=u'destroy', argv=({'videoCodecs': 252},), id=33, header=<RTMPHeader(object_id=3, timestamp=0, length=0, type=0x14, stream_id=0L)>)>", repr( Invoke(name=u'destroy', argv=({ 'videoCodecs': 252 }, ), id=33, header=RTMPHeader(object_id=3, timestamp=0, length=0, type=0x14, stream_id=0L)))) def test_read(self): for fixture in self.data: fixture[0]['buf'].seek(0) self.failUnlessEqual(fixture[1], Invoke.read(**fixture[0])) def test_write(self): for fixture in self.data: if not fixture[2]: continue fixture[0]['buf'].seek(0) self.failUnlessEqual(fixture[0]['buf'].read(), fixture[1].write())
def startVersioning(self): """ Start protocol version negotiations. """ self.buffer = BufferedByteStream()
def __init__(self, channelId, stream, frameSize): BaseChannel.__init__(self, channelId, stream, frameSize) self.buffer = BufferedByteStream() self.acquired = False self.callback = None
def __init__(self, stream=None): self.stream = stream or BufferedByteStream() self.channels = {} self.frameSize = FRAME_SIZE self.bytes = 0