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_TRANSFER_H
17 #define NSTACKX_DFILE_TRANSFER_H
18
19 #include <stdint.h>
20 #include <stdio.h>
21 #include "nstackx_list.h"
22 #include "nstackx_dfile.h"
23 #include "nstackx_util.h"
24 #include "nstackx_file_list.h"
25 #include "nstackx_dfile_frame.h"
26 #include "nstackx_file_manager.h"
27 #include "nstackx_dfile_config.h"
28 #include "nstackx_timer.h"
29 #include "nstackx_dev.h"
30
31 #define DFILE_SHOW_RECEIVE_TIME 1
32 #define NSTACKX_RETRY_HISTORY_DATA_ARRAY_SIZE 6
33 #define INTEGRAL_TIME 2
34
35 typedef enum {
36 DFILE_TRANS_MSG_FILE_SEND_DATA,
37 DFILE_TRANS_MSG_FILE_LIST_RECEIVED,
38 DFILE_TRANS_MSG_FILE_RECEIVED, /* Receiver receive all the file data */
39 DFILE_TRANS_MSG_FILE_RECEIVE_FAIL,
40 DFILE_TRANS_MSG_FILE_RECEIVED_TO_FAIL,
41 DFILE_TRANS_MSG_FILE_SENT, /* Sender send TRANSFER DONE ACK frame and come to end */
42 DFILE_TRANS_MSG_FILE_SEND_FAIL,
43 DFILE_TRANS_MSG_IN_PROGRESS,
44 DFILE_TRANS_MSG_FILE_SEND_ACK,
45 DFILE_TRANS_MSG_END,
46 } DFileTransMsgType;
47
48 typedef enum {
49 DFILE_TRANS_NO_ERROR = 0,
50 DFILE_TRANS_SOCKET_ERROR, /* Socket IO error */
51 DFILE_TRANS_INTERNAL_ERROR, /* Internal error, such as no memory. */
52 /* For sender */
53 DFILE_TRANS_FILE_HEADER_CONFIRM_TIMEOUT, /* Wait for HEADER CONFIRM frame timeout */
54 DFILE_TRANS_FILE_DATA_ACK_TIMEOUT, /* Heart beat (DATA ACK frame) timeout */
55 DFILE_TRANS_TRANSFER_DONE_TIMEOUT, /* Wait for TRANSFER DONE frame timeout */
56 /* For receiver */
57 DFILE_TRANS_FILE_HEADER_TIMEOUT, /* Receive HEADER frame timeout (partially received) */
58 DFILE_TRANS_FILE_DATA_TIMEOUT, /* Receive file data timeout (partially received) */
59 /* Receiver wait for TRANSFER DONE ACK frame timeout, for debug purpose, won't report to user */
60 DFILE_TRANS_TRANSFER_DONE_ACK_TIMEOUT,
61 DFILE_TRANS_FILE_SEND_TASK_ERROR, /* Send task error */
62 DFILE_TRANS_FILE_RECEIVE_TASK_ERROR, /* Receive task error */
63 DFILE_TRANS_FILE_WRITE_FAIL, /* Write file list fail */
64 DFILE_TRANS_FILE_RENAME_FAIL, /* Rename file fail */
65 } DFileTransErrorCode;
66
67 typedef enum {
68 STATE_SEND_FILE_INIT = 0,
69 STATE_SEND_FILE_HEADER_ONGOING,
70 STATE_WAIT_FOR_FILE_HEADER_CONFIRM,
71 STATE_SEND_FILE_DATA_ONGOING,
72 STATE_WAIT_FOR_FILE_TRANSFER_DONE_FRAME,
73 STATE_SEND_FILE_TRANSFER_DONE_ACK,
74 STATE_SEND_FILE_DONE,
75 STATE_SEND_FILE_FAIL,
76 } DFileSendState;
77
78 typedef enum {
79 STATE_RECEIVE_FILE_INIT = 0,
80 STATE_RECEIVE_FILE_HEADER_ONGOING,
81 STATE_SEND_FILE_HEADER_CONFIRM,
82 STATE_RECEIVE_FILE_DATA_ONGOING,
83 STATE_SEND_FILE_DATA_ACK,
84 STATE_SEND_FILE_TRANSFER_DONE,
85 STATE_WAIT_FOR_FILE_TRANSFER_DONE_ACK,
86 STATE_RECEIVE_FILE_DONE,
87 STATE_RECEIVE_FILE_FAIL,
88 } DFileReceiveState;
89
90 struct DFileTrans;
91 /* Reuse DFileMsg for ease use */
92 typedef DFileMsg DFileTransMsg;
93
94 typedef int32_t (*DFileTransWriteHandle)(const uint8_t *frame, size_t len, void *context);
95 typedef void (*DFileTransMsgReceiver)(struct DFileTrans *dFileTrans, DFileTransMsgType msgType, DFileTransMsg *msg);
96
97 typedef struct {
98 uint16_t lastRetranFileId;
99 uint32_t lastRetranFileSequence;
100 uint32_t sameRetraLostBlocks;
101 uint8_t lastRetranLevel;
102 } RetranFileRecord;
103
104 typedef struct DFileTrans {
105 List list;
106 uint16_t transId;
107 uint8_t isSender;
108 DFileSendState sendState;
109 DFileReceiveState recvState;
110 /* members for sending file */
111 int32_t lastSentHeaderFileId;
112 uint8_t headerRetryCnt;
113 uint8_t lostAckCnt;
114 uint8_t fileTransferReqReceived; /* Flag: Receive File Transfer REQ frame */
115 uint8_t fileTransferDoneReceived; /* Flag: Receive File Transfer Done frame */
116 uint8_t *remainDataFrame;
117
118 /* members for receiving file */
119 uint16_t lastAckedHeaderFileId;
120 uint16_t lastFileDataRecvFileId;
121 uint32_t lastFileDataSequence;
122 uint16_t prefileId;
123 uint32_t preSequence;
124 uint16_t haveRetransFilefileId;
125 uint32_t haveRetransFilepreSequence;
126 struct timespec retryAllPacketTs;
127 struct timespec heartBeatTs;
128 uint8_t headerAckRetryCnt;
129 uint8_t idleTimeoutCnt;
130 uint8_t allFileNameReceived;
131 uint8_t dupFileName;
132 uint8_t allFileDataReceived;
133 uint8_t fileTransferDoneAcked;
134 uint8_t transferDoneRetryCnt;
135 uint8_t recvPacketFlag;
136 uint8_t retransFileFlag;
137 /* members for data lost and retry */
138 List retryList;
139 List *retryPointer;
140 uint32_t retryCount;
141 uint32_t allRetryCount;
142 uint32_t allRetrySendCount;
143 uint32_t shouldSendAck;
144 uint32_t shouldSendAckDividor;
145 #if DFILE_SHOW_RECEIVE_TIME
146 struct timespec startTs;
147 #endif
148
149 uint64_t totalDataFrameCnt;
150 uint64_t receivedDataFrameCnt;
151 uint64_t adjustAckIntervalLimit;
152 uint32_t ackInterval;
153 uint32_t transRetryCount;
154 uint32_t notInsertCount;
155
156 uint16_t connType;
157 DFileTransConfig config;
158 DFileTransErrorCode errorCode;
159 struct timespec ts;
160 uint32_t timeout;
161 uint8_t fileManagerTaskStarted;
162 uint8_t sendBuffer[NSTACKX_MAX_FRAME_SIZE];
163 size_t sendBufferLength;
164 uint16_t mtu;
165 FileList *fileList;
166 FileManager *fileManager;
167 DFileTransWriteHandle writeHandle;
168 DFileTransMsgReceiver msgReceiver;
169 void *context;
170 DFileSession *session;
171 uint8_t isRecvSucMsgNotified;
172 uint64_t bytesTransferredLastRecord; /* just usefully for receiver */
173 uint64_t bytesTransferred; /* just usefully for receiver */
174 uint64_t totalBytes; /* just usefully for receiver */
175 uint8_t isAckSend;
176 uint8_t recvLastFramePrint;
177 uint8_t adjustAckIntervalLimitPrint;
178 uint64_t recvBlockListFullTimes;
179 uint8_t adjustToLastFrameAckInterval;
180 OnDFileRenameFile onRenameFile;
181 uint32_t recvCount;
182 uint8_t sendRetransFileCount;
183 uint8_t ioWriteFinishFlag;
184 uint32_t backPressureBypassCnt;
185 } DFileTrans;
186
187 typedef struct {
188 uint8_t isSender;
189 uint16_t transId;
190 FileManager *fileManager;
191 ConnectType connType;
192 DFileTransWriteHandle writeHandle;
193 DFileTransMsgReceiver msgReceiver;
194 void *context;
195 DFileSession *session;
196 OnDFileRenameFile onRenameFile;
197 } DFileTransPara;
198
199 typedef enum SettingState {
200 SETTING_NEGOTIATING = 0,
201 SETTING_NEGOTIATED
202 } SettingState;
203
204 typedef struct PeerInfo {
205 List list;
206 struct sockaddr_in dstAddr;
207 char localInterfaceName[IFNAMSIZ];
208 uint16_t localMtu;
209 uint16_t mtu;
210 uint16_t mtuInuse;
211 uint16_t dataFrameSize;
212 uint16_t connType;
213 SettingState state;
214 DFileSession *session;
215 Timer *settingTimer;
216 uint8_t settingTimeoutCnt;
217 uint8_t socketIndex;
218 int32_t remoteSessionId;
219 uint64_t overRun;
220 struct PeerInfo *brotherPeer;
221
222 /* congestion control info */
223 WifiStationInfo rxWifiStationInfo; /* save the bitrate of the server endian to calculate the sendrate */
224 int8_t rxWifiStationInfoStatus;
225 double integralLossRate[INTEGRAL_TIME];
226 uint32_t fastStartCounter;
227 /* qdisc info */
228 uint16_t qdiscMaxLeft;
229 uint16_t qdiscMinLeft;
230 uint32_t qdiscSearchNum;
231 uint32_t qdiscAveLeft;
232
233 FlowCtrlInfo flowCtrlInfo; /* flow control info */
234
235 struct timespec startTime;
236 uint32_t sendCount;
237 uint32_t sendCountRateMB;
238 uint16_t sendRate;
239 uint16_t maxSendRate;
240 uint32_t sendFrameRate;
241 uint32_t intervalSendCount;
242 int32_t amendSendRate;
243 uint8_t decreaseStatus;
244
245 uint32_t eAgainCount;
246 struct timespec measureBefore;
247 struct timespec ackDropTimer;
248 uint32_t maxRetryCountPerSec;
249 uint32_t maxRetryCountLastSec;
250
251 uint32_t recvCount;
252 uint32_t recvFrameRate;
253 uint32_t recvCountRateMB;
254 uint32_t allDtransRetryCount;
255
256 uint32_t retryCountHistoryData[NSTACKX_RETRY_HISTORY_DATA_ARRAY_SIZE];
257 uint16_t sendRateHistoryData[NSTACKX_RETRY_HISTORY_DATA_ARRAY_SIZE];
258 uint16_t recvRateHistoryData[NSTACKX_RETRY_HISTORY_DATA_ARRAY_SIZE];
259 uint16_t locationHistoryData;
260 uint16_t ackInterval;
261 uint32_t rateStateInterval;
262 uint16_t sendAckNum;
263 uint32_t remoteDFileVersion;
264 uint8_t gotWifiRate;
265 uint32_t linkSequence;
266 uint32_t lastMaxSeq;
267 uint32_t lastTimes;
268 uint32_t duplicateCount;
269 uint32_t currentTransCount;
270 } PeerInfo;
271
ClearPeerinfoStats(PeerInfo * peerInfo)272 static inline void ClearPeerinfoStats(PeerInfo *peerInfo)
273 {
274 peerInfo->sendCount = 0;
275 peerInfo->qdiscMinLeft = 0;
276 peerInfo->qdiscMaxLeft = 0;
277 peerInfo->qdiscAveLeft = 0;
278 peerInfo->qdiscSearchNum = 0;
279 }
280
281 int32_t DFileTransSendFiles(DFileTrans *trans, FileListInfo *fileListInfo);
282 int32_t DFileTransAddExtraInfo(DFileTrans *trans, uint16_t pathType, uint8_t noticeFileNameType, char *userData);
283 int32_t HandleDFileFrame(DFileTrans *dFileTrans, DFileFrame *dFileFrame);
284 void DFileTransProcess(DFileTrans *dFileTrans);
285 int64_t DFileTransGetTimeout(DFileTrans *dFileTrans);
286 int32_t DFileTransSetMtu(DFileTrans *dFileTrans, uint16_t mtu);
287
288 DFileTrans *DFileTransCreate(const DFileTransPara *para);
289 void DFileTransDestroy(DFileTrans *dFileTrans);
290 void DFileTransDestroyInner(DFileTrans *dFileTrans);
291 uint64_t DFileTransGetTotalBytes(const DFileTrans *dFileTrans);
292 void FileManagerReceiverMsgHandler(uint16_t fileId, FileManagerMsgType msgType, FileManagerMsg *msg,
293 DFileTrans *dFileTrans);
294 void FileManagerSenderMsgHandler(uint16_t fileId, FileManagerMsgType msgType, FileManagerMsg *msg,
295 DFileTrans *dFileTrans);
296 int32_t SendFrame(DFileTrans *dFileTrans, uint8_t *frame, size_t frameLength, DFileSendState *nextSend,
297 DFileReceiveState *nextRecv);
298 void ReviewSuccessMsg(const DFileTrans *dFileTrans, DFileTransMsgType *msgType,
299 DFileTransMsg *msg, char *files[]);
300 #endif /* NSTACKX_DFILE_TRANSFER_H */
301