• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device 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 #define HST_LOG_TAG "AppClient"
17 
18 #include <fstream>
19 #include <algorithm>
20 #include <fcntl.h>
21 #include <map>
22 #include "app_client.h"
23 #include "avcodec_trace.h"
24 #include "osal/task/task.h"
25 
26 
27 namespace OHOS {
28 namespace Media {
29 namespace Plugins {
30 namespace HttpPlugin {
31 namespace {
32     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_SYSTEM_PLAYER, "HiStreamer" };
33     constexpr size_t MAX_MAP_SIZE = 100;
34     constexpr int DROP_APP_DATA = -2;
35     constexpr int64_t DEFAULT_CURRENT_OFFSET = -2;
36     constexpr int BUFFER_FULL = -3;
37     constexpr int RETRY_SLEEP_TIME = 500; // ms
38     constexpr int FINISHLOADING_SLEEP_TIME = 10; // ms
39 }
40 
AppClient(RxHeader headCallback,RxBody bodyCallback,void * userParam)41 AppClient::AppClient(RxHeader headCallback, RxBody bodyCallback, void *userParam)
42     : rxHeader_(headCallback), rxBody_(bodyCallback), userParam_(userParam)
43 {
44     rxHeader_ = headCallback;
45     rxBody_ = bodyCallback;
46     userParam_ = userParam;
47     MEDIA_LOG_I("0x%{public}06" PRIXPTR " AppClient create", FAKE_POINTER(this));
48 }
49 
~AppClient()50 AppClient::~AppClient()
51 {
52 }
53 
MapToString(std::map<std::string,std::string> httpHeader)54 void AppClient::MapToString(std::map<std::string, std::string> httpHeader)
55 {
56     std::string headerStr = "";
57     if (httpHeader.size() > MAX_MAP_SIZE) { // The length of map exceeds the limit
58         rxHeader_(nullptr, 0, 0, userParam_);
59         return;
60     }
61     std::map<std::string, std::string> httpHeaderTmp = httpHeader;
62     for (std::map<std::string, std::string>::iterator iter = httpHeaderTmp.begin();
63         iter != httpHeaderTmp.end(); iter++) {
64         headerStr = iter->first + " : " + iter->second;
65         char* headerTmp = (char*)headerStr.c_str();
66         MEDIA_LOG_I("0x%{public}06" PRIXPTR " AppClient header: " PUBLIC_LOG_S,
67             FAKE_POINTER(this), (char*)headerStr.c_str());
68         void* buffer = reinterpret_cast<void*>(headerTmp);
69         rxHeader_(buffer, 1, 1, userParam_);
70     }
71 }
72 
Init()73 Status AppClient::Init()
74 {
75     return Status::OK;
76 }
77 
Open(const std::string & url,const std::map<std::string,std::string> & httpHeader,int32_t timeoutMs)78 Status AppClient::Open(const std::string& url, const std::map<std::string, std::string>& httpHeader,
79     int32_t timeoutMs)
80 {
81     (void)url;
82     (void)httpHeader;
83     (void)timeoutMs;
84     return Status::OK;
85 }
86 
RequestData(long startPos,int len,const RequestInfo & requestInfo,HandleResponseCbFunc completedCb)87 Status AppClient::RequestData(long startPos, int len, const RequestInfo& requestInfo,
88     HandleResponseCbFunc completedCb)
89 {
90     MediaAVCodec::AVCodecTrace trace("AppClient RequestData, startPos: " +
91         std::to_string(startPos) + ", len: " + std::to_string(len));
92     (void)requestInfo;
93     MEDIA_LOG_I("0x%{public}06" PRIXPTR "AppClient RequestData in, startPos: "
94         PUBLIC_LOG_D32 " len: " PUBLIC_LOG_D32, FAKE_POINTER(this), static_cast<int>(startPos), len);
95 
96     startPos_ = startPos;
97     if (startPos == -1) {
98         len = -1;
99         startPos = 0;
100     }
101     len_ = len;
102     startPos_ = startPos;
103     curOffset_ = static_cast<int64_t>(startPos);
104     dataInFlight_ = len;
105 
106     int32_t clientCode = 0;
107     int32_t serverCode = 0;
108     LoadingRequestError requestState;
109     {
110         AutoLock lock(mutex_);
111         isResponseCompleted_.store(false);
112         int32_t res = sourceLoader_->Read(uuid_, static_cast<int64_t>(startPos), static_cast<int64_t>(len));
113         FALSE_LOG_MSG(res == 0, "sourceLoader read fail.");
114 
115         responseCondition_.Wait(lock, [this] {
116             return isResponseCompleted_.load();
117         });
118         requestState = requestState_;
119     }
120     clientCode = static_cast<int32_t>(requestState) * (-1);
121 
122     Status ret = Status::OK;
123     if (requestState_ == LoadingRequestError::LOADING_ERROR_SUCCESS) {
124         MEDIA_LOG_I("0x%{public}06" PRIXPTR "AppClient RequestData success", FAKE_POINTER(this));
125         completedCb(clientCode, serverCode, ret);
126     } else {
127         MEDIA_LOG_I("0x%{public}06" PRIXPTR "AppClient RequestData fail, clientCode: " PUBLIC_LOG_D32
128             " requestState_: " PUBLIC_LOG_D32, FAKE_POINTER(this), clientCode, requestState_);
129 
130         Task::SleepInTask(RETRY_SLEEP_TIME);
131         ret = Status::ERROR_CLIENT;
132         completedCb(clientCode, serverCode, ret);
133     }
134     requestState_ = LoadingRequestError::LOADING_ERROR_SUCCESS;
135     return Status::OK;
136 }
137 
Close(bool isAsync)138 Status AppClient::Close(bool isAsync)
139 {
140     (void)isAsync;
141     NotifyResponseDataEnd(LoadingRequestError::LOADING_ERROR_SUCCESS);
142     MEDIA_LOG_I("0x%{public}06" PRIXPTR "AppClient Close.", FAKE_POINTER(this));
143     return Status::OK;
144 }
145 
Deinit()146 Status AppClient::Deinit()
147 {
148     return Status::OK;
149 }
150 
GetIp(std::string & ip)151 Status AppClient::GetIp(std::string &ip)
152 {
153     (void)ip;
154     return Status::OK;
155 }
156 
SetAppUid(int32_t appUid)157 void AppClient::SetAppUid(int32_t appUid)
158 {
159 }
160 
GetAppInstance(RxHeader headCallback,RxBody bodyCallback,void * userParam)161 std::shared_ptr<NetworkClient> NetworkClient::GetAppInstance(RxHeader headCallback,
162     RxBody bodyCallback, void *userParam)
163 {
164     return std::make_shared<AppClient>(headCallback, bodyCallback, userParam);
165 }
166 
SetLoader(std::shared_ptr<IMediaSourceLoader> sourceLoader)167 void AppClient::SetLoader(std::shared_ptr<IMediaSourceLoader> sourceLoader)
168 {
169     sourceLoader_ = sourceLoader;
170 }
171 
RespondHeader(int64_t uuid,const std::map<std::string,std::string> & httpHeader,std::string redirectUrl)172 int32_t AppClient::RespondHeader(int64_t uuid, const std::map<std::string, std::string>& httpHeader,
173     std::string redirectUrl)
174 {
175     MediaAVCodec::AVCodecTrace trace("AppClient RespondHeader, uuid: " + std::to_string(uuid));
176     FALSE_LOG_MSG(uuid > 0, "sourceLoader read fail.");
177     std::map<std::string, std::string> httpHeaderTmp = httpHeader;
178     if (!redirectUrl.empty()) {
179         httpHeaderTmp.emplace("location", redirectUrl);
180     }
181     MapToString(httpHeaderTmp);
182     return 0;
183 }
184 
NotifyResponseDataEnd(LoadingRequestError state)185 void AppClient::NotifyResponseDataEnd(LoadingRequestError state)
186 {
187     {
188         AutoLock lock(mutex_);
189         requestState_ = state;
190         isResponseCompleted_.store(true);
191         responseCondition_.NotifyOne();
192         if (state == LoadingRequestError::LOADING_ERROR_SUCCESS) {
193             curOffset_ = DEFAULT_CURRENT_OFFSET;
194         }
195     }
196     MEDIA_LOG_D("0x%{public}06" PRIXPTR "AppClient NotifyResponseDataEnd state: " PUBLIC_LOG_D32,
197         FAKE_POINTER(this), static_cast<int32_t>(state));
198 }
199 
RespondData(int64_t uuid,int64_t offset,const std::shared_ptr<AVSharedMemory> memory)200 int32_t AppClient::RespondData(int64_t uuid, int64_t offset, const std::shared_ptr<AVSharedMemory> memory)
201 {
202     FALSE_RETURN_V(memory != nullptr, 0);
203     if (uuid != uuid_) {
204         MEDIA_LOG_E("0x%{public}06" PRIXPTR " AppClient respondData uuid invalid, uuid: " PUBLIC_LOG_D64,
205             FAKE_POINTER(this), uuid);
206         NotifyResponseDataEnd(LoadingRequestError::LOADING_ERROR_NOT_READY);
207         return DROP_APP_DATA;
208     }
209 
210     if (curOffset_ != offset) {
211         MEDIA_LOG_E("0x%{public}06" PRIXPTR " AppClient respondData offset invalid, offset: " PUBLIC_LOG_D64
212             " curOffset_: " PUBLIC_LOG_D32, FAKE_POINTER(this), offset, static_cast<int32_t>(curOffset_));
213         NotifyResponseDataEnd(LoadingRequestError::LOADING_ERROR_NOT_READY);
214         return DROP_APP_DATA;
215     }
216 
217     void* buffer = reinterpret_cast<void*>(memory->GetBase());
218     size_t res = rxBody_(buffer, memory->GetSize(), 1, userParam_);
219     curOffset_ += static_cast<int64_t>(res);
220     if (res == 0) {
221         MEDIA_LOG_W("0x%{public}06" PRIXPTR " AppClient respondData buffer full, can not write, uuid: " PUBLIC_LOG_D64,
222             FAKE_POINTER(this), uuid);
223         NotifyResponseDataEnd(LoadingRequestError::LOADING_ERROR_SUCCESS);
224         return BUFFER_FULL;
225     }
226 
227     int32_t receiveDataSize = memory->GetSize();
228     MediaAVCodec::AVCodecTrace trace("AppClient RespondData, uuid: " + std::to_string(uuid) +
229         ", offset: " + std::to_string(offset) + ", receiveDataSize: " + std::to_string(receiveDataSize));
230     dataInFlight_ -= receiveDataSize;
231 
232     if (len_ > 0 && dataInFlight_ <= 0) {
233         NotifyResponseDataEnd(LoadingRequestError::LOADING_ERROR_SUCCESS);
234     }
235     MEDIA_LOG_D("0x%{public}06" PRIXPTR " AppClient RespondData, uuid " PUBLIC_LOG_D64 " offset " PUBLIC_LOG_D64
236         " dataInFlight_ " PUBLIC_LOG_D32 " size " PUBLIC_LOG_D32, FAKE_POINTER(this), uuid, offset,
237         dataInFlight_, receiveDataSize);
238     return receiveDataSize;
239 }
240 
FinishLoading(int64_t uuid,LoadingRequestError state)241 int32_t AppClient::FinishLoading(int64_t uuid, LoadingRequestError state)
242 {
243     FALSE_RETURN_V_MSG_E(uuid == uuid_, 0, "FinishLoading uuid invalid.");
244     MEDIA_LOG_I("0x%{public}06" PRIXPTR "AppClient FinishLoading uuid " PUBLIC_LOG_D64, FAKE_POINTER(this), uuid);
245     Task::SleepInTask(FINISHLOADING_SLEEP_TIME);
246     NotifyResponseDataEnd(state);
247     return 0;
248 }
249 
SetUuid(int64_t uuid)250 void AppClient::SetUuid(int64_t uuid)
251 {
252     FALSE_RETURN_MSG(uuid > 0, "SetUuid uuid invalid.");
253     MEDIA_LOG_D("0x%{public}06" PRIXPTR " AppClient SetUuid " PUBLIC_LOG_D64, FAKE_POINTER(this), uuid);
254     uuid_ = uuid;
255 }
256 
GetRedirectUrl()257 std::string AppClient::GetRedirectUrl()
258 {
259     return redirectUrl_;
260 }
261 }
262 }
263 }
264 }