• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • Examples
  • File List
  • File Members

rtmp.h

Go to the documentation of this file.
00001 // 
00002 //   Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software
00003 //   Foundation, Inc
00004 // 
00005 // This program is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation; either version 3 of the License, or
00008 // (at your option) any later version.
00009 // 
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 // 
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program; if not, write to the Free Software
00017 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018 
00019 #ifndef GNASH_LIBNET_RTMP_H
00020 #define GNASH_LIBNET_RTMP_H
00021 
00022 #include <deque>
00023 #include <boost/cstdint.hpp>
00024 #include <boost/shared_ptr.hpp>
00025 #include <boost/scoped_ptr.hpp>
00026 #include <boost/lexical_cast.hpp>
00027 #include <string>
00028 #include <vector>
00029 #include <time.h>
00030 
00031 #include "amf.h"
00032 #include "element.h"
00033 #include "network.h"
00034 #include "buffer.h"
00035 #include "rtmp_msg.h"
00036 #include "cque.h"
00037 #include "dsodefs.h"
00038 #include "utility.h"
00039 
00040 namespace gnash
00041 {
00042 
00066 
00067 
00070 const int  RTMP_HANDSHAKE_VERSION_SIZE = 1;
00073 const boost::uint8_t RTMP_VERSION = 0x3;
00077 const int  RTMP_HANDSHAKE_SIZE  = 1536;
00080 const int  RTMP_RANDOM_SIZE     = 1528;
00083 const int  RTMP_HANDSHAKE_HEADER_SIZE = 8;
00084 
00088 const int  MAX_AMF_INDEXES      = 64;
00089 
00094 const int  RTMP_HEADSIZE_MASK   = 0xc0;
00097 const char RTMP_INDEX_MASK      = 0x3f;
00100 const int  RTMP_VIDEO_PACKET_SIZE = 128;
00103 const int  RTMP_AUDIO_PACKET_SIZE = 64;
00107 const int  RTMP_MAX_HEADER_SIZE = 12;
00110 const int  PING_MSG_SIZE        = 6;
00113 const int  RTMP_SYSTEM_CHANNEL = 2;
00114 
00115 // For terminating sequences, a byte with value 0x09 is used.
00116 const char TERMINATOR = 0x09;
00117 
00118 // Each packet consists of the following:
00119 //
00120 // The first byte of the AMF file/stream is believed to be a version
00121 // indicator. So far the only valid value for this field that has been
00122 // found is 0x00. If it is anything other than 0x00 (zero), your
00123 // system should consider the AMF file/stream to be
00124 // 'malformed'd. This can happen in the IDE if AMF calls are put
00125 // on the stack but never executed and the user exits the movie from the
00126 // IDE; the two top bytes will be random and the number of headers will
00127 // be unreliable.
00128 
00129 // The third and fourth bytes form an integer value that specifies the
00130 // number of headers.
00131 typedef struct {
00132     boost::uint8_t version;
00133     boost::uint8_t source;
00134     boost::uint32_t  count;
00135 } amfpacket_t;
00136 
00137 typedef enum {
00138     onStatus,
00139     onResult,
00140     onDebugEvents
00141 } amfresponse_e;
00142 
00143 class DSOEXPORT RTMP : public Network
00144 {
00145 public:
00146     typedef std::map<const char*, cygnal::Element> AMFProperties;
00147     typedef std::deque<CQue *> queues_t;
00148     typedef enum {
00149         ENCODE_AMF0=0x0,
00150         ENCODE_AMF3=0x3
00151     } encoding_types_e;
00152     typedef enum {
00153         RAW     = 0x0001,
00154         ADPCM   = 0x0002,
00155         MP3     = 0x0004,
00156         INTEL   = 0x0005,
00157         CELT    = 0x0008,               // unique to Gnash
00158         NELLY8  = 0x0020,
00159         NELLY   = 0x0040,
00160         G711A   = 0x0080,
00161         G711U   = 0x0100,
00162         NELLY16 = 0x0200,
00163         AAC     = 0x0400,
00164         SPEEX   = 0x0800,
00165         DEFAULT_AUDIO_SET = 0x0267,
00166         ALLAUDIO = 0x0fff
00167     } audiocodecs_e;
00168     typedef enum {
00169         UNUSED   = 0x0001,
00170         JPEG     = 0x0002,
00171         SORENSON = 0x4,
00172         ADOBE    = 0x0008,
00173         VP6      = 0x0010,
00174         VP6ALPHA = 0x0020,
00175         SCREEN2  = 0x0040,
00176         H264     = 0x0080,
00177         DEFAULT_VIDEO_SET = 0x007c,
00178         ALLVIDEO = 0x00ff
00179     } videocodecs_e;
00180     typedef enum {
00181         SEEK = 0x1,
00182         AMF0 = 0x0,
00183         AMF3 = 0x3
00184     } videofunction_e;
00185     // The second byte of the AMF file/stream is appears to be 0x00 if the
00186     // client is the Flash Player and 0x01 if the client is the FlashCom
00187     // server.
00188     typedef enum {
00189         NONE         = 0x0,
00190         CHUNK_SIZE   = 0x1,
00191         ABORT        = 0x2,
00192         BYTES_READ   = 0x3,
00193         USER         = 0x4,
00194         WINDOW_SIZE  = 0x5,
00195         SET_BANDWITH = 0x6,
00196         ROUTE        = 0x7,
00197         AUDIO_DATA   = 0x8,
00198         VIDEO_DATA   = 0x9,
00199         SHARED_OBJ   = 0xa,
00200         AMF3_NOTIFY  = 0xf,
00201         AMF3_SHARED_OBJ = 0x10,
00202         AMF3_INVOKE  = 0x11,
00203         NOTIFY       = 0x12,
00204         INVOKE       = 0x14,
00205         FLV_DATA     = 0x16
00206     } content_types_e;
00207     typedef enum {
00208         STREAM_START  = 0x0,
00209         STREAM_EOF    = 0x1,
00210         STREAM_NODATA = 0x2,
00211         STREAM_BUFFER = 0x3,
00212         STREAM_LIVE   = 0x4,
00213         STREAM_PING   = 0x6,
00214         STREAM_PONG   = 0x7
00215     } user_control_e;
00216     typedef enum {
00217          CREATE_OBJ     = 0x1,      // Client sends event
00218          DELETE_OBJ     = 0x2,      // Client sends event
00219          REQUEST_CHANGE = 0x3,      // Client sends event
00220          CHANGE         = 0x4,      // Server sends event
00221          SUCCESS_CLIENT = 0x5,      // Server sends event
00222          SEND_MESSAGE   = 0x6,      // Client sends event
00223          STATUS         = 0x7,      // Server sends evetn
00224          CLEAR          = 0x8,      // Server sends event
00225          DELETE_SLOT    = 0x9,      // Server sends event
00226          REQUEST_DELETE_SLOT = 0xa, // Client sends event
00227          SUCCESS_SERVER = 0xb       // Server sends event
00228      } sharedobj_types_e;
00229     typedef enum {
00230         PING_CLEAR  = 0x0,      // clear the stream
00231         PING_PLAY   = 0x1,      // clear the playing buffer
00232         PING_TIME   = 0x3,      // Buffer time in milliseconds
00233         PING_RESET  = 0x4,      // Reset stream
00234         PING_CLIENT = 0x6,      // Ping the client from the server
00235         PONG_CLIENT = 0x7       // pong reply from client to server
00236     } rtmp_ping_e;
00237     typedef enum {
00238         STREAM_PLAY,            // play the existing stream
00239         STREAM_PAUSE,           // pause the existing stream
00240         STREAM_PUBLISH,         // publish the existing stream
00241         STREAM_STOP,            // stop the existing stream
00242         STREAM_SEEK             // seek in the existing stream
00243     } rtmp_op_e;
00244     typedef struct {
00245         rtmp_ping_e type;       // the type of the ping message
00246         boost::uint16_t target; // all Ping message data fields
00247         boost::uint16_t param1; // are 2 bytes long
00248         boost::uint16_t param2;
00249         boost::uint16_t param3;
00250     } rtmp_ping_t;
00251     typedef struct {
00252         user_control_e type;
00253         boost::uint32_t param1;
00254         boost::uint32_t param2; // only used by 
00255     } user_event_t;
00256     typedef enum {
00257         RTMP_STATE_HANDSHAKE_SEND,
00258         RTMP_STATE_HANDSHAKE_RECV,
00259         RTMP_STATE_HANDSHAKE_ACK,
00260         RTMP_STATE_CONNECT,
00261         RTMP_STATE_NETCONNECT,
00262         RTMP_STATE_NETSTREAM,
00263         RTMP_STATE_HEADER,
00264         RTMP_STATE_DONE
00265     } rtmp_state_t;
00266 //     typedef struct {
00267 //      rtmp_status_e status;
00268 //      std::string   method;
00269 //      double        streamid;
00270 //      std::vector<boost::shared_ptr<cygnal::Element> > objs;
00271 //     } rtmp_msg_t;
00272     typedef enum {
00273         RTMP_ERR_UNDEF,
00274         RTMP_ERR_NOTFOUND,
00275         RTMP_ERR_PERM,
00276         RTMP_ERR_DISKFULL,
00277         RTMP_ERR_ILLEGAL,
00278         RTMP_ERR_UNKNOWNID,
00279         RTMP_ERR_EXISTS,
00280         RTMP_ERR_NOSUCHUSER,
00281         RTMP_ERR_TIMEOUT,
00282         RTMP_ERR_NORESPONSE
00283     } rtmp_error_t;
00284 
00285 // Each header consists of the following:
00286 // a single byte that is the index of the RTMP channel,
00287 // then two bits that's a flag to note the size of the header,
00288 // which can be 1, 4, 8, or 12 bytes long.
00289     
00290 // More info at http://wiki.gnashdev.org/RTMP
00291     typedef struct {
00292         int             channel;
00293         int             head_size;
00294         int             bodysize;
00295         RTMPMsg::rtmp_source_e   src_dest;
00296         content_types_e type;
00297     } rtmp_head_t;
00298     typedef struct {
00299         boost::uint32_t uptime;
00300         boost::uint8_t version[4];
00301     } rtmp_handshake_head_t;
00302     typedef enum {
00303         HEADER_12 = 0x0,
00304         HEADER_8  = 0x40,
00305         HEADER_4  = 0x80,
00306         HEADER_1  = 0xc0
00307     } rtmp_headersize_e;    
00308     
00309 // Each body consists of the following:
00310 //
00311 // * UTF String - Target
00312 // * UTF String - Response
00313 // * Long - Body length in bytes
00314 // * Variable - Actual data (including a type code)
00315 //     typedef struct {
00316 //         amf::amfutf8_t target;
00317 //         amf::amfutf8_t response;
00318 //      boost::uint32_t length;
00319 //         void *data;
00320 //     } rtmp_body_t;
00321     
00322     RTMP();
00323     virtual ~RTMP();
00324 
00325     // Decode
00326     boost::shared_ptr<rtmp_head_t> decodeHeader(boost::uint8_t *header);
00327     boost::shared_ptr<rtmp_head_t> decodeHeader(cygnal::Buffer &data);
00328     
00329     boost::shared_ptr<cygnal::Buffer> encodeHeader(int amf_index,
00330                                         rtmp_headersize_e head_size,
00331                                         size_t total_size, content_types_e type,
00332                                         RTMPMsg::rtmp_source_e routing);
00333     boost::shared_ptr<cygnal::Buffer> encodeHeader(int amf_index,
00334                                                 rtmp_headersize_e head_size);
00335     
00336     void addProperty(cygnal::Element &el);
00337     void addProperty(char *name, cygnal::Element &el);
00338     void addProperty(std::string &name, cygnal::Element &el);
00339     cygnal::Element &getProperty(const std::string &name);
00340 //     void setHandler(Handler *hand) { _handler = hand; };
00341     int headerSize(boost::uint8_t header);
00342 
00343     rtmp_head_t *getHeader()    { return &_header; };
00344     int getHeaderSize()         { return _header.head_size; }; 
00345     int getTotalSize()          { return _header.bodysize; }; 
00346     RTMPMsg::rtmp_source_e getRouting()  { return _header.src_dest; };
00347     int getChannel()            { return _header.channel; };
00348     int getPacketSize()         { return _packet_size; };
00349     int getMysteryWord()        { return _mystery_word; };
00350 
00351     // Decode an RTMP message
00352     boost::shared_ptr<RTMPMsg> decodeMsgBody(boost::uint8_t *data, size_t size);
00353     boost::shared_ptr<RTMPMsg> decodeMsgBody(cygnal::Buffer &buf);
00354     
00355     virtual boost::shared_ptr<rtmp_ping_t> decodePing(boost::uint8_t *data);
00356     boost::shared_ptr<rtmp_ping_t> decodePing(cygnal::Buffer &buf);
00357     
00358     virtual boost::shared_ptr<user_event_t> decodeUserControl(boost::uint8_t *data);
00359     boost::shared_ptr<user_event_t> decodeUserControl(cygnal::Buffer &buf);
00360     virtual boost::shared_ptr<cygnal::Buffer> encodeUserControl(user_control_e, boost::uint32_t data);
00361     
00362     
00363     // These are handlers for the various types
00364     virtual boost::shared_ptr<cygnal::Buffer> encodeChunkSize(int size);
00365     virtual void decodeChunkSize();
00366 
00367     virtual boost::shared_ptr<cygnal::Buffer> encodeBytesRead();
00368     virtual void decodeBytesRead();
00369     virtual boost::shared_ptr<cygnal::Buffer> encodeServer();
00370     virtual void decodeServer();
00371     
00372     virtual boost::shared_ptr<cygnal::Buffer> encodeClient();
00373     virtual void decodeClient();
00374     
00375     virtual boost::shared_ptr<cygnal::Buffer> encodeAudioData();
00376     virtual void decodeAudioData();
00377     
00378     virtual boost::shared_ptr<cygnal::Buffer> encodeVideoData();
00379     virtual void decodeVideoData();
00380     
00381     virtual boost::shared_ptr<cygnal::Buffer> encodeNotify();
00382     virtual void decodeNotify();
00383     
00384     virtual boost::shared_ptr<cygnal::Buffer> encodeSharedObj();
00385     virtual void decodeSharedObj();
00386     
00387     virtual boost::shared_ptr<cygnal::Buffer> encodeInvoke();
00388     virtual void decodeInvoke();
00389 
00390     // Receive a message, which is a series of AMF elements, seperated
00391     // by a one byte header at regular byte intervals. (128 bytes for
00392     // video data by default). Each message may contain multiple packets.
00393     boost::shared_ptr<cygnal::Buffer> recvMsg();
00394     boost::shared_ptr<cygnal::Buffer> recvMsg(int fd);
00395 
00396     // Send a message, usually a single ActionScript object. This message
00397     // may be broken down into a series of packets on a regular byte
00398     // interval. (128 bytes for video data by default). Each message main
00399     // contain multiple packets.
00400     bool sendMsg(cygnal::Buffer &data);
00401     bool sendMsg(int channel, rtmp_headersize_e head_size,
00402               size_t total_size, content_types_e type,
00403               RTMPMsg::rtmp_source_e routing, cygnal::Buffer &data);
00404     bool sendMsg(int fd, int channel, rtmp_headersize_e head_size,
00405               size_t total_size, content_types_e type,
00406               RTMPMsg::rtmp_source_e routing, cygnal::Buffer &data);
00407     bool sendMsg(int channel, rtmp_headersize_e head_size,
00408                  size_t total_size, content_types_e type,
00409                  RTMPMsg::rtmp_source_e routing, boost::uint8_t *data, size_t size);
00410     bool sendMsg(int fd, int channel, rtmp_headersize_e head_size,
00411                  size_t total_size, content_types_e type,
00412                  RTMPMsg::rtmp_source_e routing, boost::uint8_t *data, size_t size);
00413     
00414 #if 0
00415     // Send a Msg, and expect a response back of some kind.
00416     RTMPMsg *sendRecvMsg(int amf_index, rtmp_headersize_e head_size,
00417                               size_t total_size, content_types_e type,
00418                               RTMPMsg::rtmp_source_e routing, cygnal::Buffer &buf);
00419 #endif
00420     // Split a large buffer into multiple smaller ones of the default chunksize
00421     // of 128 bytes. We read network data in big chunks because it's more efficient,
00422     // but RTMP uses a weird scheme of a standard header, and then every chunksize
00423     // bytes another 1 byte RTMP header. The header itself is not part of the byte
00424     // count.
00425     boost::shared_ptr<queues_t> split(cygnal::Buffer &buf);
00426     boost::shared_ptr<queues_t> split(boost::uint8_t *data, size_t size);
00427 
00428     CQue &operator[] (size_t x) { return _queues[x]; }
00429 
00434     boost::uint32_t getTime() {
00435         time_t t;
00436         time(&t);
00437         return boost::lexical_cast<boost::uint32_t>(t);
00438     };
00439 
00440     void dump();
00441   protected:
00442     AMFProperties _properties;
00443     cygnal::Buffer      *_handshake;
00444 //     Handler  *_handler;
00445     rtmp_head_t _header;
00446     int         _packet_size;
00447     int         _mystery_word;
00448     size_t      _chunksize[MAX_AMF_INDEXES];
00449     size_t      _lastsize[MAX_AMF_INDEXES];
00450     std::vector<size_t> _bodysize;
00451     std::vector<content_types_e> _type;
00452     int         _timeout;
00453     CQue        _queues[MAX_AMF_INDEXES];
00454 //    queues_t    _channels;
00455     cygnal::Buffer      _buffer;
00456     rtmp_handshake_head_t _handshake_header;
00457 };
00458 
00459 } // end of gnash namespace
00460 // end of _RTMP_H_
00461 #endif
00462 
00463 // local Variables:
00464 // mode: C++
00465 // indent-tabs-mode: t
00466 // End:
00467 

Generated on Thu Sep 2 2010 for Gnash by  doxygen 1.7.1