1 /*
2  * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "rtsp_request.h"
17 #include <iomanip>
18 #include <iostream>
19 #include <sstream>
20 
21 namespace OHOS {
22 namespace Sharing {
Stringify()23 std::string RtspRequest::Stringify()
24 {
25     std::stringstream ss;
26     ss << method_ << RTSP_SP << url_ << RTSP_SP << RTSP_VERSION << RTSP_CRLF;
27     ss << RTSP_TOKEN_CSEQ << ":" << RTSP_SP << cSeq_ << RTSP_CRLF;
28     if (!authorization_.empty()) {
29         ss << RTSP_TOKEN_AUTHORIZATION << ":" << RTSP_SP << authorization_ << RTSP_CRLF;
30     }
31     ss << RTSP_TOKEN_UA << ":" << RTSP_SP << userAgent_ << RTSP_CRLF;
32     if (!session_.empty()) {
33         ss << RTSP_TOKEN_SESSION << ":" << RTSP_SP << session_;
34         if (timeout_ > 0) {
35             ss << ";timeout=" << timeout_;
36         }
37         ss << RTSP_CRLF;
38     }
39 
40     if (!customHeaders_.empty()) {
41         ss << customHeaders_;
42     }
43     ss << RTSP_CRLF;
44     return ss.str();
45 }
46 
Parse(const std::string &request)47 RtspError RtspRequest::Parse(const std::string &request)
48 {
49     std::vector<std::string> firstLine;
50     auto result = RtspCommon::ParseMessage(request, firstLine, tokens_, body_);
51     if (result.code != RtspErrorType::OK) {
52         return result;
53     }
54 
55     if (firstLine.size() < 2 || tokens_.empty()) { // 2:rtsp line
56         tokens_.clear();
57         body_.clear();
58         return {RtspErrorType::INVALID_MESSAGE, "invalid message"};
59     }
60 
61     // "METHOD URL VERSION"
62     if (firstLine.size() != 3 || firstLine[2] != RTSP_VERSION) { // 2:rtsp line, 3:rtsp line
63         tokens_.clear();
64         body_.clear();
65         return {RtspErrorType::INVALID_MESSAGE, "invalid message"};
66     }
67 
68     if (!RtspCommon::VerifyMethod(firstLine[0])) {
69         tokens_.clear();
70         body_.clear();
71         return {RtspErrorType::INVALID_METHOD, "invalid method"};
72     }
73 
74     method_ = firstLine[0];
75     url_ = firstLine[1];
76 
77     if (tokens_.find(RTSP_TOKEN_CSEQ) != tokens_.end()) {
78         cSeq_ = atoi(tokens_.at(RTSP_TOKEN_CSEQ).c_str());
79     }
80 
81     if (tokens_.find(RTSP_TOKEN_UA) != tokens_.end()) {
82         userAgent_ = tokens_.at(RTSP_TOKEN_UA);
83     }
84 
85     if (tokens_.find(RTSP_TOKEN_SESSION) != tokens_.end()) {
86         session_ = tokens_.at(RTSP_TOKEN_SESSION);
87     }
88 
89     return {};
90 }
91 
GetToken(const std::string &token)92 std::string RtspRequest::GetToken(const std::string &token)
93 {
94     if (tokens_.find(token) != tokens_.end()) {
95         return tokens_.at(token);
96     }
97 
98     return {};
99 }
100 
Stringify()101 std::string RtspRequestOptions::Stringify()
102 {
103     if (!require_.empty()) {
104         std::stringstream ss;
105         ss << RTSP_TOKEN_REQUIRE << ":" << RTSP_SP << require_ << RTSP_CRLF;
106         ClearCustomHeader();
107         AddCustomHeader(ss.str());
108     }
109 
110     return RtspRequest::Stringify();
111 }
112 
Stringify()113 std::string RtspRequestDescribe::Stringify()
114 {
115     std::stringstream ss;
116     ss << RTSP_TOKEN_ACCEPT << ":" << RTSP_SP << acceptType_ << RTSP_CRLF;
117     ClearCustomHeader();
118     AddCustomHeader(ss.str());
119     return RtspRequest::Stringify();
120 }
121 
Stringify()122 std::string RtspRequestSetup::Stringify()
123 {
124     std::stringstream ss;
125     ss << RTSP_TOKEN_TRANSPORT << ":" << RTSP_SP << "RTP/AVP;unicast;client_port=" << minPort_;
126     if (maxPort_ > 0) {
127         ss << "-" << maxPort_;
128     }
129     ss << RTSP_CRLF;
130     ClearCustomHeader();
131     AddCustomHeader(ss.str());
132     return RtspRequest::Stringify();
133 }
134 
Stringify()135 std::string RtspRequestPlay::Stringify()
136 {
137     if (range_ >= 0) {
138         std::stringstream ss;
139         ss << RTSP_TOKEN_RANGE << ":" << RTSP_SP << "npt=";
140         ss << std::fixed << std::setprecision(3) << range_ << "-" << RTSP_CRLF; // 3:precision
141         ClearCustomHeader();
142         AddCustomHeader(ss.str());
143     }
144 
145     return RtspRequest::Stringify();
146 }
147 
Stringify()148 std::string RtspRequestParameter::Stringify()
149 {
150     std::stringstream body;
151     for (auto &item : body_) {
152         body << item << RTSP_CRLF;
153     }
154 
155     if (body.str().empty()) {
156         return RtspRequest::Stringify();
157     } else {
158         std::stringstream ss;
159         ss << RTSP_TOKEN_CONTENT_TYPE << ":" << RTSP_SP << "text/parameters" << RTSP_CRLF;
160         ss << RTSP_TOKEN_CONTENT_LENGTH << ":" << RTSP_SP << body.str().length() << RTSP_CRLF;
161         ClearCustomHeader();
162         AddCustomHeader(ss.str());
163         return RtspRequest::Stringify() + body.str();
164     }
165 }
166 } // namespace Sharing
167 } // namespace OHOS