2 // Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012
3 // Free Software Foundation, Inc.
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 #include "SimpleBuffer.h"
31 #define RTMP_DEFAULT_CHUNKSIZE 128
33 // Forward declarations.
44 /// Known control / ping codes
46 /// See http://jira.red5.org/confluence/display/docs/Ping (may not exist).
48 /// 0x00: Clear the stream. No third and fourth parameters. The second
49 /// parameter could be 0. After the connection is established, a
50 /// Ping 0,0 will be sent from server to client. The message will
51 /// also be sent to client on the start of Play and in response of
52 /// a Seek or Pause/Resume request. This Ping tells client to
53 /// re-calibrate the clock with the timestamp of the next packet
55 /// 0x01: Tell the stream to clear the playing buffer.
56 /// 0x02: Stream dry (not sure what this means!)
57 /// 0x03: Buffer time of the client. The third parameter is the buffer
58 /// time in milliseconds.
59 /// 0x04: Reset a stream. Used together with type 0 in the case of VOD.
60 /// Often sent before type 0.
61 /// 0x06: Ping the client from server. The second parameter is the current
63 /// 0x07: Pong reply from client. The second parameter is the time the
64 /// server sent with his ping request.
65 /// 0x1a: SWFVerification request
66 /// 0x1b: SWFVerification response
67 /// 0x1f: Not sure, maybe buffer empty.
68 /// 0x20: Buffer ready.
71 CONTROL_CLEAR_STREAM
= 0x00,
72 CONTROL_CLEAR_BUFFER
= 0x01,
73 CONTROL_STREAM_DRY
= 0x02,
74 CONTROL_BUFFER_TIME
= 0x03,
75 CONTROL_RESET_STREAM
= 0x04,
78 CONTROL_REQUEST_VERIFY
= 0x1a,
79 CONTROL_RESPOND_VERIFY
= 0x1b,
80 CONTROL_BUFFER_EMPTY
= 0x1f,
81 CONTROL_BUFFER_READY
= 0x20
84 /// The known channels.
86 /// CHANNEL_CONTROL1 is for internal controls:
89 /// send bytes received.
91 /// These contain no AMF data.
93 /// CHANNEL_CONTROL2 is for ActionScript controls
96 /// connect: Maybe from ASNative(2100, 0) (connect)
98 /// deleteStream: Maybe ASNative(2100, 1) (close)
99 /// FCSubscribe: Don't know.
101 /// These all contain AMF data.
104 CHANNEL_CONTROL1
= 0x02,
105 CHANNEL_CONTROL2
= 0x03,
109 /// The known packet types.
112 PACKET_TYPE_NONE
= 0x00,
113 PACKET_TYPE_CHUNK_SIZE
= 0x01,
114 PACKET_TYPE_BYTES_READ
= 0x03,
115 PACKET_TYPE_CONTROL
= 0x04,
116 PACKET_TYPE_SERVERBW
= 0x05,
117 PACKET_TYPE_CLIENTBW
= 0x06,
118 PACKET_TYPE_AUDIO
= 0x08,
119 PACKET_TYPE_VIDEO
= 0x09,
120 PACKET_TYPE_FLEX_STREAM_SEND
= 0x0f,
121 PACKET_TYPE_FLEX_SHARED_OBJECT
= 0x10,
122 PACKET_TYPE_FLEX_MESSAGE
= 0x11,
123 PACKET_TYPE_METADATA
= 0x12,
124 PACKET_TYPE_SHARED_OBJECT
= 0x13,
125 PACKET_TYPE_INVOKE
= 0x14,
126 PACKET_TYPE_FLV
= 0x16
129 /// The PacketSize specifies the number of fields contained in the header.
131 /// 1. A large packet has all header fields.
132 /// We would expect the first packet on any channel to be large.
133 /// 2. A medium packet has the same m_nInfoField2 and packet type.
134 /// 3. A small packet has the same data size.
135 /// 4. A minimal packet has all fields the same.
137 /// The minimal and small data packets can be used to send a payload in more
138 /// than one packet. If the data received is smaller than the specified data
139 /// size, the packet remains in the channel with its payload. Data from each
140 /// new packet is added to this stored payload until all the advertised data
143 /// These names are taken from rtmpdump.
145 RTMP_PACKET_SIZE_LARGE
= 0,
146 RTMP_PACKET_SIZE_MEDIUM
= 1,
147 RTMP_PACKET_SIZE_SMALL
= 2,
148 RTMP_PACKET_SIZE_MINIMUM
= 3
151 /// The RTMPHeader contains all the fields for the packet header.
154 /// The maximum header size of an RTMP packet.
155 static const size_t headerSize
= 18;
159 headerType(RTMP_PACKET_SIZE_LARGE
),
160 packetType(PACKET_TYPE_NONE
),
167 PacketSize headerType
;
168 PacketType packetType
;
172 /// This is encoded either as in the 3-byte relative timestamp field or the
173 /// 4 byte extended (absolute) timestamp field.
174 std::uint32_t _timestamp
;
176 /// This seems to be used for NetStream.play.
177 std::uint32_t _streamID
;
181 // The size of the data.
186 /// An RTMPPacket class contains a full description of an RTMP packet.
189 /// header information
192 /// An RTMPPacket may be copied without a large penalty. This is to allow
193 /// storage in the RTMP client's channels.
196 /// Construct a packet with an optional reserved memory allocation.
198 /// @param reserve The amount of space in bytes to reserve for the
199 /// message body. This can save reallocations when
200 /// appending AMF data. Space for the header is
201 /// always reserved and is not affected by this
203 explicit RTMPPacket(size_t reserve
= 0);
205 /// Copy constructor.
207 /// Creates an identical RTMPPacket with shared ownership of the
209 RTMPPacket(const RTMPPacket
& other
);
215 /// A buffer with enough storage to write the entire message.
217 /// This always includes at least the header. Storage for the message
218 /// payload is added as necessary.
219 std::shared_ptr
<SimpleBuffer
> buffer
;
225 /// Check whether an RTMPPacket has a payload.
227 /// Only stored packets may not have a payload. A packet without a payload
228 /// has already been processed and is only used for its header information.
230 hasPayload(const RTMPPacket
& p
)
232 return (p
.buffer
.get());
235 /// Clear the message body and the bytes read of an RTMPPacket.
237 /// This is to be used to free used information from packets in a channel.
238 /// The header information must be preserved for future packets, but the
239 /// payload is no longer needed once read.
241 clearPayload(RTMPPacket
& p
)
247 /// The current size of the space allocated for the message payload.
249 /// For messages we create, this matches the exact size of the payload. For
250 /// messages we read, this is the expected size of the data.
252 payloadSize(const RTMPPacket
& p
)
254 assert(hasPayload(p
));
255 const SimpleBuffer
& buf
= *p
.buffer
;
256 assert(buf
.size() >= RTMPHeader::headerSize
);
257 return buf
.size() - RTMPHeader::headerSize
;
260 /// Access the payload data section of the buffer.
262 payloadData(RTMPPacket
& p
)
264 assert(hasPayload(p
));
265 SimpleBuffer
& buf
= *p
.buffer
;
266 return buf
.data() + RTMPHeader::headerSize
;
269 /// Access the payload data section of the buffer.
270 inline const std::uint8_t*
271 payloadData(const RTMPPacket
& p
)
273 assert(hasPayload(p
));
274 const SimpleBuffer
& buf
= *p
.buffer
;
275 return buf
.data() + RTMPHeader::headerSize
;
278 /// Get the end of the allocated payload data section of the buffer.
280 /// Note that this is only valid for packets we create, and for packets
281 /// we have fully read. Stored packets that have not yet received all data
282 /// have allocated space that has not yet been written.
283 inline const std::uint8_t*
284 payloadEnd(const RTMPPacket
& p
)
286 assert(hasPayload(p
));
287 SimpleBuffer
& buf
= *p
.buffer
;
288 return buf
.data() + buf
.size();
291 /// Check if a packet is ready for processing.
293 /// A packet is ready for processing if its payload size matches the data
294 /// size in its header. It may take several successive packets to form a
297 isReady(const RTMPPacket
& p
) {
298 return p
.bytesRead
== p
.header
.dataSize
;
302 /// This class is for handling the RTMP protocol.
304 /// Only the RTMP protocol itself is handled in this class. An RTMP connection
305 /// is valid only when connected() is true.
307 /// An RTMP object may be closed and reconnected. As soon as connect() returns
308 /// true, callers are responsible for calling close().
310 /// RTMP has a set of channels for incoming and outgoing packets. Packets
311 /// are stored here for two reasons:
312 /// 1. The payload size exceeds the chunk size, so a single payload requires
313 /// several complete packets. A packet is not 'ready' unless it has a
314 /// complete payload, or is the packet that completes the payload of
315 /// previous packets.
316 /// 2. Subsequent packets sent on the same channel can be compressed if they
317 /// have the same header information. The stored packet header is used for
318 /// comparison. For this case, the payload is no longer necessary.
320 /// A different case applies to incomplete packets. The payload of a single
321 /// packet (whether the packet is 'ready' or not) is the smaller of (a) the
322 /// advertised data size and (b) the chunk size. Until this much data has
323 /// been read, the packet is incomplete. Whereas Gnash always
324 /// expects a complete header to be available or none at all, the payload
325 /// can be read over several calls to update().
326 struct DSOEXPORT RTMP
329 /// Construct a non-connected RTMP handler.
334 /// Initiate a network connection.
336 /// Note that this only creates the TCP connection and carries out the
337 /// handshake. An active data connection needs an AMF connect request,
338 /// which is not part of the RTMP protocol.
340 /// @return true if the connection attempt starts, otherwise false.
341 /// A return of false means that the RTMP object is in a
342 /// closed state and can be reconnected.
343 bool connect(const URL
& url
);
345 /// This is used for sending call requests from the core.
347 /// These are sent as invoke packets on CHANNEL_CONTROL2. The AMF data
350 /// 2. callback number,
353 void call(const SimpleBuffer
& amf
);
355 /// This is used for sending NetStream requests.
357 /// These include play and pause. They are sent as invoke packets on the
360 /// @param id The stream ID to control. This is encoded in the header,
361 /// not the AMF payload.
362 void play(const SimpleBuffer
& amf
, int id
);
364 /// Instruct server to buffer this much data.
366 /// @param time time in milliseconds.
367 /// @param streamID the ID of the stream to set buffer time on.
368 void setBufferTime(size_t time
, int streamID
);
370 /// Whether we have a basic connection to a server.
372 /// This only means that the handshake is complete and that AMF requests
373 /// can be sent to the server. It does not mean that was can send or
374 /// receive media streams.
376 /// You should ensure that connected() is true before attempting to send
378 bool connected() const {
382 /// Whether the RTMP connection is in error condition.
384 /// This is a fatal error.
389 /// This function handles reading incoming data and filling data queues.
391 /// You should call this function regularly once the initial connection
392 /// has been initiated.
394 /// Its tasks involve:
395 /// 1. completing the handshake
396 /// 2. checking for socket errors
397 /// 3. reading incoming data
398 /// 4. filling data queues.
400 /// None of those things should concern you. Just call the function
401 /// regularly and use connected(), error(), and check the message
405 /// Close the connection.
407 /// A new connection may now be opened.
410 /// Get an AMF message received from the server.
412 /// TODO: this returns the whole RTMP message, which is ugly. And it
413 /// only returns one at time, and can return a null pointer. We need
414 /// a better way to retrieve the messages.
415 std::shared_ptr
<SimpleBuffer
> getMessage() {
416 if (_messageQueue
.empty()) return std::shared_ptr
<SimpleBuffer
>();
417 std::shared_ptr
<SimpleBuffer
> b
= _messageQueue
.front();
418 _messageQueue
.pop_front();
422 /// Get an FLV packet received from the server
424 /// TODO: this returns the whole RTMP message, which is ugly. And it
425 /// only returns one at time, and can return a null pointer. We need
426 /// a better way to retrieve the frames.
427 std::shared_ptr
<SimpleBuffer
> getFLVFrame() {
428 if (_flvQueue
.empty()) return std::shared_ptr
<SimpleBuffer
>();
429 std::shared_ptr
<SimpleBuffer
> b
= _flvQueue
.front();
430 _flvQueue
.pop_front();
434 /// Handle an RTMPPacket.
435 void handlePacket(const RTMPPacket
& packet
);
437 /// Read from the socket.
438 int readSocket(std::uint8_t* dst
, int num
);
440 /// Send an RTMPPacket on the connection.
441 bool sendPacket(RTMPPacket
& packet
);
443 /// Store the server bandwidth
445 /// Not sure why we need this.
446 void setServerBandwidth(std::uint32_t bw
) {
447 _serverBandwidth
= bw
;
450 /// Get the stored server bandwidth.
451 std::uint32_t serverBandwidth() const {
452 return _serverBandwidth
;
455 /// Store our bandwidth
456 void setBandwidth(std::uint32_t bw
) {
460 /// Get our bandwidth.
461 std::uint32_t bandwidth() const {
467 std::uint8_t m_nClientBW2
;
478 /// Read an RTMP packet from the connection.
479 bool readPacketHeader(RTMPPacket
& packet
);
481 bool readPacketPayload(RTMPPacket
& packet
);
483 /// Check whether a packet exists on a channel.
484 bool hasPacket(ChannelType t
, size_t channel
) const;
486 /// Retrieve a stored packet.
488 /// If no packet exists on the channel, a new one will be created and
489 /// returned. Use hasPacket() to check whether a previous packet exists.
490 RTMPPacket
& getPacket(ChannelType t
, size_t channel
);
492 /// Store a packet in a channel.
494 /// A copy of the packet is stored and returned. Any data is shared
495 /// between the copies until explicitly reset.
496 RTMPPacket
& storePacket(ChannelType t
, size_t channel
, const RTMPPacket
& p
);
498 /// A set of channels. An RTMP handler has two sets.
500 /// Packets are stored on these channels. As soon as a packet has been
501 /// processed, its payload is removed. The header remains in memory to
502 /// allow compression of later packets.
504 /// RTMPPackets must be stored with an absolute timestamp.
505 typedef std::map
<size_t, RTMPPacket
> ChannelSet
;
509 /// A set of channels for receiving packets.
510 ChannelSet _inChannels
;
512 /// A set of channels for sending packets.
513 ChannelSet _outChannels
;
515 std::deque
<std::shared_ptr
<SimpleBuffer
> > _messageQueue
;
516 std::deque
<std::shared_ptr
<SimpleBuffer
> > _flvQueue
;
518 /// Stored server bandwidth (reported by server).
519 std::uint32_t _serverBandwidth
;
521 /// Stored client bandwidth (ours), reported by server.
522 std::uint32_t _bandwidth
;
524 /// Chunk size for sending.
525 size_t _outChunkSize
;
527 std::unique_ptr
<HandShaker
> _handShaker
;
533 /// If a packet could not be read in one go, it is stored here.
535 /// This is not the same as a non-ready packet. It applies only to packets
536 /// waiting for payload data.
537 std::unique_ptr
<RTMPPacket
> _incompletePacket
;
541 /// Send a bandwidth ping to the server.
542 DSOEXPORT
bool sendServerBW(RTMP
& r
);
544 /// Send a control packet
545 bool sendCtrl(RTMP
& r
, ControlType
, unsigned int nObject
, unsigned int nTime
);
547 /// Logging assistance for PacketType.
548 std::ostream
& operator<<(std::ostream
& o
, PacketType p
);
550 /// Logging assistance for ControlType.
551 std::ostream
& operator<<(std::ostream
& o
, ControlType t
);