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