/** * The MIT License (MIT) * * Copyright (c) 2013-2021 Winlin * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of * the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef SRS_PROTOCOL_RTMP_HPP #define SRS_PROTOCOL_RTMP_HPP #include #include #include #include // For srs-librtmp, @see https://github.com/ossrs/srs/issues/213 #ifndef _WIN32 #include #endif #include #include #include #include #include class SrsFastStream; class SrsBuffer; class SrsAmf0Any; class SrsMessageHeader; class SrsChunkStream; class SrsSharedPtrMessage; class SrsProtocol; class ISrsProtocolReader; class ISrsProtocolReadWriter; class SrsCreateStreamPacket; class SrsFMLEStartPacket; class SrsPublishPacket; class SrsOnMetaDataPacket; class SrsPlayPacket; class SrsCommonMessage; class SrsPacket; class SrsAmf0Object; class IMergeReadHandler; class SrsCallPacket; // The amf0 command message, command name macros #define RTMP_AMF0_COMMAND_CONNECT "connect" #define RTMP_AMF0_COMMAND_CREATE_STREAM "createStream" #define RTMP_AMF0_COMMAND_CLOSE_STREAM "closeStream" #define RTMP_AMF0_COMMAND_PLAY "play" #define RTMP_AMF0_COMMAND_PAUSE "pause" #define RTMP_AMF0_COMMAND_ON_BW_DONE "onBWDone" #define RTMP_AMF0_COMMAND_ON_STATUS "onStatus" #define RTMP_AMF0_COMMAND_RESULT "_result" #define RTMP_AMF0_COMMAND_ERROR "_error" #define RTMP_AMF0_COMMAND_RELEASE_STREAM "releaseStream" #define RTMP_AMF0_COMMAND_FC_PUBLISH "FCPublish" #define RTMP_AMF0_COMMAND_UNPUBLISH "FCUnpublish" #define RTMP_AMF0_COMMAND_PUBLISH "publish" #define RTMP_AMF0_DATA_SAMPLE_ACCESS "|RtmpSampleAccess" // The signature for packets to client. #define RTMP_SIG_FMS_VER "3,5,3,888" #define RTMP_SIG_AMF0_VER 0 #define RTMP_SIG_CLIENT_ID "ASAICiss" // The onStatus consts. #define StatusLevel "level" #define StatusCode "code" #define StatusDescription "description" #define StatusDetails "details" #define StatusClientId "clientid" // The status value #define StatusLevelStatus "status" // The status error #define StatusLevelError "error" // The code value #define StatusCodeConnectSuccess "NetConnection.Connect.Success" #define StatusCodeConnectRejected "NetConnection.Connect.Rejected" #define StatusCodeStreamReset "NetStream.Play.Reset" #define StatusCodeStreamStart "NetStream.Play.Start" #define StatusCodeStreamPause "NetStream.Pause.Notify" #define StatusCodeStreamUnpause "NetStream.Unpause.Notify" #define StatusCodePublishStart "NetStream.Publish.Start" #define StatusCodeDataStart "NetStream.Data.Start" #define StatusCodeUnpublishSuccess "NetStream.Unpublish.Success" // The decoded message payload. // @remark we seperate the packet from message, // for the packet focus on logic and domain data, // the message bind to the protocol and focus on protocol, such as header. // we can merge the message and packet, using OOAD hierachy, packet extends from message, // it's better for me to use components -- the message use the packet as payload. class SrsPacket { public: SrsPacket(); virtual ~SrsPacket(); public: // Covert packet to common message. virtual srs_error_t to_msg(SrsCommonMessage* msg, int stream_id); public: // The subpacket can override this encode, // For example, video and audio will directly set the payload withou memory copy, // other packet which need to serialize/encode to bytes by override the // get_size and encode_packet. virtual srs_error_t encode(int& size, char*& payload); // Decode functions for concrete packet to override. public: // The subpacket must override to decode packet from stream. // @remark never invoke the super.decode, it always failed. virtual srs_error_t decode(SrsBuffer* stream); // Encode functions for concrete packet to override. public: // The cid(chunk id) specifies the chunk to send data over. // Generally, each message perfer some cid, for example, // all protocol control messages perfer RTMP_CID_ProtocolControl, // SrsSetWindowAckSizePacket is protocol control message. virtual int get_prefer_cid(); // The subpacket must override to provide the right message type. // The message type set the RTMP message type in header. virtual int get_message_type(); protected: // The subpacket can override to calc the packet size. virtual int get_size(); // The subpacket can override to encode the payload to stream. // @remark never invoke the super.encode_packet, it always failed. virtual srs_error_t encode_packet(SrsBuffer* stream); }; // The protocol provides the rtmp-message-protocol services, // To recv RTMP message from RTMP chunk stream, // and to send out RTMP message over RTMP chunk stream. class SrsProtocol { private: class AckWindowSize { public: uint32_t window; // number of received bytes. int64_t nb_recv_bytes; // previous responsed sequence number. uint32_t sequence_number; AckWindowSize(); }; // For peer in/out private: // The underlayer socket object, send/recv bytes. ISrsProtocolReadWriter* skt; // The requests sent out, used to build the response. // key: transactionId // value: the request command name std::map requests; // For peer in private: // The chunk stream to decode RTMP messages. std::map chunk_streams; // Cache some frequently used chunk header. // cs_cache, the chunk stream cache. // @see https://github.com/ossrs/srs/issues/249 SrsChunkStream** cs_cache; // The bytes buffer cache, recv from skt, provide services for stream. SrsFastStream* in_buffer; // The input chunk size, default to 128, set by peer packet. int32_t in_chunk_size; // The input ack window, to response acknowledge to peer, // For example, to respose the encoder, for server got lots of packets. AckWindowSize in_ack_size; // The output ack window, to require peer to response the ack. AckWindowSize out_ack_size; // The buffer length set by peer. int32_t in_buffer_length; // Whether print the protocol level debug info. // Generally we print the debug info when got or send first A/V packet. bool show_debug_info; // Whether auto response when recv messages. // default to true for it's very easy to use the protocol stack. // @see: https://github.com/ossrs/srs/issues/217 bool auto_response_when_recv; // When not auto response message, manual flush the messages in queue. std::vector manual_response_queue; // For peer out private: // Cache for multiple messages send, // initialize to iovec[SRS_CONSTS_IOVS_MAX] and realloc when consumed, // it's ok to realloc the iovs cache, for all ptr is ok. iovec* out_iovs; int nb_out_iovs; // The output header cache. // used for type0, 11bytes(or 15bytes with extended timestamp) header. // or for type3, 1bytes(or 5bytes with extended timestamp) header. // The c0c3 caches must use unit SRS_CONSTS_RTMP_MAX_FMT0_HEADER_SIZE bytes. // // @remark, the c0c3 cache cannot be realloc. // To allocate it in heap to make VS2015 happy. char* out_c0c3_caches; // Whether warned user to increase the c0c3 header cache. bool warned_c0c3_cache_dry; // The output chunk size, default to 128, set by config. int32_t out_chunk_size; public: SrsProtocol(ISrsProtocolReadWriter* io); virtual ~SrsProtocol(); public: // Set the auto response message when recv for protocol stack. // @param v, whether auto response message when recv message. // @see: https://github.com/ossrs/srs/issues/217 virtual void set_auto_response(bool v); // Flush for manual response when the auto response is disabled // by set_auto_response(false), we default use auto response, so donot // need to call this api(the protocol sdk will auto send message). // @see the auto_response_when_recv and manual_response_queue. virtual srs_error_t manual_response_flush(); public: #ifdef SRS_PERF_MERGED_READ // To improve read performance, merge some packets then read, // When it on and read small bytes, we sleep to wait more data., // that is, we merge some data to read together. // @param v true to ename merged read. // @param handler the handler when merge read is enabled. // @see https://github.com/ossrs/srs/issues/241 virtual void set_merge_read(bool v, IMergeReadHandler* handler); // Create buffer with specifeid size. // @param buffer the size of buffer. // @remark when MR(SRS_PERF_MERGED_READ) disabled, always set to 8K. // @remark when buffer changed, the previous ptr maybe invalid. // @see https://github.com/ossrs/srs/issues/241 virtual void set_recv_buffer(int buffer_size); #endif public: // To set/get the recv timeout in srs_utime_t. // if timeout, recv/send message return ERROR_SOCKET_TIMEOUT. virtual void set_recv_timeout(srs_utime_t tm); virtual srs_utime_t get_recv_timeout(); // To set/get the send timeout in srs_utime_t. // if timeout, recv/send message return ERROR_SOCKET_TIMEOUT. virtual void set_send_timeout(srs_utime_t tm); virtual srs_utime_t get_send_timeout(); // Get recv/send bytes. virtual int64_t get_recv_bytes(); virtual int64_t get_send_bytes(); public: // Set the input default ack size. This is generally set by the message from peer, // but for some encoder, it never send the ack message while it default to a none zone size. // This will cause the encoder to block after publishing some messages to server, // because it wait for server to send acknowledge, but server default to 0 which means no need // To ack encoder. We can change the default input ack size. We will always response the // ack size whatever the encoder set or not. virtual srs_error_t set_in_window_ack_size(int ack_size); public: // Recv a RTMP message, which is bytes oriented. // user can use decode_message to get the decoded RTMP packet. // @param pmsg, set the received message, // always NULL if error, // NULL for unknown packet but return success. // never NULL if decode success. // @remark, drop message when msg is empty or payload length is empty. virtual srs_error_t recv_message(SrsCommonMessage** pmsg); // Decode bytes oriented RTMP message to RTMP packet, // @param ppacket, output decoded packet, // always NULL if error, never NULL if success. // @return error when unknown packet, error when decode failed. virtual srs_error_t decode_message(SrsCommonMessage* msg, SrsPacket** ppacket); // Send the RTMP message and always free it. // user must never free or use the msg after this method, // For it will always free the msg. // @param msg, the msg to send out, never be NULL. // @param stream_id, the stream id of packet to send over, 0 for control message. virtual srs_error_t send_and_free_message(SrsSharedPtrMessage* msg, int stream_id); // Send the RTMP message and always free it. // user must never free or use the msg after this method, // For it will always free the msg. // @param msgs, the msgs to send out, never be NULL. // @param nb_msgs, the size of msgs to send out. // @param stream_id, the stream id of packet to send over, 0 for control message. virtual srs_error_t send_and_free_messages(SrsSharedPtrMessage** msgs, int nb_msgs, int stream_id); // Send the RTMP packet and always free it. // user must never free or use the packet after this method, // For it will always free the packet. // @param packet, the packet to send out, never be NULL. // @param stream_id, the stream id of packet to send over, 0 for control message. virtual srs_error_t send_and_free_packet(SrsPacket* packet, int stream_id); public: // Expect a specified message, drop others util got specified one. // @pmsg, user must free it. NULL if not success. // @ppacket, user must free it, which decode from payload of message. NULL if not success. // @remark, only when success, user can use and must free the pmsg and ppacket. // For example: // SrsCommonMessage* msg = NULL; // SrsConnectAppResPacket* pkt = NULL; // if ((ret = protocol->expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { // return ret; // } // // Use then free msg and pkt // srs_freep(msg); // srs_freep(pkt); // user should never recv message and convert it, use this method instead. // if need to set timeout, use set timeout of SrsProtocol. template srs_error_t expect_message(SrsCommonMessage** pmsg, T** ppacket) { *pmsg = NULL; *ppacket = NULL; srs_error_t err = srs_success; while (true) { SrsCommonMessage* msg = NULL; if ((err = recv_message(&msg)) != srs_success) { return srs_error_wrap(err, "recv message"); } SrsPacket* packet = NULL; if ((err = decode_message(msg, &packet)) != srs_success) { srs_freep(msg); srs_freep(packet); return srs_error_wrap(err, "decode message"); } T* pkt = dynamic_cast(packet); if (!pkt) { srs_freep(msg); srs_freep(packet); continue; } *pmsg = msg; *ppacket = pkt; break; } return err; } private: // Send out the messages, donot free it, // The caller must free the param msgs. virtual srs_error_t do_send_messages(SrsSharedPtrMessage** msgs, int nb_msgs); // Send iovs. send multiple times if exceed limits. virtual srs_error_t do_iovs_send(iovec* iovs, int size); // The underlayer api for send and free packet. virtual srs_error_t do_send_and_free_packet(SrsPacket* packet, int stream_id); // The imp for decode_message virtual srs_error_t do_decode_message(SrsMessageHeader& header, SrsBuffer* stream, SrsPacket** ppacket); // Recv bytes oriented RTMP message from protocol stack. // return error if error occur and nerver set the pmsg, // return success and pmsg set to NULL if no entire message got, // return success and pmsg set to entire message if got one. virtual srs_error_t recv_interlaced_message(SrsCommonMessage** pmsg); // Read the chunk basic header(fmt, cid) from chunk stream. // user can discovery a SrsChunkStream by cid. virtual srs_error_t read_basic_header(char& fmt, int& cid); // Read the chunk message header(timestamp, payload_length, message_type, stream_id) // From chunk stream and save to SrsChunkStream. virtual srs_error_t read_message_header(SrsChunkStream* chunk, char fmt); // Read the chunk payload, remove the used bytes in buffer, // if got entire message, set the pmsg. virtual srs_error_t read_message_payload(SrsChunkStream* chunk, SrsCommonMessage** pmsg); // When recv message, update the context. virtual srs_error_t on_recv_message(SrsCommonMessage* msg); // When message sentout, update the context. virtual srs_error_t on_send_packet(SrsMessageHeader* mh, SrsPacket* packet); private: // Auto response the ack message. virtual srs_error_t response_acknowledgement_message(); // Auto response the ping message. virtual srs_error_t response_ping_message(int32_t timestamp); private: virtual void print_debug_info(); }; // incoming chunk stream maybe interlaced, // Use the chunk stream to cache the input RTMP chunk streams. class SrsChunkStream { public: // Represents the basic header fmt, // which used to identify the variant message header type. char fmt; // Represents the basic header cid, // which is the chunk stream id. int cid; // Cached message header SrsMessageHeader header; // Whether the chunk message header has extended timestamp. bool extended_timestamp; // The partially read message. SrsCommonMessage* msg; // Decoded msg count, to identify whether the chunk stream is fresh. int64_t msg_count; public: SrsChunkStream(int _cid); virtual ~SrsChunkStream(); }; // The original request from client. class SrsRequest { public: // The client ip. std::string ip; public: // The tcUrl: rtmp://request_vhost:port/app/stream // support pass vhost in query string, such as: // rtmp://ip:port/app?vhost=request_vhost/stream // rtmp://ip:port/app...vhost...request_vhost/stream std::string tcUrl; std::string pageUrl; std::string swfUrl; double objectEncoding; // The data discovery from request. public: // Discovery from tcUrl and play/publish. std::string schema; // The vhost in tcUrl. std::string vhost; // The host in tcUrl. std::string host; // The port in tcUrl. int port; // The app in tcUrl, without param. std::string app; // The param in tcUrl(app). std::string param; // The stream in play/publish std::string stream; // For play live stream, // used to specified the stop when exceed the duration. // @see https://github.com/ossrs/srs/issues/45 // in srs_utime_t. srs_utime_t duration; // The token in the connect request, // used for edge traverse to origin authentication, // @see https://github.com/ossrs/srs/issues/104 SrsAmf0Object* args; public: SrsRequest(); virtual ~SrsRequest(); public: // Deep copy the request, for source to use it to support reload, // For when initialize the source, the request is valid, // When reload it, the request maybe invalid, so need to copy it. virtual SrsRequest* copy(); // update the auth info of request, // To keep the current request ptr is ok, // For many components use the ptr of request. virtual void update_auth(SrsRequest* req); // Get the stream identify, vhost/app/stream. virtual std::string get_stream_url(); // To strip url, user must strip when update the url. virtual void strip(); public: // Transform it as HTTP request. virtual SrsRequest* as_http(); public: // The protocol of client: // rtmp, Adobe RTMP protocol. // flv, HTTP-FLV protocol. // flvs, HTTPS-FLV protocol. std::string protocol; }; // The response to client. class SrsResponse { public: // The stream id to response client createStream. int stream_id; public: SrsResponse(); virtual ~SrsResponse(); }; // The rtmp client type. enum SrsRtmpConnType { SrsRtmpConnUnknown, SrsRtmpConnPlay, SrsRtmpConnFMLEPublish, SrsRtmpConnFlashPublish, SrsRtmpConnHaivisionPublish, }; std::string srs_client_type_string(SrsRtmpConnType type); bool srs_client_type_is_publish(SrsRtmpConnType type); // store the handshake bytes, // For smart switch between complex and simple handshake. class SrsHandshakeBytes { public: // For RTMP proxy, the real IP. uint32_t proxy_real_ip; // [1+1536] char* c0c1; // [1+1536+1536] char* s0s1s2; // [1536] char* c2; public: SrsHandshakeBytes(); virtual ~SrsHandshakeBytes(); public: virtual void dispose(); public: virtual srs_error_t read_c0c1(ISrsProtocolReader* io); virtual srs_error_t read_s0s1s2(ISrsProtocolReader* io); virtual srs_error_t read_c2(ISrsProtocolReader* io); virtual srs_error_t create_c0c1(); virtual srs_error_t create_s0s1s2(const char* c1 = NULL); virtual srs_error_t create_c2(); }; // The information return from RTMP server. struct SrsServerInfo { std::string ip; std::string sig; int pid; int cid; int major; int minor; int revision; int build; SrsServerInfo(); }; // implements the client role protocol. class SrsRtmpClient { private: SrsHandshakeBytes* hs_bytes; protected: SrsProtocol* protocol; ISrsProtocolReadWriter* io; public: SrsRtmpClient(ISrsProtocolReadWriter* skt); virtual ~SrsRtmpClient(); // Protocol methods proxy public: virtual void set_recv_timeout(srs_utime_t tm); virtual void set_send_timeout(srs_utime_t tm); virtual int64_t get_recv_bytes(); virtual int64_t get_send_bytes(); virtual srs_error_t recv_message(SrsCommonMessage** pmsg); virtual srs_error_t decode_message(SrsCommonMessage* msg, SrsPacket** ppacket); virtual srs_error_t send_and_free_message(SrsSharedPtrMessage* msg, int stream_id); virtual srs_error_t send_and_free_messages(SrsSharedPtrMessage** msgs, int nb_msgs, int stream_id); virtual srs_error_t send_and_free_packet(SrsPacket* packet, int stream_id); public: // handshake with server, try complex, then simple handshake. virtual srs_error_t handshake(); // only use simple handshake virtual srs_error_t simple_handshake(); // only use complex handshake virtual srs_error_t complex_handshake(); // Connect to RTMP tcUrl and app, get the server info. // // @param app, The app to connect at, for example, live. // @param tcUrl, The tcUrl to connect at, for example, rtmp://ossrs.net/live. // @param req, the optional req object, use the swfUrl/pageUrl if specified. NULL to ignore. // @param dsu, Whether debug SRS upnode. For edge, set to true to send its info to upnode. // @param si, The server information, retrieve from response of connect app request. NULL to ignore. virtual srs_error_t connect_app(std::string app, std::string tcUrl, SrsRequest* r, bool dsu, SrsServerInfo* si); // Create a stream, then play/publish data over this stream. virtual srs_error_t create_stream(int& stream_id); // start play stream. virtual srs_error_t play(std::string stream, int stream_id, int chunk_size); // start publish stream. use flash publish workflow: // connect-app => create-stream => flash-publish virtual srs_error_t publish(std::string stream, int stream_id, int chunk_size); // start publish stream. use FMLE publish workflow: // connect-app => FMLE publish virtual srs_error_t fmle_publish(std::string stream, int& stream_id); public: // Expect a specified message, drop others util got specified one. // @pmsg, user must free it. NULL if not success. // @ppacket, user must free it, which decode from payload of message. NULL if not success. // @remark, only when success, user can use and must free the pmsg and ppacket. // For example: // SrsCommonMessage* msg = NULL; // SrsConnectAppResPacket* pkt = NULL; // if ((ret = client->expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { // return ret; // } // // Use then free msg and pkt // srs_freep(msg); // srs_freep(pkt); // user should never recv message and convert it, use this method instead. // if need to set timeout, use set timeout of SrsProtocol. template srs_error_t expect_message(SrsCommonMessage** pmsg, T** ppacket) { return protocol->expect_message(pmsg, ppacket); } }; // The rtmp provices rtmp-command-protocol services, // a high level protocol, media stream oriented services, // such as connect to vhost/app, play stream, get audio/video data. class SrsRtmpServer { private: SrsHandshakeBytes* hs_bytes; SrsProtocol* protocol; ISrsProtocolReadWriter* io; public: SrsRtmpServer(ISrsProtocolReadWriter* skt); virtual ~SrsRtmpServer(); public: // For RTMP proxy, the real IP. 0 if no proxy. // @doc https://github.com/ossrs/go-oryx/wiki/RtmpProxy virtual uint32_t proxy_real_ip(); // Protocol methods proxy public: // Set the auto response message when recv for protocol stack. // @param v, whether auto response message when recv message. // @see: https://github.com/ossrs/srs/issues/217 virtual void set_auto_response(bool v); #ifdef SRS_PERF_MERGED_READ // To improve read performance, merge some packets then read, // When it on and read small bytes, we sleep to wait more data., // that is, we merge some data to read together. // @param v true to ename merged read. // @param handler the handler when merge read is enabled. // @see https://github.com/ossrs/srs/issues/241 virtual void set_merge_read(bool v, IMergeReadHandler* handler); // Create buffer with specifeid size. // @param buffer the size of buffer. // @remark when MR(SRS_PERF_MERGED_READ) disabled, always set to 8K. // @remark when buffer changed, the previous ptr maybe invalid. // @see https://github.com/ossrs/srs/issues/241 virtual void set_recv_buffer(int buffer_size); #endif // To set/get the recv timeout in srs_utime_t. // if timeout, recv/send message return ERROR_SOCKET_TIMEOUT. virtual void set_recv_timeout(srs_utime_t tm); virtual srs_utime_t get_recv_timeout(); // To set/get the send timeout in srs_utime_t. // if timeout, recv/send message return ERROR_SOCKET_TIMEOUT. virtual void set_send_timeout(srs_utime_t tm); virtual srs_utime_t get_send_timeout(); // Get recv/send bytes. virtual int64_t get_recv_bytes(); virtual int64_t get_send_bytes(); // Recv a RTMP message, which is bytes oriented. // user can use decode_message to get the decoded RTMP packet. // @param pmsg, set the received message, // always NULL if error, // NULL for unknown packet but return success. // never NULL if decode success. // @remark, drop message when msg is empty or payload length is empty. virtual srs_error_t recv_message(SrsCommonMessage** pmsg); // Decode bytes oriented RTMP message to RTMP packet, // @param ppacket, output decoded packet, // always NULL if error, never NULL if success. // @return error when unknown packet, error when decode failed. virtual srs_error_t decode_message(SrsCommonMessage* msg, SrsPacket** ppacket); // Send the RTMP message and always free it. // user must never free or use the msg after this method, // For it will always free the msg. // @param msg, the msg to send out, never be NULL. // @param stream_id, the stream id of packet to send over, 0 for control message. virtual srs_error_t send_and_free_message(SrsSharedPtrMessage* msg, int stream_id); // Send the RTMP message and always free it. // user must never free or use the msg after this method, // For it will always free the msg. // @param msgs, the msgs to send out, never be NULL. // @param nb_msgs, the size of msgs to send out. // @param stream_id, the stream id of packet to send over, 0 for control message. // // @remark performance issue, to support 6k+ 250kbps client, // @see https://github.com/ossrs/srs/issues/194 virtual srs_error_t send_and_free_messages(SrsSharedPtrMessage** msgs, int nb_msgs, int stream_id); // Send the RTMP packet and always free it. // user must never free or use the packet after this method, // For it will always free the packet. // @param packet, the packet to send out, never be NULL. // @param stream_id, the stream id of packet to send over, 0 for control message. virtual srs_error_t send_and_free_packet(SrsPacket* packet, int stream_id); public: // Do handshake with client, try complex then simple. virtual srs_error_t handshake(); // Do connect app with client, to discovery tcUrl. virtual srs_error_t connect_app(SrsRequest* req); // Set output ack size to client, client will send ack-size for each ack window virtual srs_error_t set_window_ack_size(int ack_size); // Set the default input ack size value. virtual srs_error_t set_in_window_ack_size(int ack_size); // @type: The sender can mark this message hard (0), soft (1), or dynamic (2) // using the Limit type field. virtual srs_error_t set_peer_bandwidth(int bandwidth, int type); // @param server_ip the ip of server. virtual srs_error_t response_connect_app(SrsRequest* req, const char* server_ip = NULL); // Redirect the connection to another rtmp server. // @param a RTMP url to redirect to. // @param whether the client accept the redirect. virtual srs_error_t redirect(SrsRequest* r, std::string url, bool& accepted); // Reject the connect app request. virtual void response_connect_reject(SrsRequest* req, const char* desc); // Response client the onBWDone message. virtual srs_error_t on_bw_done(); // Recv some message to identify the client. // @stream_id, client will createStream to play or publish by flash, // the stream_id used to response the createStream request. // @type, output the client type. // @stream_name, output the client publish/play stream name. @see: SrsRequest.stream // @duration, output the play client duration. @see: SrsRequest.duration virtual srs_error_t identify_client(int stream_id, SrsRtmpConnType& type, std::string& stream_name, srs_utime_t& duration); // Set the chunk size when client type identified. virtual srs_error_t set_chunk_size(int chunk_size); // When client type is play, response with packets: // StreamBegin, // onStatus(NetStream.Play.Reset), onStatus(NetStream.Play.Start)., // |RtmpSampleAccess(false, false), // onStatus(NetStream.Data.Start). virtual srs_error_t start_play(int stream_id); // When client(type is play) send pause message, // if is_pause, response the following packets: // onStatus(NetStream.Pause.Notify) // StreamEOF // if not is_pause, response the following packets: // onStatus(NetStream.Unpause.Notify) // StreamBegin virtual srs_error_t on_play_client_pause(int stream_id, bool is_pause); // When client type is publish, response with packets: // releaseStream response // FCPublish // FCPublish response // createStream response // onFCPublish(NetStream.Publish.Start) // onStatus(NetStream.Publish.Start) virtual srs_error_t start_fmle_publish(int stream_id); // For encoder of Haivision, response the startup request. // @see https://github.com/ossrs/srs/issues/844 virtual srs_error_t start_haivision_publish(int stream_id); // process the FMLE unpublish event. // @unpublish_tid the unpublish request transaction id. virtual srs_error_t fmle_unpublish(int stream_id, double unpublish_tid); // When client type is publish, response with packets: // onStatus(NetStream.Publish.Start) virtual srs_error_t start_flash_publish(int stream_id); public: // Expect a specified message, drop others util got specified one. // @pmsg, user must free it. NULL if not success. // @ppacket, user must free it, which decode from payload of message. NULL if not success. // @remark, only when success, user can use and must free the pmsg and ppacket. // For example: // SrsCommonMessage* msg = NULL; // SrsConnectAppResPacket* pkt = NULL; // if ((ret = server->expect_message(&msg, &pkt)) != ERROR_SUCCESS) { // return ret; // } // // Use then free msg and pkt // srs_freep(msg); // srs_freep(pkt); // user should never recv message and convert it, use this method instead. // if need to set timeout, use set timeout of SrsProtocol. template srs_error_t expect_message(SrsCommonMessage** pmsg, T** ppacket) { return protocol->expect_message(pmsg, ppacket); } private: virtual srs_error_t identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, int depth, SrsRtmpConnType& type, std::string& stream_name, srs_utime_t& duration); virtual srs_error_t identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsRtmpConnType& type, std::string& stream_name); virtual srs_error_t identify_haivision_publish_client(SrsFMLEStartPacket* req, SrsRtmpConnType& type, std::string& stream_name); virtual srs_error_t identify_flash_publish_client(SrsPublishPacket* req, SrsRtmpConnType& type, std::string& stream_name); private: virtual srs_error_t identify_play_client(SrsPlayPacket* req, SrsRtmpConnType& type, std::string& stream_name, srs_utime_t& duration); }; // 4.1.1. connect // The client sends the connect command to the server to request // connection to a server application instance. class SrsConnectAppPacket : public SrsPacket { public: // Name of the command. Set to "connect". std::string command_name; // Always set to 1. double transaction_id; // Command information object which has the name-value pairs. // @remark: alloc in packet constructor, user can directly use it, // user should never alloc it again which will cause memory leak. // @remark, never be NULL. SrsAmf0Object* command_object; // Any optional information // @remark, optional, init to and maybe NULL. SrsAmf0Object* args; public: SrsConnectAppPacket(); virtual ~SrsConnectAppPacket(); // Decode functions for concrete packet to override. public: virtual srs_error_t decode(SrsBuffer* stream); // Encode functions for concrete packet to override. public: virtual int get_prefer_cid(); virtual int get_message_type(); protected: virtual int get_size(); virtual srs_error_t encode_packet(SrsBuffer* stream); }; // Response for SrsConnectAppPacket. class SrsConnectAppResPacket : public SrsPacket { public: // The _result or _error; indicates whether the response is result or error. std::string command_name; // Transaction ID is 1 for call connect responses double transaction_id; // Name-value pairs that describe the properties(fmsver etc.) of the connection. // @remark, never be NULL. SrsAmf0Object* props; // Name-value pairs that describe the response from|the server. 'code', // 'level', 'description' are names of few among such information. // @remark, never be NULL. SrsAmf0Object* info; public: SrsConnectAppResPacket(); virtual ~SrsConnectAppResPacket(); // Decode functions for concrete packet to override. public: virtual srs_error_t decode(SrsBuffer* stream); // Encode functions for concrete packet to override. public: virtual int get_prefer_cid(); virtual int get_message_type(); protected: virtual int get_size(); virtual srs_error_t encode_packet(SrsBuffer* stream); }; // 4.1.2. Call // The call method of the NetConnection object runs remote procedure // calls (RPC) at the receiving end. The called RPC name is passed as a // parameter to the call command. class SrsCallPacket : public SrsPacket { public: // Name of the remote procedure that is called. std::string command_name; // If a response is expected we give a transaction Id. Else we pass a value of 0 double transaction_id; // If there exists any command info this // is set, else this is set to null type. // @remark, optional, init to and maybe NULL. SrsAmf0Any* command_object; // Any optional arguments to be provided // @remark, optional, init to and maybe NULL. SrsAmf0Any* arguments; public: SrsCallPacket(); virtual ~SrsCallPacket(); // Decode functions for concrete packet to override. public: virtual srs_error_t decode(SrsBuffer* stream); // Encode functions for concrete packet to override. public: virtual int get_prefer_cid(); virtual int get_message_type(); protected: virtual int get_size(); virtual srs_error_t encode_packet(SrsBuffer* stream); }; // Response for SrsCallPacket. class SrsCallResPacket : public SrsPacket { public: // Name of the command. std::string command_name; // ID of the command, to which the response belongs to double transaction_id; // If there exists any command info this is set, else this is set to null type. // @remark, optional, init to and maybe NULL. SrsAmf0Any* command_object; // Response from the method that was called. // @remark, optional, init to and maybe NULL. SrsAmf0Any* response; public: SrsCallResPacket(double _transaction_id); virtual ~SrsCallResPacket(); // Encode functions for concrete packet to override. public: virtual int get_prefer_cid(); virtual int get_message_type(); protected: virtual int get_size(); virtual srs_error_t encode_packet(SrsBuffer* stream); }; // 4.1.3. createStream // The client sends this command to the server to create a logical // channel for message communication The publishing of audio, video, and // metadata is carried out over stream channel created using the // createStream command. class SrsCreateStreamPacket : public SrsPacket { public: // Name of the command. Set to "createStream". std::string command_name; // Transaction ID of the command. double transaction_id; // If there exists any command info this is set, else this is set to null type. // @remark, never be NULL, an AMF0 null instance. SrsAmf0Any* command_object; // null public: SrsCreateStreamPacket(); virtual ~SrsCreateStreamPacket(); // Decode functions for concrete packet to override. public: virtual srs_error_t decode(SrsBuffer* stream); // Encode functions for concrete packet to override. public: virtual int get_prefer_cid(); virtual int get_message_type(); protected: virtual int get_size(); virtual srs_error_t encode_packet(SrsBuffer* stream); }; // Response for SrsCreateStreamPacket. class SrsCreateStreamResPacket : public SrsPacket { public: // The _result or _error; indicates whether the response is result or error. std::string command_name; // ID of the command that response belongs to. double transaction_id; // If there exists any command info this is set, else this is set to null type. // @remark, never be NULL, an AMF0 null instance. SrsAmf0Any* command_object; // null // The return value is either a stream ID or an error information object. double stream_id; public: SrsCreateStreamResPacket(double _transaction_id, double _stream_id); virtual ~SrsCreateStreamResPacket(); // Decode functions for concrete packet to override. public: virtual srs_error_t decode(SrsBuffer* stream); // Encode functions for concrete packet to override. public: virtual int get_prefer_cid(); virtual int get_message_type(); protected: virtual int get_size(); virtual srs_error_t encode_packet(SrsBuffer* stream); }; // client close stream packet. class SrsCloseStreamPacket : public SrsPacket { public: // Name of the command, set to "closeStream". std::string command_name; // Transaction ID set to 0. double transaction_id; // Command information object does not exist. Set to null type. // @remark, never be NULL, an AMF0 null instance. SrsAmf0Any* command_object; // null public: SrsCloseStreamPacket(); virtual ~SrsCloseStreamPacket(); // Decode functions for concrete packet to override. public: virtual srs_error_t decode(SrsBuffer* stream); }; // FMLE start publish: ReleaseStream/PublishStream/FCPublish/FCUnpublish class SrsFMLEStartPacket : public SrsPacket { public: // Name of the command std::string command_name; // The transaction ID to get the response. double transaction_id; // If there exists any command info this is set, else this is set to null type. // @remark, never be NULL, an AMF0 null instance. SrsAmf0Any* command_object; // null // The stream name to start publish or release. std::string stream_name; public: SrsFMLEStartPacket(); virtual ~SrsFMLEStartPacket(); // Decode functions for concrete packet to override. public: virtual srs_error_t decode(SrsBuffer* stream); // Encode functions for concrete packet to override. public: virtual int get_prefer_cid(); virtual int get_message_type(); protected: virtual int get_size(); virtual srs_error_t encode_packet(SrsBuffer* stream); // Factory method to create specified FMLE packet. public: static SrsFMLEStartPacket* create_release_stream(std::string stream); static SrsFMLEStartPacket* create_FC_publish(std::string stream); }; // Response for SrsFMLEStartPacket. class SrsFMLEStartResPacket : public SrsPacket { public: // Name of the command std::string command_name; // The transaction ID to get the response. double transaction_id; // If there exists any command info this is set, else this is set to null type. // @remark, never be NULL, an AMF0 null instance. SrsAmf0Any* command_object; // null // The optional args, set to undefined. // @remark, never be NULL, an AMF0 undefined instance. SrsAmf0Any* args; // undefined public: SrsFMLEStartResPacket(double _transaction_id); virtual ~SrsFMLEStartResPacket(); // Decode functions for concrete packet to override. public: virtual srs_error_t decode(SrsBuffer* stream); // Encode functions for concrete packet to override. public: virtual int get_prefer_cid(); virtual int get_message_type(); protected: virtual int get_size(); virtual srs_error_t encode_packet(SrsBuffer* stream); }; // FMLE/flash publish // 4.2.6. Publish // The client sends the publish command to publish a named stream to the // server. Using this name, any client can play this stream and receive // The published audio, video, and data messages. class SrsPublishPacket : public SrsPacket { public: // Name of the command, set to "publish". std::string command_name; // Transaction ID set to 0. double transaction_id; // Command information object does not exist. Set to null type. // @remark, never be NULL, an AMF0 null instance. SrsAmf0Any* command_object; // null // Name with which the stream is published. std::string stream_name; // Type of publishing. Set to "live", "record", or "append". // record: The stream is published and the data is recorded to a new file.The file // is stored on the server in a subdirectory within the directory that // contains the server application. If the file already exists, it is // overwritten. // append: The stream is published and the data is appended to a file. If no file // is found, it is created. // live: Live data is published without recording it in a file. // @remark, SRS only support live. // @remark, optional, default to live. std::string type; public: SrsPublishPacket(); virtual ~SrsPublishPacket(); // Decode functions for concrete packet to override. public: virtual srs_error_t decode(SrsBuffer* stream); // Encode functions for concrete packet to override. public: virtual int get_prefer_cid(); virtual int get_message_type(); protected: virtual int get_size(); virtual srs_error_t encode_packet(SrsBuffer* stream); }; // 4.2.8. pause // The client sends the pause command to tell the server to pause or // start playing. class SrsPausePacket : public SrsPacket { public: // Name of the command, set to "pause". std::string command_name; // There is no transaction ID for this command. Set to 0. double transaction_id; // Command information object does not exist. Set to null type. // @remark, never be NULL, an AMF0 null instance. SrsAmf0Any* command_object; // null // true or false, to indicate pausing or resuming play bool is_pause; // Number of milliseconds at which the the stream is paused or play resumed. // This is the current stream time at the Client when stream was paused. When the // playback is resumed, the server will only send messages with timestamps // greater than this value. double time_ms; public: SrsPausePacket(); virtual ~SrsPausePacket(); // Decode functions for concrete packet to override. public: virtual srs_error_t decode(SrsBuffer* stream); }; // 4.2.1. play // The client sends this command to the server to play a stream. class SrsPlayPacket : public SrsPacket { public: // Name of the command. Set to "play". std::string command_name; // Transaction ID set to 0. double transaction_id; // Command information does not exist. Set to null type. // @remark, never be NULL, an AMF0 null instance. SrsAmf0Any* command_object; // null // Name of the stream to play. // To play video (FLV) files, specify the name of the stream without a file // extension (for example, "sample"). // To play back MP3 or ID3 tags, you must precede the stream name with mp3: // (for example, "mp3:sample".) // To play H.264/AAC files, you must precede the stream name with mp4: and specify the // file extension. For example, to play the file sample.m4v, specify // "mp4:sample.m4v" std::string stream_name; // An optional parameter that specifies the start time in seconds. // The default value is -2, which means the subscriber first tries to play the live // stream specified in the Stream Name field. If a live stream of that name is // not found, it plays the recorded stream specified in the Stream Name field. // If you pass -1 in the Start field, only the live stream specified in the Stream // Name field is played. // If you pass 0 or a positive number in the Start field, a recorded stream specified // in the Stream Name field is played beginning from the time specified in the // Start field. // If no recorded stream is found, the next item in the playlist is played. double start; // An optional parameter that specifies the duration of playback in seconds. // The default value is -1. The -1 value means a live stream is played until it is no // longer available or a recorded stream is played until it ends. // If u pass 0, it plays the single frame since the time specified in the Start field // from the beginning of a recorded stream. It is assumed that the value specified // in the Start field is equal to or greater than 0. // If you pass a positive number, it plays a live stream for the time period specified // in the Duration field. After that it becomes available or plays a recorded // stream for the time specified in the Duration field. (If a stream ends before the // time specified in the Duration field, playback ends when the stream ends.) // If you pass a negative number other than -1 in the Duration field, it interprets the // value as if it were -1. double duration; // An optional Boolean value or number that specifies whether to flush any // previous playlist. bool reset; public: SrsPlayPacket(); virtual ~SrsPlayPacket(); // Decode functions for concrete packet to override. public: virtual srs_error_t decode(SrsBuffer* stream); // Encode functions for concrete packet to override. public: virtual int get_prefer_cid(); virtual int get_message_type(); protected: virtual int get_size(); virtual srs_error_t encode_packet(SrsBuffer* stream); }; // Response for SrsPlayPacket. // @remark, user must set the stream_id in header. class SrsPlayResPacket : public SrsPacket { public: // Name of the command. If the play command is successful, the command // name is set to onStatus. std::string command_name; // Transaction ID set to 0. double transaction_id; // Command information does not exist. Set to null type. // @remark, never be NULL, an AMF0 null instance. SrsAmf0Any* command_object; // null // If the play command is successful, the client receives OnStatus message from // server which is NetStream.Play.Start. If the specified stream is not found, // NetStream.Play.StreamNotFound is received. // @remark, never be NULL, an AMF0 object instance. SrsAmf0Object* desc; public: SrsPlayResPacket(); virtual ~SrsPlayResPacket(); // Encode functions for concrete packet to override. public: virtual int get_prefer_cid(); virtual int get_message_type(); protected: virtual int get_size(); virtual srs_error_t encode_packet(SrsBuffer* stream); }; // When bandwidth test done, notice client. class SrsOnBWDonePacket : public SrsPacket { public: // Name of command. Set to "onBWDone" std::string command_name; // Transaction ID set to 0. double transaction_id; // Command information does not exist. Set to null type. // @remark, never be NULL, an AMF0 null instance. SrsAmf0Any* args; // null public: SrsOnBWDonePacket(); virtual ~SrsOnBWDonePacket(); // Encode functions for concrete packet to override. public: virtual int get_prefer_cid(); virtual int get_message_type(); protected: virtual int get_size(); virtual srs_error_t encode_packet(SrsBuffer* stream); }; // onStatus command, AMF0 Call // @remark, user must set the stream_id by SrsCommonMessage.set_packet(). class SrsOnStatusCallPacket : public SrsPacket { public: // Name of command. Set to "onStatus" std::string command_name; // Transaction ID set to 0. double transaction_id; // Command information does not exist. Set to null type. // @remark, never be NULL, an AMF0 null instance. SrsAmf0Any* args; // null // Name-value pairs that describe the response from the server. // 'code','level', 'description' are names of few among such information. // @remark, never be NULL, an AMF0 object instance. SrsAmf0Object* data; public: SrsOnStatusCallPacket(); virtual ~SrsOnStatusCallPacket(); // Encode functions for concrete packet to override. public: virtual int get_prefer_cid(); virtual int get_message_type(); protected: virtual int get_size(); virtual srs_error_t encode_packet(SrsBuffer* stream); }; // The special packet for the bandwidth test. // actually, it's a SrsOnStatusCallPacket, but // 1. encode with data field, to send data to client. // 2. decode ignore the data field, donot care. class SrsBandwidthPacket : public SrsPacket { public: // Name of command. std::string command_name; // Transaction ID set to 0. double transaction_id; // Command information does not exist. Set to null type. // @remark, never be NULL, an AMF0 null instance. SrsAmf0Any* args; // null // Name-value pairs that describe the response from the server. // 'code','level', 'description' are names of few among such information. // @remark, never be NULL, an AMF0 object instance. SrsAmf0Object* data; public: SrsBandwidthPacket(); virtual ~SrsBandwidthPacket(); // Decode functions for concrete packet to override. public: virtual srs_error_t decode(SrsBuffer* stream); // Encode functions for concrete packet to override. public: virtual int get_prefer_cid(); virtual int get_message_type(); protected: virtual int get_size(); virtual srs_error_t encode_packet(SrsBuffer* stream); // help function for bandwidth packet. public: virtual bool is_start_play(); virtual bool is_starting_play(); virtual bool is_stop_play(); virtual bool is_stopped_play(); virtual bool is_start_publish(); virtual bool is_starting_publish(); virtual bool is_stop_publish(); virtual bool is_stopped_publish(); virtual bool is_finish(); virtual bool is_final(); static SrsBandwidthPacket* create_start_play(); static SrsBandwidthPacket* create_starting_play(); static SrsBandwidthPacket* create_playing(); static SrsBandwidthPacket* create_stop_play(); static SrsBandwidthPacket* create_stopped_play(); static SrsBandwidthPacket* create_start_publish(); static SrsBandwidthPacket* create_starting_publish(); static SrsBandwidthPacket* create_publishing(); static SrsBandwidthPacket* create_stop_publish(); static SrsBandwidthPacket* create_stopped_publish(); static SrsBandwidthPacket* create_finish(); static SrsBandwidthPacket* create_final(); private: virtual SrsBandwidthPacket* set_command(std::string command); }; // onStatus data, AMF0 Data // @remark, user must set the stream_id by SrsCommonMessage.set_packet(). class SrsOnStatusDataPacket : public SrsPacket { public: // Name of command. Set to "onStatus" std::string command_name; // Name-value pairs that describe the response from the server. // 'code', are names of few among such information. // @remark, never be NULL, an AMF0 object instance. SrsAmf0Object* data; public: SrsOnStatusDataPacket(); virtual ~SrsOnStatusDataPacket(); // Encode functions for concrete packet to override. public: virtual int get_prefer_cid(); virtual int get_message_type(); protected: virtual int get_size(); virtual srs_error_t encode_packet(SrsBuffer* stream); }; // AMF0Data RtmpSampleAccess // @remark, user must set the stream_id by SrsCommonMessage.set_packet(). class SrsSampleAccessPacket : public SrsPacket { public: // Name of command. Set to "|RtmpSampleAccess". std::string command_name; // Whether allow access the sample of video. // @see: https://github.com/ossrs/srs/issues/49 // @see: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/NetStream.html#videoSampleAccess bool video_sample_access; // Whether allow access the sample of audio. // @see: https://github.com/ossrs/srs/issues/49 // @see: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/NetStream.html#audioSampleAccess bool audio_sample_access; public: SrsSampleAccessPacket(); virtual ~SrsSampleAccessPacket(); // Encode functions for concrete packet to override. public: virtual int get_prefer_cid(); virtual int get_message_type(); protected: virtual int get_size(); virtual srs_error_t encode_packet(SrsBuffer* stream); }; // The stream metadata. // FMLE: @setDataFrame // others: onMetaData class SrsOnMetaDataPacket : public SrsPacket { public: // Name of metadata. Set to "onMetaData" std::string name; // Metadata of stream. // @remark, never be NULL, an AMF0 object instance. SrsAmf0Object* metadata; public: SrsOnMetaDataPacket(); virtual ~SrsOnMetaDataPacket(); // Decode functions for concrete packet to override. public: virtual srs_error_t decode(SrsBuffer* stream); // Encode functions for concrete packet to override. public: virtual int get_prefer_cid(); virtual int get_message_type(); protected: virtual int get_size(); virtual srs_error_t encode_packet(SrsBuffer* stream); }; // 5.5. Window Acknowledgement Size (5) // The client or the server sends this message to inform the peer which // window size to use when sending acknowledgment. class SrsSetWindowAckSizePacket : public SrsPacket { public: int32_t ackowledgement_window_size; public: SrsSetWindowAckSizePacket(); virtual ~SrsSetWindowAckSizePacket(); // Decode functions for concrete packet to override. public: virtual srs_error_t decode(SrsBuffer* stream); // Encode functions for concrete packet to override. public: virtual int get_prefer_cid(); virtual int get_message_type(); protected: virtual int get_size(); virtual srs_error_t encode_packet(SrsBuffer* stream); }; // 5.3. Acknowledgement (3) // The client or the server sends the acknowledgment to the peer after // receiving bytes equal to the window size. class SrsAcknowledgementPacket : public SrsPacket { public: uint32_t sequence_number; public: SrsAcknowledgementPacket(); virtual ~SrsAcknowledgementPacket(); // Decode functions for concrete packet to override. public: virtual srs_error_t decode(SrsBuffer* stream); // Encode functions for concrete packet to override. public: virtual int get_prefer_cid(); virtual int get_message_type(); protected: virtual int get_size(); virtual srs_error_t encode_packet(SrsBuffer* stream); }; // 7.1. Set Chunk Size // Protocol control message 1, Set Chunk Size, is used to notify the // peer about the new maximum chunk size. class SrsSetChunkSizePacket : public SrsPacket { public: // The maximum chunk size can be 65536 bytes. The chunk size is // maintained independently for each direction. int32_t chunk_size; public: SrsSetChunkSizePacket(); virtual ~SrsSetChunkSizePacket(); // Decode functions for concrete packet to override. public: virtual srs_error_t decode(SrsBuffer* stream); // Encode functions for concrete packet to override. public: virtual int get_prefer_cid(); virtual int get_message_type(); protected: virtual int get_size(); virtual srs_error_t encode_packet(SrsBuffer* stream); }; // 5.6. Set Peer Bandwidth (6) enum SrsPeerBandwidthType { // The sender can mark this message hard (0), soft (1), or dynamic (2) // using the Limit type field. SrsPeerBandwidthHard = 0, SrsPeerBandwidthSoft = 1, SrsPeerBandwidthDynamic = 2, }; // 5.6. Set Peer Bandwidth (6) // The client or the server sends this message to update the output // bandwidth of the peer. class SrsSetPeerBandwidthPacket : public SrsPacket { public: int32_t bandwidth; // @see: SrsPeerBandwidthType int8_t type; public: SrsSetPeerBandwidthPacket(); virtual ~SrsSetPeerBandwidthPacket(); // Encode functions for concrete packet to override. public: virtual int get_prefer_cid(); virtual int get_message_type(); protected: virtual int get_size(); virtual srs_error_t encode_packet(SrsBuffer* stream); }; // 3.7. User Control message enum SrcPCUCEventType { // Generally, 4bytes event-data // The server sends this event to notify the client // that a stream has become functional and can be // used for communication. By default, this event // is sent on ID 0 after the application connect // command is successfully received from the // client. The event data is 4-byte and represents // The stream ID of the stream that became // Functional. SrcPCUCStreamBegin = 0x00, // The server sends this event to notify the client // that the playback of data is over as requested // on this stream. No more data is sent without // issuing additional commands. The client discards // The messages received for the stream. The // 4 bytes of event data represent the ID of the // stream on which playback has ended. SrcPCUCStreamEOF = 0x01, // The server sends this event to notify the client // that there is no more data on the stream. If the // server does not detect any message for a time // period, it can notify the subscribed clients // that the stream is dry. The 4 bytes of event // data represent the stream ID of the dry stream. SrcPCUCStreamDry = 0x02, // The client sends this event to inform the server // of the buffer size (in milliseconds) that is // used to buffer any data coming over a stream. // This event is sent before the server starts // processing the stream. The first 4 bytes of the // event data represent the stream ID and the next // 4 bytes represent the buffer length, in // milliseconds. SrcPCUCSetBufferLength = 0x03, // 8bytes event-data // The server sends this event to notify the client // that the stream is a recorded stream. The // 4 bytes event data represent the stream ID of // The recorded stream. SrcPCUCStreamIsRecorded = 0x04, // The server sends this event to test whether the // client is reachable. Event data is a 4-byte // timestamp, representing the local server time // When the server dispatched the command. The // client responds with kMsgPingResponse on // receiving kMsgPingRequest. SrcPCUCPingRequest = 0x06, // The client sends this event to the server in // Response to the ping request. The event data is // a 4-byte timestamp, which was received with the // kMsgPingRequest request. SrcPCUCPingResponse = 0x07, // For PCUC size=3, for example the payload is "00 1A 01", // it's a FMS control event, where the event type is 0x001a and event data is 0x01, // please notice that the event data is only 1 byte for this event. SrsPCUCFmsEvent0 = 0x1a, }; // 5.4. User Control Message (4) // // For the EventData is 4bytes. // Stream Begin(=0) 4-bytes stream ID // Stream EOF(=1) 4-bytes stream ID // StreamDry(=2) 4-bytes stream ID // SetBufferLength(=3) 8-bytes 4bytes stream ID, 4bytes buffer length. // StreamIsRecorded(=4) 4-bytes stream ID // PingRequest(=6) 4-bytes timestamp local server time // PingResponse(=7) 4-bytes timestamp received ping request. // // 3.7. User Control message // +------------------------------+------------------------- // | Event Type ( 2- bytes ) | Event Data // +------------------------------+------------------------- // Figure 5 Pay load for the 'User Control Message'. class SrsUserControlPacket : public SrsPacket { public: // Event type is followed by Event data. // @see: SrcPCUCEventType int16_t event_type; // The event data generally in 4bytes. // @remark for event type is 0x001a, only 1bytes. // @see SrsPCUCFmsEvent0 int32_t event_data; // 4bytes if event_type is SetBufferLength; otherwise 0. int32_t extra_data; public: SrsUserControlPacket(); virtual ~SrsUserControlPacket(); // Decode functions for concrete packet to override. public: virtual srs_error_t decode(SrsBuffer* stream); // Encode functions for concrete packet to override. public: virtual int get_prefer_cid(); virtual int get_message_type(); protected: virtual int get_size(); virtual srs_error_t encode_packet(SrsBuffer* stream); }; #endif