1 /*
2  * Copyright (c) 2024 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 #include "net_http_ffi.h"
16 #include "net_http_request_context.h"
17 #include "net_http_cache_proxy.h"
18 #include "net_http_client_exec.h"
19 #include "cj_lambda.h"
20 
21 #include <vector>
22 
23 using namespace OHOS::FFI;
24 namespace OHOS::NetStack::Http {
25 
SetUnknowError(RetDataCString & ret)26 void SetUnknowError(RetDataCString &ret)
27 {
28     ret.code = static_cast<int32_t>(HttpErrorCode::HTTP_UNKNOWN_OTHER_ERROR);
29     ret.data = MallocCString("Unknown Other Error.");
30 }
31 
32 EXTERN_C_START
CJ_CreateHttpResponseCache(uint32_t cacheSize)33     int32_t CJ_CreateHttpResponseCache(uint32_t cacheSize)
34     {
35         CacheProxy::RunCacheWithSize(cacheSize);
36         return 0;
37     }
38 
CJ_HttpResponseCacheFlush()39     int32_t CJ_HttpResponseCacheFlush()
40     {
41         CacheProxy::FlushCache();
42         return 0;
43     }
44 
CJ_HttpResponseCacheDelete()45     int32_t CJ_HttpResponseCacheDelete()
46     {
47         CacheProxy::StopCacheAndDelete();
48         return 0;
49     }
50 
CJ_CreateHttp()51     int64_t CJ_CreateHttp()
52     {
53         auto request = FFI::FFIData::Create<HttpRequestProxy>();
54         if (!request) {
55             return ERR_INVALID_INSTANCE_CODE;
56         }
57         return request->GetID();
58     }
59 
CJ_DestroyRequest(int64_t id)60     void CJ_DestroyRequest(int64_t id)
61     {
62         auto req = FFIData::GetData<HttpRequestProxy>(id);
63         if (req == nullptr) {
64             NETSTACK_LOGE("Failed to get HttpRequestProxy.");
65             return;
66         }
67         req->Destroy();
68         FFI::FFIData::Release(id);
69         return;
70     }
71 
CJ_SendRequest(int64_t id,char * url,CHttpRequestOptions * opt,bool isInStream,void (* callback)(CHttpResponse))72     RetDataCString CJ_SendRequest(int64_t id, char* url,
73         CHttpRequestOptions* opt, bool isInStream, void (*callback)(CHttpResponse))
74     {
75         NETSTACK_LOGI("request start");
76         RetDataCString ret = { .code = 0, .data = nullptr};
77         auto req = FFIData::GetData<HttpRequestProxy>(id);
78         if (req == nullptr || req->isDestroyed) {
79             // destroyed
80             SetUnknowError(ret);
81             return ret;
82         }
83         auto context = req->Request(std::string(url), opt, isInStream);
84         if (context == nullptr) {
85             // curl initialize failed
86             SetUnknowError(ret);
87             return ret;
88         }
89         if (isInStream) {
90             context->streamingCallback = req->callbacks;
91         }
92 
93         context->respCallback = CJLambda::Create(callback);
94 
95         if (context->IsPermissionDenied() || !context->IsParseOK()) {
96             ret.code = context->GetErrorCode();
97             ret.data = MallocCString(context->GetErrorMessage());
98             return ret;
99         }
100 
101         return ret;
102     }
103 
CJ_OnHeadersReceive(int64_t id,bool once,void (* callback)(CArrString))104     void CJ_OnHeadersReceive(int64_t id, bool once, void (*callback)(CArrString))
105     {
106         auto req = FFIData::GetData<HttpRequestProxy>(id);
107         if (req == nullptr) {
108             NETSTACK_LOGE("Failed to get HttpRequestProxy.");
109             return;
110         }
111         if (once) {
112             req->callbacks->headersReceiveOnce.push_back(CJLambda::Create(callback));
113         } else {
114             req->callbacks->headersReceive.push_back(CJLambda::Create(callback));
115         }
116     }
117 
CJ_OffHeadersReceive(int64_t id)118     void CJ_OffHeadersReceive(int64_t id)
119     {
120         auto req = FFIData::GetData<HttpRequestProxy>(id);
121         if (req == nullptr) {
122             NETSTACK_LOGE("Failed to get HttpRequestProxy.");
123             return;
124         }
125         req->callbacks->headersReceiveOnce.clear();
126         req->callbacks->headersReceive.clear();
127     }
128 
CJ_OnDataReceive(int64_t id,void (* callback)(CArrUI8))129     void CJ_OnDataReceive(int64_t id, void (*callback)(CArrUI8))
130     {
131         auto req = FFIData::GetData<HttpRequestProxy>(id);
132         if (req == nullptr) {
133             NETSTACK_LOGE("Failed to get HttpRequestProxy.");
134             return;
135         }
136         req->callbacks->dataReceive.push_back(CJLambda::Create(callback));
137     }
138 
CJ_OffDataReceive(int64_t id)139     void CJ_OffDataReceive(int64_t id)
140     {
141         auto req = FFIData::GetData<HttpRequestProxy>(id);
142         if (req == nullptr) {
143             NETSTACK_LOGE("Failed to get HttpRequestProxy.");
144             return;
145         }
146         req->callbacks->dataReceive.clear();
147     }
148 
CJ_OnDataEnd(int64_t id,void (* callback)())149     void CJ_OnDataEnd(int64_t id, void (*callback)())
150     {
151         auto req = FFIData::GetData<HttpRequestProxy>(id);
152         if (req == nullptr) {
153             NETSTACK_LOGE("Failed to get HttpRequestProxy.");
154             return;
155         }
156         req->callbacks->dataEnd.push_back(CJLambda::Create(callback));
157     }
158 
CJ_OffDataEnd(int64_t id)159     void CJ_OffDataEnd(int64_t id)
160     {
161         auto req = FFIData::GetData<HttpRequestProxy>(id);
162         if (req == nullptr) {
163             NETSTACK_LOGE("Failed to get HttpRequestProxy.");
164             return;
165         }
166         req->callbacks->dataEnd.clear();
167     }
168 
CJ_OnDataReceiveProgress(int64_t id,void (* callback)(CDataReceiveProgressInfo))169     void CJ_OnDataReceiveProgress(int64_t id, void (*callback)(CDataReceiveProgressInfo))
170     {
171         auto req = FFIData::GetData<HttpRequestProxy>(id);
172         if (req == nullptr) {
173             NETSTACK_LOGE("Failed to get HttpRequestProxy.");
174             return;
175         }
176         req->callbacks->dataReceiveProgress.push_back(CJLambda::Create(callback));
177     }
178 
CJ_OffDataReceiveProgress(int64_t id)179     void CJ_OffDataReceiveProgress(int64_t id)
180     {
181         auto req = FFIData::GetData<HttpRequestProxy>(id);
182         if (req == nullptr) {
183             NETSTACK_LOGE("Failed to get HttpRequestProxy.");
184             return;
185         }
186         req->callbacks->dataReceiveProgress.clear();
187     }
188 
CJ_OnDataSendProgress(int64_t id,void (* callback)(CDataSendProgressInfo))189     void CJ_OnDataSendProgress(int64_t id, void (*callback)(CDataSendProgressInfo))
190     {
191         auto req = FFIData::GetData<HttpRequestProxy>(id);
192         if (req == nullptr) {
193             NETSTACK_LOGE("Failed to get HttpRequestProxy.");
194             return;
195         }
196         req->callbacks->dataSendProgress.push_back(CJLambda::Create(callback));
197     }
198 
CJ_OffDataSendProgress(int64_t id)199     void CJ_OffDataSendProgress(int64_t id)
200     {
201         auto req = FFIData::GetData<HttpRequestProxy>(id);
202         if (req == nullptr) {
203             NETSTACK_LOGE("Failed to get HttpRequestProxy.");
204             return;
205         }
206         req->callbacks->dataSendProgress.clear();
207     }
208 EXTERN_C_END
209 }
210 
211