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_SESSION_H
17 #define NSTACKX_DFILE_SESSION_H
18 #include "nstackx_event.h"
19 #include "nstackx_socket.h"
20 #include "nstackx_file_manager.h"
21 #include "nstackx_dfile_transfer.h"
22 #include "nstackx_dfile_private.h"
23 #include "nstackx_timer.h"
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
27
28 #define MAX_EPOLL_SIZE 128
29 #define MAX_PEERINFO_SIZE 10
30 #define MAX_SEND_TRANSFERDONE_ACK_FRAME_COUNT 14
31 #define MAX_TRANSFERDONE_ACK_NODE_COUNT 100
32 #define MAX_TRANSTATELISTSIZE 100
33
34 typedef enum {
35 DFILE_SESSION_TYPE_CLIENT = 1,
36 DFILE_SESSION_TYPE_SERVER,
37 } DFileSessionType;
38
39 typedef struct {
40 List list;
41 uint32_t sendLen;
42 uint8_t *frame;
43 size_t length;
44 struct sockaddr_in peerAddr;
45 uint8_t socketIndex;
46 } QueueNode;
47
48 typedef struct {
49 pthread_t senderTid;
50 sem_t sendWait;
51 sem_t semNewCycle;
52 } SendThreadPara;
53
54 typedef struct {
55 List entry;
56 void *addr;
57 size_t len;
58 } IovList;
59
60 typedef struct {
61 List list;
62 uint16_t transId;
63 uint16_t sendNum;
64 } TransferDoneAckNode;
65
66 typedef struct {
67 uint8_t isWorking;
68 uint16_t transId;
69 PeerInfo *peerInfo;
70 } TransSlot;
71
72 struct DFileSession {
73 List list;
74 uint16_t sessionId; /* reserve for multi session */
75 DFileSessionType sessionType;
76 SocketProtocol protocol;
77 Socket *socket[NSTACKX_MULTI_PATH_NUM];
78 Socket *acceptSocket;
79 pthread_t tid;
80 EpollDesc epollfd;
81 List eventNodeChain;
82 uint8_t closeFlag;
83 uint32_t vtransDefaultSize;
84 List vtransManagerList;
85 pthread_mutex_t transIdLock;
86 BindType bindType;
87 DFileMsgReceiver msgReceiver;
88 OnDFileRenameFile onRenameFile;
89 uint16_t lastDFileTransId; /* for client, server will use client trans id */
90 List dFileTransChain;
91 List peerInfoChain;
92 MutexList transferDoneAckList; /* DATA:FileListTask */
93 uint32_t peerInfoCnt;
94 FileManager *fileManager;
95 pthread_t senderTid[NSTACKX_MULTI_PATH_NUM];
96 SendThreadPara sendThreadPara[NSTACKX_MAX_CLIENT_SEND_THREAD_NUM];
97 uint8_t addiSenderCloseFlag;
98 pthread_t receiverTid;
99 pthread_t controlTid;
100 List outboundQueue;
101 List inboundQueue;
102 pthread_mutex_t outboundQueueLock;
103 pthread_mutex_t inboundQueueLock;
104 sem_t outboundQueueWait[NSTACKX_MULTI_PATH_NUM];
105 uint64_t outboundQueueSize;
106 uint64_t inboundQueueSize;
107 List pendingFileLists;
108 #ifdef NSTACKX_SMALL_FILE_SUPPORT
109 List smallFileLists;
110 #endif
111 uint32_t fileListProcessingCnt;
112 uint32_t fileListPendingCnt;
113 uint32_t smallListProcessingCnt;
114 #ifdef NSTACKX_SMALL_FILE_SUPPORT
115 uint32_t smallListPendingCnt;
116 #endif
117 /*
118 * Receiver thread is blocking at "select" most of time.
119 * This "receiverPipe" is used to unblock "select" and terminate receiver thread during NSTACKX_DFileClose(),
120 * decreasing the closing time.
121 */
122 struct timespec measureBefore;
123 PipeDesc receiverPipe[PIPE_FD_NUM];
124 uint64_t recvBlockNumDirect;
125 uint64_t recvBlockNumInner;
126 atomic_t totalSendBlocks;
127 atomic_t totalRecvBlocks;
128 uint8_t partReadFlag;
129 atomic_t sendBlockListEmptyTimes;
130 atomic_t noPendingDataTimes;
131 uint32_t sleepTimes;
132 uint16_t clientSendThreadNum;
133 uint8_t cycleRunning[2];
134 struct timespec startTs;
135 uint64_t bytesTransferred;
136 uint32_t transCount;
137 atomic_t unprocessedReadEventCount;
138 uint8_t mainLoopActiveReadFlag;
139 List freeIovList[NSTACKX_MAX_CLIENT_SEND_THREAD_NUM];
140 uint8_t transFlag;
141 uint32_t capability;
142 uint32_t internalCaps;
143 uint32_t capsCheck;
144 MutexList tranIdStateList;
145 uint32_t wlanCatagory;
146 TransSlot transSlot[NSTACKX_FILE_MANAGER_THREAD_NUM];
147 uint8_t *recvBuffer;
148 uint32_t recvLen;
149 uint8_t acceptFlag;
150 uint8_t sendRemain;
151 int32_t allTaskCount;
152 pthread_mutex_t backPressLock;
153 uint32_t stopSendCnt[NSTACKX_MAX_CLIENT_SEND_THREAD_NUM];
154 };
155
156 PeerInfo *CreatePeerInfo(DFileSession *session, const struct sockaddr_in *peerAddr,
157 uint16_t mtu, uint16_t connType, uint8_t socketIndex);
158 int32_t DFileWriteHandle(const uint8_t *frame, size_t len, void *context);
159 void NotifyMsgRecver(const DFileSession *session, DFileMsgType msgType, const DFileMsg *msg);
160 void TerminateMainThreadInner(void *arg);
161 void *DFileMainLoop(void *arg);
162 void *DFileSenderHandle(void *arg);
163 void *DFileReceiverHandle(void *arg);
164 void NotifyPipeEvent(const DFileSession *session);
165 int32_t CreateReceiverPipe(DFileSession *session);
166 int32_t CreateFileManager(DFileSession *session, const uint8_t *key, uint32_t keyLen, uint8_t isSender,
167 uint16_t connType);
168 int32_t DFileStartTrans(DFileSession *session, FileListInfo *fileListInfo);
169 int32_t StartDFileThreadsInner(DFileSession *session);
170 void DFileSessionSendSetting(PeerInfo *peerInfo);
171 void UpdateAllTransRetryCount(DFileSession *session, PeerInfo *peerInfo);
172 void CalculateSessionTransferRatePrepare(DFileSession *session);
173
174 void DestroyQueueNode(QueueNode *queueNode);
175 PeerInfo *ClientGetPeerInfoBySocketIndex(uint8_t socketIndex, const DFileSession *session);
176 void NoticeSessionProgress(DFileSession *session);
177 int32_t DFileSessionHandleReadBuffer(DFileSession *session, const uint8_t *buf, size_t bufLen,
178 struct sockaddr_in *peerAddr, uint8_t socketIndex);
179 int32_t DFileAcceptSocket(DFileSession *session);
180
181 int32_t WaitSocketEvent(const DFileSession *session, SocketDesc fd, uint32_t timeoutMs,
182 uint8_t *canRead, uint8_t *canWrite);
183
184 int32_t CheckFdSetSize(SocketDesc sock);
185 void DestroyReceiverPipe(DFileSession *session);
186
187 #define DFILE_SESSION_TERMINATE_FLAG 0x01
188 #define DFILE_SESSION_FATAL_FLAG 0x02
189
DFileSessionSetFatalFlag(struct DFileSession * session)190 static inline void DFileSessionSetFatalFlag(struct DFileSession *session)
191 {
192 session->closeFlag |= DFILE_SESSION_FATAL_FLAG;
193 }
194
DFileSessionSetTerminateFlag(struct DFileSession * session)195 static inline void DFileSessionSetTerminateFlag(struct DFileSession *session)
196 {
197 session->closeFlag |= DFILE_SESSION_TERMINATE_FLAG;
198 }
199
DFileSessionCheckFatalFlag(const struct DFileSession * session)200 static inline int32_t DFileSessionCheckFatalFlag(const struct DFileSession *session)
201 {
202 return session->closeFlag & DFILE_SESSION_FATAL_FLAG;
203 }
204
ClearSessionStats(struct DFileSession * session)205 static inline void ClearSessionStats(struct DFileSession *session)
206 {
207 session->sleepTimes = 0;
208 NSTACKX_ATOM_SET(&(session->sendBlockListEmptyTimes), 0);
209 NSTACKX_ATOM_SET(&(session->noPendingDataTimes), 0);
210 session->fileManager->sendListFullTimes = 0;
211 session->fileManager->iorBytes = 0;
212 }
213
CapsGSO(const struct DFileSession * session)214 static inline bool CapsGSO(const struct DFileSession *session)
215 {
216 return session->capability & NSTACKX_CAPS_UDP_GSO;
217 }
218
CapsLinkSeq(const struct DFileSession * session)219 static inline bool CapsLinkSeq(const struct DFileSession *session)
220 {
221 return session->capability & NSTACKX_CAPS_LINK_SEQUENCE;
222 }
223
CapsNoRW(const struct DFileSession * session)224 static inline bool CapsNoRW(const struct DFileSession *session)
225 {
226 return session->internalCaps & NSTACKX_INTERNAL_CAPS_NORW;
227 }
228
CapsTcp(const struct DFileSession * session)229 static inline bool CapsTcp(const struct DFileSession *session)
230 {
231 return ((session->capability & NSTACKX_CAPS_WLAN_CATAGORY) && (session->wlanCatagory == NSTACKX_WLAN_CAT_TCP));
232 }
233
CapsRecvFeedback(const struct DFileSession * session)234 static inline bool CapsRecvFeedback(const struct DFileSession *session)
235 {
236 return session->capsCheck & NSTACKX_INTERNAL_CAPS_RECV_FEEDBACK;
237 }
238
CapsChaCha(const struct DFileSession * session)239 static inline bool CapsChaCha(const struct DFileSession *session)
240 {
241 return (session->fileManager->keyLen == CHACHA20_KEY_LENGTH) && (session->capability & NSTACKX_CAPS_CHACHA);
242 }
243
244 void NSTACKX_DFileAssembleFunc(void *softObj, const DFileEvent *info);
245 void DFileSetEvent(void *softObj, DFileEventFunc func);
246
247 #ifdef __cplusplus
248 }
249 #endif
250 #endif // NSTACKX_DFILE_SESSION_H
251