1 /*
2  * Copyright (C) 2021 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 #ifndef NSTACKX_DFILE_H
17 #define NSTACKX_DFILE_H
18 
19 #include <stdint.h>
20 #include <stdbool.h>
21 #include <stdarg.h>
22 
23 #if defined(_WIN32) || defined(_WIN64)
24 #include <WS2tcpip.h>
25 #define NSTACKX_EXPORT __declspec(dllexport)
26 #else
27 #include <ifaddrs.h>
28 #include <netinet/in.h>
29 #define NSTACKX_EXPORT extern
30 #endif
31 
32 #include "nstackx_error.h"
33 #ifdef __cplusplus
34 extern "C" {
35 #endif
36 
37 #ifdef NSTACKX_WITH_LITEOS
38 #define NSTACKX_DFILE_MAX_FILE_NUM 10
39 #else
40 #define NSTACKX_DFILE_MAX_FILE_NUM 500
41 #endif
42 #define NSTACKX_MAX_FILE_NAME_LEN 256
43 #define NSTACKX_MAX_PATH_LEN 256
44 #define NSTACKX_MAX_REMOTE_PATH_LEN 1024
45 /* Maximum sending list limit. Sending more than this value will fail. */
46 #ifdef NSTACKX_WITH_LITEOS
47 #define NSTACKX_MAX_FILE_LIST_NUM 10
48 #else
49 #define NSTACKX_MAX_FILE_LIST_NUM 500
50 #endif
51 #define NSTACKX_MAX_STORAGE_PATH_NUM 500
52 #define NSTACKX_RESERVED_TRANS_ID 0
53 #define NSTACKX_RESERVED_PATH_TYPE 0
54 #define NSTACKX_MULTI_PATH_NUM 2
55 /* 10MB VTRANS */
56 #define NSTACKX_VTRANS_DEFAULT_SIZE (10 * 1024 * 1024)
57 #define NSTACKX_VTRANS_STEP_SIZE (5 * 1024 * 1024)
58 #define NSTACKX_VTRANS_MAX_SIZE (1024 * 1024 * 1024)
59 
60 #define CAPS_MULTIPATH 4
61 
62 typedef struct DFileSession DFileSession;
63 
64 /* DFile session message type list. */
65 typedef enum {
66     DFILE_ON_CONNECT_SUCCESS = 1,
67     DFILE_ON_CONNECT_FAIL,
68     DFILE_ON_FILE_LIST_RECEIVED,
69     DFILE_ON_FILE_RECEIVE_SUCCESS,
70     DFILE_ON_FILE_RECEIVE_FAIL,
71     DFILE_ON_FILE_SEND_SUCCESS,
72     DFILE_ON_FILE_SEND_FAIL,
73     DFILE_ON_FATAL_ERROR,
74     DFILE_ON_SESSION_IN_PROGRESS,
75     DFILE_ON_TRANS_IN_PROGRESS,
76     DFILE_ON_SESSION_TRANSFER_RATE,
77     DFILE_ON_BIND,
78     DFILE_ON_CLEAR_POLICY_FILE_LIST,
79 } DFileMsgType;
80 
81 enum {
82     CAPS_UDP_GSO = 0,
83     CAPS_LINK_SEQUENCE,
84     CAPS_WLAN_CATAGORY,
85     CAPS_NO_RTT,
86     CAPS_RESERVED, /* for multipath check of old version */
87     CAPS_ALG_NORATE, // NoRate algorithm
88     CAPS_RESUMABLE_TRANS,
89     CAPS_ZEROCOPY,
90     CAPS_CHACHA_CIPHRE,
91     /* add more capability here */
92     CAPS_MAX,
93 };
94 
95 #define NSTACKX_WLAN_CAT_2_4G               1U
96 #define NSTACKX_WLAN_CAT_5G                 2U
97 #define NSTACKX_WLAN_CAT_DIRECT             3U
98 #define NSTACKX_WLAN_CAT_TCP                4U
99 
100 #define NSTACKX_RECV_BUFFER_LEN  1600
101 
102 #define NBITS(n)                            (1U << (n))
103 #define NSTACKX_CAPS_UDP_GSO                NBITS(CAPS_UDP_GSO)
104 #define NSTACKX_CAPS_LINK_SEQUENCE          NBITS(CAPS_LINK_SEQUENCE)
105 #define NSTACKX_CAPS_WLAN_CATAGORY          NBITS(CAPS_WLAN_CATAGORY)
106 #define NSTACKX_CAPS_MULTIPATH              NBITS(CAPS_MULTIPATH)
107 #define NSTACKX_CAPS_CHACHA                 NBITS(CAPS_CHACHA_CIPHRE)
108 
109 #define NSTACKX_CAPS_MASK                   (NBITS(CAPS_MAX) - 1)
110 
111 /*
112  * DFile session message data. User should fetch corresponding member variable based on message type:
113  *          DFileMsgType               Member variable
114  *   DFILE_ON_CONNECT_SUCCESS            none
115  *   DFILE_ON_CONNECT_FAIL               errorCode
116  *   DFILE_ON_FILE_LIST_RECEIVED         fileList
117  *   DFILE_ON_FILE_RECEIVE_SUCCESS       fileList and transferUpdate
118  *   DFILE_ON_FILE_RECEIVE_FAIL          fileList, errorCode and transferUpdate. fileList maybe empty, as not all the
119  *                                       file names are received.
120  *   DFILE_ON_FILE_SEND_SUCCESS          fileList and transferUpdate
121  *   DFILE_ON_FILE_SEND_FAIL             fileList, errorCode and transferUpdate.
122  *   DFILE_ON_TRANS_IN_PROGRESS          transferUpdate and fileList. Transfer process update of target trans identified
123  *                                       by the transId.
124  *   DFILE_ON_SESSION_IN_PROGRESS        transferUpdate. Transfer process update of the whole session.
125  *
126  *   DFILE_ON_FATAL_ERROR                errorCode. DFileSession cannot be used any more, and should be destroyed.
127  *   DFILE_ON_SESSION_TRANSFER_RATE      rate.
128  *
129  * It's invalid when for other message types.
130  */
131 typedef enum {
132     FILE_STAT_COMPLETE,     /* whole file transfered*/
133     FILE_STAT_NOT_COMPLETE, /*file start transfered but not whole*/
134     FILE_STAT_NOT_START,    /*file not start transfered*/
135     FILE_STAT_BUTT,
136 } DFileFileStat;
137 
138 typedef struct {
139     char *file;
140     DFileFileStat stat;
141 } DFileFileInfo;
142 
143 typedef struct {
144     struct {
145         const char **files;
146         uint32_t fileNum;
147         uint16_t transId;
148         char *userData;
149     } fileList;
150     struct {
151         uint32_t fileNum;
152         const DFileFileInfo *fileInfo;
153     } clearPolicyFileList;
154     int32_t errorCode;
155     struct {
156         uint16_t transId;
157         uint64_t totalBytes;
158         uint64_t bytesTransferred;
159     } transferUpdate;
160     uint32_t rate;
161     struct sockaddr_in sockAddr[NSTACKX_MULTI_PATH_NUM];
162 } DFileMsg;
163 
164 typedef struct {
165     const char *files[NSTACKX_DFILE_MAX_FILE_NUM];
166     const char *remotePath[NSTACKX_DFILE_MAX_FILE_NUM];
167     uint32_t fileNum;
168     const char *userData;
169     uint16_t pathType;
170     uint8_t tarFlag : 1;
171     uint8_t smallFlag : 1;
172     uint8_t unuse : 6;
173 } NSTACKX_FilesInfo;
174 
175 typedef struct {
176     uint16_t rootPathType;
177     const char *initFileName;
178     char newFileName[NSTACKX_MAX_REMOTE_PATH_LEN];
179 } DFileRenamePara;
180 
181 /* Callback type for rename existing file */
182 typedef void (*OnDFileRenameFile)(DFileRenamePara *renamePara);
183 
184 /* Callback type for DFile session message receiver. */
185 typedef void (*DFileMsgReceiver)(int32_t sessionId, DFileMsgType msgType, const DFileMsg *msg);
186 
187 typedef struct {
188     struct sockaddr_in *addr;
189     socklen_t addrLen;
190     const uint8_t *key;
191     uint32_t keyLen;
192     DFileMsgReceiver msgReceiver;
193     const char *localInterfaceName;
194 } NSTACKX_SessionPara;
195 
196 typedef void (*DFileLogImpl)(const char *tag, uint32_t level, const char *format, va_list args);
197 
198 typedef struct {
199     struct sockaddr_in *addr;
200     socklen_t addrLen;
201     const char *localInterfaceName;
202 } NSTACKX_SessionParaMp;
203 
204 typedef struct {
205     struct sockaddr_in *addr;
206     socklen_t addrLen;
207 } NSTACKX_ServerParaMp;
208 
209 /* nStack HIEVENT接口设计 */
210 typedef enum {
211     DFile_EVENT_TYPE_FAULT,
212     DFile_EVENT_TYPE_STATISTIC,
213     DFile_EVENT_TYPE_SECURITY,
214     DFile_EVENT_TYPE_BEHAVIOR,
215 } DFileEventType;
216 
217 typedef enum {
218     DFile_EVENT_LEVEL_CRITICAL,
219     DFile_EVENT_LEVEL_MINOR,
220 } DFileEventLevel;
221 
222 typedef enum {
223     DFile_PARAM_TYPE_BOOL,
224     DFile_PARAM_TYPE_UINT8,
225     DFile_PARAM_TYPE_UINT16,
226     DFile_PARAM_TYPE_INT32,
227     DFile_PARAM_TYPE_UINT32,
228     DFile_PARAM_TYPE_UINT64,
229     DFile_PARAM_TYPE_FLOAT,
230     DFile_PARAM_TYPE_DOUBLE,
231     DFile_PARAM_TYPE_STRING
232 } DFileEventParamType;
233 
234 enum {
235     DFILE_LOG_LEVEL_OFF     = 0,
236     DFILE_LOG_LEVEL_FATAL   = 1,
237     DFILE_LOG_LEVEL_ERROR   = 2,
238     DFILE_LOG_LEVEL_WARNING = 3,
239     DFILE_LOG_LEVEL_INFO    = 4,
240     DFILE_LOG_LEVEL_DEBUG   = 5,
241     DFILE_LOG_LEVEL_END,
242 };
243 
244 #define DFile_EVENT_NAME_LEN 33
245 #define DFile_EVENT_TAG_LEN 16
246 
247 typedef struct {
248     DFileEventParamType type;
249     char name[DFile_EVENT_NAME_LEN];
250     union {
251         uint8_t u8v;
252         uint16_t u16v;
253         int32_t i32v;
254         uint32_t u32v;
255         uint64_t u64v;
256         float f;
257         double d;
258         char str[DFile_EVENT_NAME_LEN];
259     } value;
260 } DFileEventParam;
261 
262 typedef struct {
263     char eventName[DFile_EVENT_NAME_LEN];
264     DFileEventType type;
265     DFileEventLevel level;
266     uint32_t paramNum;
267     DFileEventParam *params;
268 } DFileEvent;
269 
270 /*
271  * Create DFile server session.
272  * param: localAddr - filled with local ip addr, port and family for socket binding
273  *                    the ip addr and port must be host order
274  * param: addrLen - localAddr length
275  * param: key - key for data encrypt or decrypt, should be a 16 bytes string.
276  * param: msgReceiver - event callback for user
277  * return positive session id on success, negative value on failure
278  */
279 NSTACKX_EXPORT int32_t NSTACKX_DFileServer(struct sockaddr_in *localAddr, socklen_t addrLen, const uint8_t *key,
280                                            uint32_t keyLen, DFileMsgReceiver msgReceiver);
281 
282 
283 /*
284  * Create DFile client session.
285  * param: srvAddr - filled with remote ip addr, port and family, the ip addr and port must be host order
286  * param: addrLen - srvAddr length
287  * param: key - key for data encrypt or decrypt. It should be a 16 bytes buffer if this session is used to transfer
288  *              file with crypto, or NULL if transfer without crypto.
289  * param: keyLen - keyLen for the key. It should be 16 if this session is used to transfer file with crypto, or 0
290  *                 if transfer without crypto.
291  * param: msgReceiver - event callback for user
292  * return positive session id on success, negative value on failure
293  */
294 NSTACKX_EXPORT int32_t NSTACKX_DFileClient(struct sockaddr_in *srvAddr, socklen_t addrLen, const uint8_t *key,
295                                            uint32_t keyLen, DFileMsgReceiver msgReceiver);
296 
297 /*
298  * Create DFile client session on target device.
299  * param: sessionInfo->srvAddr - filled with remote ip addr, port and family, the ip addr and port must be host order
300  * param: sessionInfo->addrLen - srvAddr length
301  * param: sessionInfo->key - key for data encrypt or decrypt. It should be a 16 bytes buffer if this session is used to
302  *                           transfer file with crypto, or NULL if transfer without crypto.
303  * param: sessionInfo->keyLen - keyLen for the key. It should be 16 if this session is used to transfer file with
304  *                              crypto, or 0 if transfer without crypto.
305  * param: sessionInfo->msgReceiver - event callback for user
306  * param: sessionInfo->localInterfaceName - The full name of the target device for the socket of the session to bind.
307  *                                          If this param is NULL, the session's socket will bind to the device in the
308  *                                          same LAN with the srvAddr, but it may be inaccurate under certain
309  *                                          conditions. *
310  * return positive session id on success, negative value on failure
311  */
312 NSTACKX_EXPORT int32_t NSTACKX_DFileClientWithTargetDev(NSTACKX_SessionPara *sessionPara);
313 
314 /* Close session instance. */
315 NSTACKX_EXPORT void NSTACKX_DFileClose(int32_t sessionId);
316 
317 /*
318  * Start to send files by client session.
319  * param: files - File name list.to be sent.
320  * param: fileNum - Number of elements in "files".
321  * param: userData - user context data for each Send Files.
322  * return 0 on success, negative value on failure
323  */
324 NSTACKX_EXPORT int32_t NSTACKX_DFileSendFiles(int32_t sessionId, const char *files[], uint32_t fileNum,
325                                               const char *userData);
326 
327 /*
328  * Start to send files by client session assign the storage dir of this files for server.
329  * param: files - File name list.to be sent.
330  * param: remotePath - The remote path(including file name) list of files for the server to save them.
331  * param: fileNum - Number of elements in "files".
332  * param: userData - user context data for each Send Files.
333  * return 0 on success, negative value on failure
334  */
335 NSTACKX_EXPORT int32_t NSTACKX_DFileSendFilesWithRemotePath(int32_t sessionId, const char *files[],
336     const char *remotePath[], uint32_t fileNum, const char *userData);
337 
338 /*
339  * Start to send files by client session and assign the storage dir of this files for server. The storage dir contains
340  * a root path and a relative dir(including filename). The root dir is set by the server, who may has set more than and
341  * will chose one who has the same type as the filesInfo->pathType. The relative path is filesInfo->remotePath.
342  * param: filesInfo->files - File name list.to be sent.
343  * param: filesInf->remotePath - The remote path list of files.
344  * param: filesInfo->fileNum - Number of elements in "files".
345  * param: filesInfo->userData - User context data for each Send Files.
346  * param: filesInfo->pathType - The type of the fileInfo->files. It determines which root path the server will storage
347  *                              these files. Whats more, transfer will be failed if the server can't find the root path
348  *                              with tha same type.
349  * param: filesInfo->tarFlag - If it is true, this files will be packaged to a tar file and sent. Otherwise, they will
350  *                             be sent separately.
351  * param: filesInfo->smallflag - If it is true, means all files of the list are small files. the files will try to send
352  *                               with big files side-by-side.
353  * return 0 on success, negative value on failure
354  */
355 NSTACKX_EXPORT int32_t NSTACKX_DFileSendFilesWithRemotePathAndType(int32_t sessionId, NSTACKX_FilesInfo *filesInfo);
356 
357 /*
358  * Set storage path for server session. Note that it will move the files that already recevied to this new path.
359  * New incoming files will also be save to here.
360  * return 0 on success, negative value on failure
361  */
362 NSTACKX_EXPORT int32_t NSTACKX_DFileSetStoragePath(int32_t sessionId, const char *path);
363 
364 /*
365  * Set callback for server to rename a new file when there is an existing file with the same dir and name.
366  * If this is not called, the existing file will be overwritte by the new received file with the same dir and name.
367  */
368 NSTACKX_EXPORT int32_t NSTACKX_DFileSetRenameHook(int32_t sessionId, OnDFileRenameFile onRenameFile);
369 
370 /*
371  * Set storage paths for diffreant types of files for server session.
372  * Note that it will move the files that already recevied to this new path.
373  * For the same sessionId, only one of this interface and the NSTACKX_DFileSetStoragePath() can be used.
374  * New incoming files will also be save to one of these path who has the same type. If the incoming files't type isn't
375  * one of the pathType list, these files will be refused
376  * return 0 on success, negative value on failure
377  */
378 NSTACKX_EXPORT int32_t NSTACKX_DFileSetStoragePathList(int32_t sessionId, const char *path[], const uint16_t *pathType,
379                                                        uint16_t pathNum);
380 
381 /*
382  * Set the log implementation
383  */
384 NSTACKX_EXPORT int32_t NSTACKX_DFileRegisterLog(DFileLogImpl logImpl);
385 
386 /*
387  * Get/Set the DFILE capabilities
388  */
389 NSTACKX_EXPORT uint32_t NSTACKX_DFileGetCapabilities(void);
390 
391 NSTACKX_EXPORT int32_t NSTACKX_DFileSetCapabilities(uint32_t capabilities, uint32_t value);
392 
393 typedef void (*DFileDumpFunc)(void *softObj, const char *data, uint32_t len);
394 
395 NSTACKX_EXPORT int32_t NSTACKX_DFileDump(uint32_t argc, const char **arg, void *softObj, DFileDumpFunc dump);
396 
397 /* 软总线提供的回调支持多线程调用,事件的触发频率要求(表格整理出来,什么时候触发,触发频率) */
398 typedef void (*DFileEventFunc)(void *softObj, const DFileEvent *info);
399 
400 NSTACKX_EXPORT void NSTACKX_DFileSetEventFunc(void *softObj, DFileEventFunc func);
401 
402 typedef void (*DFileLogCallback)(const char *moduleName, uint32_t logLevel, const char *format, ...);
403 
404 /*
405  * Set the DFile log implementation
406  */
407 NSTACKX_EXPORT int32_t NSTACKX_DFileRegisterLogCallback(DFileLogCallback userLogCallback);
408 NSTACKX_EXPORT void NSTACKX_DFileRegisterDefaultLog(void);
409 
410 /**
411  * get DFILE_ON_CLEAR_POLICY_FILE_LIST event callback.
412  * @brief Gets file list with file state
413  * @param[in] sessionId the session id of the session
414  * @return 0 on success, negative value on failure
415  */
416 NSTACKX_EXPORT int32_t NSTACKX_DFileSessionGetFileList(int32_t sessionId);
417 
418 typedef enum {
419     /* the priority of socket, value is same as IP_TOS, vallen is siezeof(uint8_t) */
420     OPT_TYPE_SOCK_PRIO,
421     OPT_TYPE_BUTT
422 } DFileOptType;
423 
424 typedef struct {
425     DFileOptType optType;
426     uint32_t valLen; /* length of value */
427     uint64_t value;  /* the option value, could be a pointer */
428 } DFileOpt;
429 
430 /*
431  * set dfile session opt
432  * @brief Sets DFile session options. for client session, Recommend to configure after DFILE_ON_CONNECT_SUCCESS.
433  * @param[in] sessionId the session id of the session
434  * @param[in] opt option tlv
435  * @return 0 on success, negative value on failure
436  */
437 NSTACKX_EXPORT int32_t NSTACKX_DFileSetSessionOpt(int32_t sessionId, const DFileOpt *opt);
438 #ifdef __cplusplus
439 }
440 #endif
441 
442 #endif  /* #ifndef NSTACKX_DFILE_H */
443