RtspSession.h 8.55 KB
Newer Older
xiongziliang committed
1
/*
xiongziliang committed
2
 * MIT License
xzl committed
3
 *
xiongziliang committed
4
 * Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
xiongziliang committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 *
 * This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
 *
 * 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.
xzl committed
25 26 27 28 29 30
 */

#ifndef SESSION_RTSPSESSION_H_
#define SESSION_RTSPSESSION_H_

#include <set>
xiongzilaing committed
31
#include <vector>
32
#include <unordered_set>
xzl committed
33
#include <unordered_map>
xiongziliang committed
34 35
#include "Util/util.h"
#include "Util/logger.h"
xiongziliang committed
36
#include "Common/config.h"
xiongziliang committed
37 38
#include "Network/TcpSession.h"
#include "Player/PlayerBase.h"
xiongziliang committed
39
#include "RtpMultiCaster.h"
xzl committed
40
#include "RtspMediaSource.h"
xiongziliang committed
41
#include "RtspSplitter.h"
xiongziliang committed
42 43
#include "RtpReceiver.h"
#include "RtspToRtmpMediaSource.h"
xzl committed
44 45

using namespace std;
xiongziliang committed
46
using namespace toolkit;
47

xiongziliang committed
48
namespace mediakit {
xzl committed
49 50

class RtspSession;
51

52
class BufferRtp : public Buffer{
53 54 55 56 57
public:
    typedef std::shared_ptr<BufferRtp> Ptr;
    BufferRtp(const RtpPacket::Ptr & pkt,uint32_t offset = 0 ):_rtp(pkt),_offset(offset){}
    virtual ~BufferRtp(){}

58
    char *data() const override {
xiongziliang committed
59
        return (char *)_rtp->data() + _offset;
60 61
    }
    uint32_t size() const override {
xiongziliang committed
62
        return _rtp->size() - _offset;
63 64 65 66 67 68
    }
private:
    RtpPacket::Ptr _rtp;
    uint32_t _offset;
};

xiongziliang committed
69
class RtspSession: public TcpSession, public RtspSplitter, public RtpReceiver , public MediaSourceEvent{
xzl committed
70 71
public:
	typedef std::shared_ptr<RtspSession> Ptr;
72 73 74 75 76
	typedef std::function<void(const string &realm)> onGetRealm;
    //encrypted为true是则表明是md5加密的密码,否则是明文密码
    //在请求明文密码时如果提供md5密码者则会导致认证失败
	typedef std::function<void(bool encrypted,const string &pwd_or_md5)> onAuth;

xiongziliang committed
77
	RtspSession(const Socket::Ptr &pSock);
xzl committed
78
	virtual ~RtspSession();
xiongziliang committed
79
	////TcpSession override////
80
	void onRecv(const Buffer::Ptr &pBuf) override;
xzl committed
81 82
	void onError(const SockException &err) override;
	void onManager() override;
xiongziliang committed
83
protected:
xiongziliang committed
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
	//RtspSplitter override
    /**
     * 收到完整的rtsp包回调,包括sdp等content数据
     * @param parser rtsp包
     */
    void onWholeRtspPacket(Parser &parser) override;

    /**
     * 收到rtp包回调
     * @param data
     * @param len
     */
    void onRtpPacket(const char *data,uint64_t len) override;

    /**
     * 从rtsp头中获取Content长度
     * @param parser
     * @return
     */
    int64_t getContentLength(Parser &parser) override;

xiongziliang committed
105 106
	//RtpReceiver override
	void onRtpSorted(const RtpPacket::Ptr &rtppt, int trackidx) override;
107
	//MediaSourceEvent override
xiongziliang committed
108
	bool close(MediaSource &sender,bool force) override ;
109
    void onNoneReader(MediaSource &sender) override;
110

111
    //TcpSession override
112
    int send(const Buffer::Ptr &pkt) override;
113 114 115 116 117 118 119 120

    /**
     * 收到RTCP包回调
     * @param iTrackidx
     * @param track
     * @param pucData
     * @param uiLen
     */
121
    virtual void onRtcpPacket(int iTrackidx, SdpTrack::Ptr &track, unsigned char *pucData, unsigned int uiLen);
xzl committed
122
private:
xiongziliang committed
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
	//处理options方法,获取服务器能力
    void handleReq_Options(const Parser &parser);
	//处理describe方法,请求服务器rtsp sdp信息
    void handleReq_Describe(const Parser &parser);
	//处理ANNOUNCE方法,请求推流,附带sdp
    void handleReq_ANNOUNCE(const Parser &parser);
	//处理record方法,开始推流
    void handleReq_RECORD(const Parser &parser);
	//处理setup方法,播放和推流协商rtp传输方式用
    void handleReq_Setup(const Parser &parser);
	//处理play方法,开始或恢复播放
    void handleReq_Play(const Parser &parser);
	//处理pause方法,暂停播放
    void handleReq_Pause(const Parser &parser);
	//处理teardown方法,结束播放
    void handleReq_Teardown(const Parser &parser);
	//处理Get方法,rtp over http才用到
    void handleReq_Get(const Parser &parser);
	//处理Post方法,rtp over http才用到
    void handleReq_Post(const Parser &parser);
	//处理SET_PARAMETER、GET_PARAMETER方法,一般用于心跳
    void handleReq_SET_PARAMETER(const Parser &parser);

	//rtsp资源未找到
	void inline send_StreamNotFound();
	//不支持的传输模式
	void inline send_UnsupportedTransport();
	//会话id错误
	void inline send_SessionNotFound();
	//一般rtsp服务器打开端口失败时触发
	void inline send_NotAcceptable();
	//ssrc转字符串
155
	inline string printSSRC(uint32_t ui32Ssrc);
xiongziliang committed
156 157

