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