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