	//获取track下标
158 159
	inline int getTrackIndexByTrackType(TrackType type);
    inline int getTrackIndexByControlSuffix(const string &controlSuffix);
xiongziliang committed
160
	inline int getTrackIndexByInterleaved(int interleaved);
161

xiongziliang committed
162
	//一般用于接收udp打洞包,也用于rtsp推流
163
	inline void onRcvPeerUdpData(int intervaled, const Buffer::Ptr &pBuf, const struct sockaddr &addr);
xiongziliang committed
164
	//配合onRcvPeerUdpData使用
165
	inline void startListenPeerUdpData(int iTrackIdx);
xzl committed
166

xiongziliang committed
167 168
    ////rtsp专有认证相关////
	//认证成功
169
    void onAuthSuccess();
xiongziliang committed
170
	//认证失败
171
    void onAuthFailed(const string &realm,const string &why,bool close = true);
xiongziliang committed
172
	//开始走rtsp专有认证流程
173
    void onAuthUser(const string &realm,const string &authorization);
xiongziliang committed
174
	//校验base64方式的认证加密
175
    void onAuthBasic(const string &realm,const string &strBase64);
xiongziliang committed
176
	//校验md5方式的认证加密
177
    void onAuthDigest(const string &realm,const string &strMd5);
178

xiongziliang committed
179
	//发送rtp给客户端
xiongziliang committed
180
    void sendRtpPacket(const RtpPacket::Ptr &pkt);
xiongziliang committed
181
	//回复客户端
182 183
	bool sendRtspResponse(const string &res_code,const std::initializer_list<string> &header, const string &sdp = "" , const char *protocol = "RTSP/1.0");
	bool sendRtspResponse(const string &res_code,const StrCaseMap &header = StrCaseMap(), const string &sdp = "",const char *protocol = "RTSP/1.0");
xiongziliang committed
184
	//服务器发送rtcp
xiongziliang committed
185
	void sendSenderReport(bool overTcp,int iTrackIndex);
186 187
	//设置socket标志
	void setSocketFlags();
xiongziliang committed
188
private:
xiongziliang committed
189
	//用于判断客户端是否超时
190
	Ticker _ticker;
xiongziliang committed
191
	//收到的seq,回复时一致
192
	int _iCseq = 0;
xiongziliang committed
193
	//ContentBase
xiongziliang committed
194
	string _strContentBase;
xiongziliang committed
195
	//Session号
196
	string _strSession;
xiongziliang committed
197
	//是否第一次播放,第一次播放需要鉴权,第二次播放属于暂停恢复
198
	bool _bFirstPlay = true;
xiongziliang committed
199
	//url解析后保存的相关信息
200
    MediaInfo _mediaInfo;
xiongziliang committed
201
	//rtsp播放器绑定的直播源
202
	std::weak_ptr<RtspMediaSource> _pMediaSrc;
xiongziliang committed
203
	//直播源读取器
204
	RingBuffer<RtpPacket::Ptr>::RingReader::Ptr _pRtpReader;
xiongziliang committed
205
	//推流或拉流客户端采用的rtp传输方式
xiongziliang committed
206
	Rtsp::eRtpType _rtpType = Rtsp::RTP_Invalid;
xiongziliang committed
207
	//sdp里面有效的track,包含音频或视频
xiongziliang committed
208
	vector<SdpTrack::Ptr> _aTrackInfo;
xiongziliang committed
209 210 211 212 213 214
	////////RTP over udp////////
	//RTP端口,trackid idx 为数组下标
	Socket::Ptr _apRtpSock[2];
	//RTCP端口,trackid idx 为数组下标
	Socket::Ptr _apRtcpSock[2];
	//标记是否收到播放的udp打洞包,收到播放的udp打洞包后才能知道其外网udp端口号
215
    unordered_set<int> _udpSockConnected;
xiongziliang committed
216 217
	////////RTP over udp_multicast////////
	//共享的rtp组播对象
xiongziliang committed
218
	RtpMultiCaster::Ptr _multicaster;
xzl committed
219

220
	//登录认证
221
    string _strNonce;
222 223
    //消耗的总流量
    uint64_t _ui64TotalBytes = 0;
224

xzl committed
225 226
	//RTSP over HTTP
	//quicktime 请求rtsp会产生两次tcp连接,
227 228 229
	//一次发送 get 一次发送post,需要通过x-sessioncookie关联起来
	string _http_x_sessioncookie;
	function<void(const Buffer::Ptr &pBuf)> _onRecv;
xiongziliang committed
230
	//是否开始发送rtp
231
    bool _enableSendRtp;
xiongziliang committed
232 233
    //rtsp推流相关
	RtspToRtmpMediaSource::Ptr _pushSrc;
xiongziliang committed
234 235 236 237
	//rtcp统计,trackid idx 为数组下标
	RtcpCounter _aRtcpCnt[2];
	//rtcp发送时间,trackid idx 为数组下标
	Ticker _aRtcpTicker[2];
238 239
    //时间戳修整器
    Stamp _stamp[2];
xzl committed
240 241
};

242 243 244 245 246
/**
 * 支持ssl加密的rtsp服务器,可用于诸如亚马逊echo show这样的设备访问
 */
typedef TcpSessionWithSSL<RtspSession> RtspSessionWithSSL;

xiongziliang committed
247
} /* namespace mediakit */
xzl committed
248 249

#endif /* SESSION_RTSPSESSION_H_ */