1 //
2 //   Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012
3 //   Free Software Foundation, Inc
4 //
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.
9 //
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.
14 //
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
18 
19 #ifndef GNASH_LIBNET_RTMP_H
20 #define GNASH_LIBNET_RTMP_H
21 
22 #include <deque>
23 #include <cstdint>
24 #include <memory>
25 #include <boost/lexical_cast.hpp>
26 #include <string>
27 #include <vector>
28 #include <time.h>
29 
30 #include "amf.h"
31 #include "element.h"
32 #include "network.h"
33 #include "buffer.h"
34 #include "rtmp_msg.h"
35 #include "cque.h"
36 #include "dsodefs.h"
37 #include "utility.h"
38 
39 namespace gnash
40 {
41 
42 /// \page RTMP RTMP Protocol
43 /// \section rtmp_handshake RTMP Handshake
44 ///     The headers and data for the initial RTMP handshake differ from
45 ///     what is used by RTMP during normal message processing. The layout
46 ///     is this:
47 /// <pre>
48 ///     [version (1 byte)]
49 ///     [1st timestamp (4 bytes)]
50 ///     [2nd timestamp (4 bytes)]
51 ///     [1528 bytes of random data]
52 /// </pre>
53 ///
54 ///     The handshake process is client sends a handhsake request to the
55 ///     server. This is 1537 bytes (version + handshake).
56 ///     The server then responds with a 3073 byte packet, which is the
57 ///     version byte plus two 1536 byte packets, the second one being the
58 ///     the same random data as we originally sent, but with the header
59 ///     changed.
60 ///
61 /// \section rtmp_packet RTMP Packet
62 ///     An RTMP packet has a variablew length header field, followed by data
63 ///     encoded in AMF format. The header can be one of 1, 4, 8, or 12 bytes.
64 ///
65 
66 
67 /// \var RTMP_HANDSHAKE_VERSION_SIZE
68 ///     The RTMP version field of the handshake is 1 byte large
69 const int  RTMP_HANDSHAKE_VERSION_SIZE = 1;
70 /// \var RTMP_VERSION
71 ///     The RTMP version number for now is always a 3.
72 const std::uint8_t RTMP_VERSION = 0x3;
73 /// \var
74 ///    This is the total size of an RTMP packet, not including the
75 ///    version field.
76 const int  RTMP_HANDSHAKE_SIZE	= 1536;
77 /// \var
78 ///    This is the size of the random data section in the RTMP handshake
79 const int  RTMP_RANDOM_SIZE	= 1528;
80 /// \var
81 ///    The RTMP handshake header if always 2 32bit words. (8 bytes)
82 const int  RTMP_HANDSHAKE_HEADER_SIZE = 8;
83 
84 /// \var
85 ///    This is the maximum number of channels supported in a single
86 ///    RTMP connection.
87 const int  MAX_AMF_INDEXES	= 64;
88 
89 /// \par RTMP Header
90 ///
91 /// \var
92 ///     This is a mask to get to the upper 2 bits of the header
93 const int  RTMP_HEADSIZE_MASK	= 0xc0;
94 /// \var
95 ///     This is a mask to get to the lower 6 bits of the header
96 const char RTMP_INDEX_MASK	= 0x3f;
97 /// \var
98 ///     All video data packets are 128 bytes
99 const int  RTMP_VIDEO_PACKET_SIZE = 128;
100 /// \var
101 ///     All audio data packets are 64 bytes
102 const int  RTMP_AUDIO_PACKET_SIZE = 64;
103 /// \var
104 ///     While the RTMP header can be one of 4 sizes, this is the
105 ///     maximum size used
106 const int  RTMP_MAX_HEADER_SIZE = 12;
107 /// \var
108 ///     All System Ping messages are 6 bytes
109 const int  PING_MSG_SIZE	= 6;
110 /// \var
111 ///     This is a reserved channel for system messages
112 const int  RTMP_SYSTEM_CHANNEL = 2;
113 
114 // For terminating sequences, a byte with value 0x09 is used.
115 const char TERMINATOR = 0x09;
116 
117 // Each packet consists of the following:
118 //
119 // The first byte of the AMF file/stream is believed to be a version
120 // indicator. So far the only valid value for this field that has been
121 // found is 0x00. If it is anything other than 0x00 (zero), your
122 // system should consider the AMF file/stream to be
123 // 'malformed'd. This can happen in the IDE if AMF calls are put
124 // on the stack but never executed and the user exits the movie from the
125 // IDE; the two top bytes will be random and the number of headers will
126 // be unreliable.
127 
128 // The third and fourth bytes form an integer value that specifies the
129 // number of headers.
130 typedef struct {
131     std::uint8_t version;
132     std::uint8_t source;
133     std::uint32_t  count;
134 } amfpacket_t;
135 
136 typedef enum {
137     onStatus,
138     onResult,
139     onDebugEvents
140 } amfresponse_e;
141 
142 class DSOEXPORT RTMP : public Network
143 {
144 public:
145     typedef std::map<const char*, cygnal::Element> AMFProperties;
146     typedef std::deque<CQue *> queues_t;
147     typedef enum {
148 	ENCODE_AMF0=0x0,
149 	ENCODE_AMF3=0x3
150     } encoding_types_e;
151     typedef enum {
152 	RAW     = 0x0001,
153 	ADPCM   = 0x0002,
154 	MP3     = 0x0004,
155 	INTEL   = 0x0005,
156 	CELT    = 0x0008,		// unique to Gnash
157 	NELLY8  = 0x0020,
158 	NELLY   = 0x0040,
159 	G711A   = 0x0080,
160 	G711U   = 0x0100,
161 	NELLY16 = 0x0200,
162 	AAC     = 0x0400,
163 	SPEEX   = 0x0800,
164 	DEFAULT_AUDIO_SET = 0x0267,
165 	ALLAUDIO = 0x0fff
166     } audiocodecs_e;
167     typedef enum {
168 	UNUSED   = 0x0001,
169 	JPEG     = 0x0002,
170 	SORENSON = 0x4,
171 	ADOBE    = 0x0008,
172 	VP6      = 0x0010,
173 	VP6ALPHA = 0x0020,
174 	SCREEN2  = 0x0040,
175 	H264     = 0x0080,
176 	DEFAULT_VIDEO_SET = 0x007c,
177 	ALLVIDEO = 0x00ff
178     } videocodecs_e;
179     typedef enum {
180 	SEEK = 0x1,
181 	AMF0 = 0x0,
182 	AMF3 = 0x3
183     } videofunction_e;
184     // The second byte of the AMF file/stream is appears to be 0x00 if the
185     // client is the Flash Player and 0x01 if the client is the FlashCom
186     // server.
187     typedef enum {
188         NONE         = 0x0,
189         CHUNK_SIZE   = 0x1,
190         ABORT        = 0x2,
191         BYTES_READ   = 0x3,
192         USER         = 0x4,
193         WINDOW_SIZE  = 0x5,
194         SET_BANDWITH = 0x6,
195         ROUTE        = 0x7,
196         AUDIO_DATA   = 0x8,
197         VIDEO_DATA   = 0x9,
198         SHARED_OBJ   = 0xa,
199 	AMF3_NOTIFY  = 0xf,
200 	AMF3_SHARED_OBJ = 0x10,
201 	AMF3_INVOKE  = 0x11,
202         NOTIFY       = 0x12,
203         INVOKE       = 0x14,
204 	FLV_DATA     = 0x16
205     } content_types_e;
206     typedef enum {
207 	STREAM_START  = 0x0,
208 	STREAM_EOF    = 0x1,
209 	STREAM_NODATA = 0x2,
210 	STREAM_BUFFER = 0x3,
211 	STREAM_LIVE   = 0x4,
212 	STREAM_PING   = 0x6,
213 	STREAM_PONG   = 0x7
214     } user_control_e;
215     typedef enum {
216          CREATE_OBJ     = 0x1,	    // Client sends event
217          DELETE_OBJ     = 0x2,	    // Client sends event
218          REQUEST_CHANGE = 0x3,	    // Client sends event
219          CHANGE         = 0x4,	    // Server sends event
220          SUCCESS_CLIENT = 0x5,	    // Server sends event
221          SEND_MESSAGE   = 0x6,	    // Client sends event
222          STATUS         = 0x7,	    // Server sends evetn
223          CLEAR          = 0x8,	    // Server sends event
224          DELETE_SLOT    = 0x9,	    // Server sends event
225          REQUEST_DELETE_SLOT = 0xa, // Client sends event
226          SUCCESS_SERVER = 0xb	    // Server sends event
227      } sharedobj_types_e;
228     typedef enum {
229 	PING_CLEAR  = 0x0,	// clear the stream
230 	PING_PLAY   = 0x1,	// clear the playing buffer
231 	PING_TIME   = 0x3,	// Buffer time in milliseconds
232 	PING_RESET  = 0x4,	// Reset stream
233 	PING_CLIENT = 0x6,	// Ping the client from the server
234 	PONG_CLIENT = 0x7	// pong reply from client to server
235     } rtmp_ping_e;
236     typedef enum {
237 	STREAM_PLAY,		// play the existing stream
238 	STREAM_PAUSE,		// pause the existing stream
239 	STREAM_PUBLISH,		// publish the existing stream
240 	STREAM_STOP,		// stop the existing stream
241 	STREAM_SEEK		// seek in the existing stream
242     } rtmp_op_e;
243     typedef struct {
244 	rtmp_ping_e type;	// the type of the ping message
245 	std::uint16_t target; // all Ping message data fields
246 	std::uint16_t param1; // are 2 bytes long
247 	std::uint16_t param2;
248 	std::uint16_t param3;
249     } rtmp_ping_t;
250     typedef struct {
251 	user_control_e type;
252 	std::uint32_t param1;
253 	std::uint32_t param2;	// only used by
254     } user_event_t;
255     typedef enum {
256         RTMP_STATE_HANDSHAKE_SEND,
257         RTMP_STATE_HANDSHAKE_RECV,
258         RTMP_STATE_HANDSHAKE_ACK,
259         RTMP_STATE_CONNECT,
260         RTMP_STATE_NETCONNECT,
261         RTMP_STATE_NETSTREAM,
262         RTMP_STATE_HEADER,
263         RTMP_STATE_DONE
264     } rtmp_state_t;
265 //     typedef struct {
266 // 	rtmp_status_e status;
267 // 	std::string   method;
268 // 	double        streamid;
269 // 	std::vector<std::shared_ptr<cygnal::Element> > objs;
270 //     } rtmp_msg_t;
271     typedef enum {
272         RTMP_ERR_UNDEF,
273         RTMP_ERR_NOTFOUND,
274         RTMP_ERR_PERM,
275         RTMP_ERR_DISKFULL,
276         RTMP_ERR_ILLEGAL,
277         RTMP_ERR_UNKNOWNID,
278         RTMP_ERR_EXISTS,
279         RTMP_ERR_NOSUCHUSER,
280         RTMP_ERR_TIMEOUT,
281         RTMP_ERR_NORESPONSE
282     } rtmp_error_t;
283 
284 // Each header consists of the following:
285 // a single byte that is the index of the RTMP channel,
286 // then two bits that's a flag to note the size of the header,
287 // which can be 1, 4, 8, or 12 bytes long.
288 
289 // More info at http://wiki.gnashdev.org/RTMP
290     typedef struct {
291 	int             channel;
292 	int             head_size;
293 	int             bodysize;
294 	RTMPMsg::rtmp_source_e   src_dest;
295 	content_types_e type;
296     } rtmp_head_t;
297     typedef struct {
298 	std::uint32_t uptime;
299 	std::uint8_t version[4];
300     } rtmp_handshake_head_t;
301     typedef enum {
302         HEADER_12 = 0x0,
303         HEADER_8  = 0x40,
304         HEADER_4  = 0x80,
305         HEADER_1  = 0xc0
306     } rtmp_headersize_e;
307 
308 // Each body consists of the following:
309 //
310 // * UTF String - Target
311 // * UTF String - Response
312 // * Long - Body length in bytes
313 // * Variable - Actual data (including a type code)
314 //     typedef struct {
315 //         amf::amfutf8_t target;
316 //         amf::amfutf8_t response;
317 // 	std::uint32_t length;
318 //         void *data;
319 //     } rtmp_body_t;
320 
321     RTMP();
322     virtual ~RTMP();
323 
324     // Decode
325     std::shared_ptr<rtmp_head_t> decodeHeader(std::uint8_t *header);
326     std::shared_ptr<rtmp_head_t> decodeHeader(cygnal::Buffer &data);
327 
328     std::shared_ptr<cygnal::Buffer> encodeHeader(int amf_index,
329 					rtmp_headersize_e head_size,
330 					size_t total_size, content_types_e type,
331 					RTMPMsg::rtmp_source_e routing);
332     std::shared_ptr<cygnal::Buffer> encodeHeader(int amf_index,
333 						rtmp_headersize_e head_size);
334 
335     void addProperty(cygnal::Element &el);
336     void addProperty(char *name, cygnal::Element &el);
337     void addProperty(std::string &name, cygnal::Element &el);
338     cygnal::Element &getProperty(const std::string &name);
339 //     void setHandler(Handler *hand) { _handler = hand; };
340     int headerSize(std::uint8_t header);
341 
getHeader()342     rtmp_head_t *getHeader()    { return &_header; };
getHeaderSize()343     int getHeaderSize()         { return _header.head_size; };
getTotalSize()344     int getTotalSize()          { return _header.bodysize; };
getRouting()345     RTMPMsg::rtmp_source_e getRouting()  { return _header.src_dest; };
getChannel()346     int getChannel()            { return _header.channel; };
getPacketSize()347     int getPacketSize()         { return _packet_size; };
getMysteryWord()348     int getMysteryWord()        { return _mystery_word; };
349 
350     // Decode an RTMP message
351     std::shared_ptr<RTMPMsg> decodeMsgBody(std::uint8_t *data, size_t size);
352     std::shared_ptr<RTMPMsg> decodeMsgBody(cygnal::Buffer &buf);
353 
354     virtual std::shared_ptr<rtmp_ping_t> decodePing(std::uint8_t *data);
355     std::shared_ptr<rtmp_ping_t> decodePing(cygnal::Buffer &buf);
356 
357     virtual std::shared_ptr<user_event_t> decodeUserControl(std::uint8_t *data);
358     std::shared_ptr<user_event_t> decodeUserControl(cygnal::Buffer &buf);
359     virtual std::shared_ptr<cygnal::Buffer> encodeUserControl(user_control_e, std::uint32_t data);
360 
361 
362     // These are handlers for the various types
363     virtual std::shared_ptr<cygnal::Buffer> encodeChunkSize(int size);
364     virtual void decodeChunkSize();
365 
366     virtual std::shared_ptr<cygnal::Buffer> encodeBytesRead();
367     virtual void decodeBytesRead();
368     virtual std::shared_ptr<cygnal::Buffer> encodeServer();
369     virtual void decodeServer();
370 
371     virtual std::shared_ptr<cygnal::Buffer> encodeClient();
372     virtual void decodeClient();
373 
374     virtual std::shared_ptr<cygnal::Buffer> encodeAudioData();
375     virtual void decodeAudioData();
376 
377     virtual std::shared_ptr<cygnal::Buffer> encodeVideoData();
378     virtual void decodeVideoData();
379 
380     virtual std::shared_ptr<cygnal::Buffer> encodeNotify();
381     virtual void decodeNotify();
382 
383     virtual std::shared_ptr<cygnal::Buffer> encodeSharedObj();
384     virtual void decodeSharedObj();
385 
386     virtual std::shared_ptr<cygnal::Buffer> encodeInvoke();
387     virtual void decodeInvoke();
388 
389     // Receive a message, which is a series of AMF elements, seperated
390     // by a one byte header at regular byte intervals. (128 bytes for
391     // video data by default). Each message may contain multiple packets.
392     std::shared_ptr<cygnal::Buffer> recvMsg();
393     std::shared_ptr<cygnal::Buffer> recvMsg(int fd);
394 
395     // Send a message, usually a single ActionScript object. This message
396     // may be broken down into a series of packets on a regular byte
397     // interval. (128 bytes for video data by default). Each message main
398     // contain multiple packets.
399     bool sendMsg(cygnal::Buffer &data);
400     bool sendMsg(int channel, rtmp_headersize_e head_size,
401 	      size_t total_size, content_types_e type,
402 	      RTMPMsg::rtmp_source_e routing, cygnal::Buffer &data);
403     bool sendMsg(int fd, int channel, rtmp_headersize_e head_size,
404 	      size_t total_size, content_types_e type,
405 	      RTMPMsg::rtmp_source_e routing, cygnal::Buffer &data);
406     bool sendMsg(int channel, rtmp_headersize_e head_size,
407 		 size_t total_size, content_types_e type,
408 		 RTMPMsg::rtmp_source_e routing, std::uint8_t *data, size_t size);
409     bool sendMsg(int fd, int channel, rtmp_headersize_e head_size,
410 		 size_t total_size, content_types_e type,
411 		 RTMPMsg::rtmp_source_e routing, std::uint8_t *data, size_t size);
412 
413 #if 0
414     // Send a Msg, and expect a response back of some kind.
415     RTMPMsg *sendRecvMsg(int amf_index, rtmp_headersize_e head_size,
416 			      size_t total_size, content_types_e type,
417 			      RTMPMsg::rtmp_source_e routing, cygnal::Buffer &buf);
418 #endif
419     // Split a large buffer into multiple smaller ones of the default chunksize
420     // of 128 bytes. We read network data in big chunks because it's more efficient,
421     // but RTMP uses a weird scheme of a standard header, and then every chunksize
422     // bytes another 1 byte RTMP header. The header itself is not part of the byte
423     // count.
424     std::shared_ptr<queues_t> split(cygnal::Buffer &buf);
425     std::shared_ptr<queues_t> split(std::uint8_t *data, size_t size);
426 
427     CQue &operator[] (size_t x) { return _queues[x]; }
428 
429     /// \method getTime
430     ///    The time on most systems these days is a 64 bit long, but swf
431     ///    is old, so it only uses a 32 bit integer instead. We know casting
432     ///    looses precision, but that's just the way it is in RTMP.
getTime()433     std::uint32_t getTime() {
434 	time_t t;
435 	time(&t);
436 	return boost::lexical_cast<std::uint32_t>(t);
437     };
438 
439     void dump();
440   protected:
441     AMFProperties _properties;
442     cygnal::Buffer	*_handshake;
443 //     Handler	*_handler;
444     rtmp_head_t	_header;
445     int         _packet_size;
446     int         _mystery_word;
447     size_t	_chunksize[MAX_AMF_INDEXES];
448     size_t	_lastsize[MAX_AMF_INDEXES];
449     std::vector<size_t> _bodysize;
450     std::vector<content_types_e> _type;
451     int		_timeout;
452     CQue	_queues[MAX_AMF_INDEXES];
453 //    queues_t    _channels;
454     cygnal::Buffer	_buffer;
455     rtmp_handshake_head_t _handshake_header;
456 };
457 
458 } // end of gnash namespace
459 // end of _RTMP_H_
460 #endif
461 
462 // local Variables:
463 // mode: C++
464 // indent-tabs-mode: t
465 // End:
466 
467