1 /*
2  * Copyright (C) 2022 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 FILLP_SOCKETS_H
17 #define FILLP_SOCKETS_H
18 #include "opt.h"
19 #include "queue.h"
20 #include "epoll.h"
21 #include "hlist.h"
22 #include "net.h"
23 
24 #ifdef FILLP_LINUX
25 #include <errno.h>
26 #elif defined(FILLP_WIN32)
27 #include <Winsock2.h>
28 #endif
29 
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33 
34 enum SockAllockState {
35     SOCK_ALLOC_STATE_FREE,
36     SOCK_ALLOC_STATE_ERR,
37 
38     SOCK_ALLOC_STATE_WAIT_TO_CLOSE, /* app has called SockClose */
39     SOCK_ALLOC_STATE_COMM,
40     SOCK_ALLOC_STATE_EPOLL,
41     SOCK_ALLOC_STATE_EPOLL_TO_CLOSE
42 };
43 
44 struct GlobalAppUdpRes {
45     FILLP_UINT32 txBurst; /* max pkt number to send each cycle */
46 #ifdef FILLP_64BIT_ALIGN
47     FILLP_UINT32 reserve;
48 #endif
49 };
50 
51 struct GlobalAppCommon {
52     FILLP_UINT32 keepAliveTime; /* ms */
53     FILLP_UINT32 maxServerAllowSendCache;
54     FILLP_UINT32 maxServerAllowRecvCache;
55     FILLP_UINT32 udpSendBufSize;
56     FILLP_UINT32 recvBufSize;
57     FILLP_UINT32 disconnectRetryTimeout; /* Testability addition in the code it is 100. */
58     FILLP_UINT32 sendCache;              /* size of send cache */
59     FILLP_UINT32 recvCache;              /* size of recv cache  */
60     FILLP_UINT32 connectTimeout;         /* seconds */
61     FILLP_UINT16 reserve;                /* Now not used, need to remove it */
62     FILLP_UINT16 connRetryTimeout;       /* Testability addition in the code it is 10. */
63     FILLP_BOOL enableNackDelay;
64     FILLP_BOOL enlargePackIntervalFlag;
65     FILLP_BOOL enableDateOptTimestamp;
66     FILLP_UCHAR pad[3];
67     FILLP_LLONG nackDelayTimeout;
68     FILLP_UINT32 fcStasticsInterval;
69 };
70 
71 struct GlobalAppFlowControl {
72     FILLP_UINT32 maxRate; /* maximum data sending rate */
73     FILLP_UINT32 maxRecvRate;
74     FILLP_UINT32 oppositeSetRate; /* Only for Server */
75     FILLP_UINT32 packInterval;    /* us */
76     FILLP_UINT16 pktSize;         /* default pkt size to cal flow rate */
77     FILLP_BOOL slowStart;
78     FILLP_BOOL constRateEnbale;
79     FILLP_UCHAR reserve[4];
80 };
81 
82 struct GlobalAppResource {
83     struct GlobalAppUdpRes udp;
84     struct GlobalAppCommon common;
85     struct GlobalAppFlowControl flowControl;
86 };
87 
88 #define MAX_SPUNGE_TYPE_NUM 24 /* Check with SpungeMsgType it shopuld be more than max elements in this enum */
89 
90 struct FtSocket {
91     FILLP_INT index;      /* index of table */
92     FILLP_INT allocState; /* socket has been allocState */
93     struct FtNetconn *netconn;
94     /* These following members are used for connection and referenced by FtNetconn */
95     FILLP_INT coreErrType[MAX_SPUNGE_TYPE_NUM];
96 
97     struct HlistNode listenNode;
98     FILLP_INT listenBacklog;
99     SYS_ARCH_SEM acceptSem;
100     FillpQueue *acceptBox;
101 
102     void *recvPktBuf;
103     struct SpungeInstance *inst;
104     void *traceHandle; /* Handle provided by FillpTrace callback */
105 
106     struct EventPoll *eventEpoll;
107     SysArchAtomic rcvEvent;
108     SysArchAtomic sendEvent;
109     SysArchAtomic sendEventCount;
110     SysArchAtomic epollWaiting;
111     FILLP_UINT32 errEvent;
112 
113     struct Hlist epTaskList;
114     SYS_ARCH_SEM epollTaskListLock;
115 
116     /* It means, that A ft-socket can be registered up to 10 epoll instances, not
117        more than that. This value is compile config controlled, App can
118        increase the number if expects more epoll instances for its user application
119     */
120     FILLP_INT associatedEpollInstanceArr[FILLP_NUM_OF_EPOLL_INSTANCE_SUPPORTED];
121     FILLP_UINT32 associatedEpollInstanceIdx;
122 
123     FILLP_UINT32 offset;
124     FILLP_UINT16 dataOptionFlag;
125     FILLP_UINT16 dataOptionSize;
126     FILLP_LLONG jitter;
127     FILLP_LLONG transmit;
128 
129     FILLP_UINT16 sockAddrType;
130     FILLP_INT socketType;     // get from SockSocket
131     FILLP_INT socketProtocol; // get from SockSocket
132     FILLP_UINT16 flags;
133 
134     FILLP_BOOL isListenSock;
135 
136     FILLP_UINT8 traceFlag; /* Flag for enable indication User/Network */
137     FILLP_INT freeTimeCount;
138     FILLP_BOOL isSockBind;
139     SYS_ARCH_SEM connBlockSem;     /* Used when do connect */
140     SYS_ARCH_RW_SEM sockConnSem;   /* Used to protect socket resource not freed */
141     SYS_ARCH_SEM sockCloseProtect; /* To make sure that only one close message posted to fillp thread */
142     FILLP_INT err;
143     struct GlobalAppResource resConf; /* Total size is 15 * sizeof uint32 */
144     FILLP_BOOL lingering;
145     struct linger fillpLinger;
146     FILLP_INT directlySend; /* directly send packet in the app thread instead of in the main thread */
147 };
148 
149 #define FILLP_SOCK_SET_ERR(sk, e) ((sk)->err = (e))
150 
SockEntryListenSocket(struct HlistNode * node)151 static __inline struct FtSocket *SockEntryListenSocket(struct HlistNode *node)
152 {
153     return (struct FtSocket *)((char *)(node) - (uintptr_t)(&(((struct FtSocket *)0)->listenNode)));
154 }
155 
156 #define SOCK_GET_SENDPKTPOOL(_sock) ((_sock)->netconn->pcb->fpcb.send.itemPool)
157 #define SOCK_GET_SENDBOX(_sock) ((_sock)->netconn->pcb->fpcb.send.unsendBox)
158 #define SOCK_GET_RECVBOX(_sock) ((_sock)->netconn->pcb->fpcb.recv.recvBox)
159 #define SOCK_GET_PKTSIZE(_sock) ((_sock)->netconn->pcb->fpcb.pktSize)
160 
161 #define SOCK_CONN_TRY_RDLOCK(_sock) SYS_ARCH_RWSEM_TRYRDWAIT(&(_sock)->sockConnSem)
162 #define SOCK_CONN_UNLOCK_RD(_sock) SYS_ARCH_RWSEM_RDPOST(&(_sock)->sockConnSem)
163 
164 #define SOCK_CONN_TRY_LOCK_CLOSE(_sock) SYS_ARCH_SEM_TRYWAIT(&(_sock)->sockCloseProtect)
165 #define SOCK_CONN_UNLOCK_CLOSE(_sock) SYS_ARCH_SEM_POST(&(_sock)->sockCloseProtect)
166 
167 #define SOCK_GET_SENDSEM(_sock) ((_sock)->netconn->pcb->fpcb.send.sendSem)
168 #define SOCK_GET_RECVSEM(_sock) ((_sock)->netconn->pcb->fpcb.recv.recvSem)
169 
170 #define SOCK_WAIT_SENDSEM(_sock) SYS_ARCH_SEM_WAIT(&SOCK_GET_SENDSEM(_sock))
171 #define SOCK_POST_SENDSEM(_sock) SYS_ARCH_SEM_POST(&SOCK_GET_SENDSEM(_sock))
172 #define SOCK_TRYWAIT_SENDSEM(_sock) SYS_ARCH_SEM_TRYWAIT(&SOCK_GET_SENDSEM(_sock))
173 
174 #define SOCK_WAIT_RECVSEM(_sock) SYS_ARCH_SEM_WAIT(&SOCK_GET_RECVSEM(_sock))
175 #define SOCK_POST_RECVSEM(_sock) SYS_ARCH_SEM_POST(&SOCK_GET_RECVSEM(_sock))
176 #define SOCK_TRYWAIT_RECVSEM(_sock) SYS_ARCH_SEM_TRYWAIT(&SOCK_GET_RECVSEM(_sock))
177 
178 #ifdef FILLP_LINUX
179 #if defined(FILLP_LW_LITEOS)
180 #define SOCK_SEND_CPU_PAUSE() FILLP_SLEEP_MS(10)
181 #else
182 #define SOCK_SEND_CPU_PAUSE() (void)FILLP_USLEEP(FILLP_CPU_PAUSE_TIME)
183 #endif
184 #else
185 #define SOCK_SEND_CPU_PAUSE() FILLP_SLEEP_MS(1)
186 #endif
187 
188 #if defined(FILLP_LW_LITEOS)
189 #define SOCK_RECV_CPU_PAUSE() FILLP_SLEEP_MS(10)
190 #else
191 #define SOCK_RECV_CPU_PAUSE() FILLP_SLEEP_MS(1)
192 #endif
193 
194 #ifdef FILLP_LINUX
195 #define EPOLL_CPU_PAUSE() (void)FILLP_USLEEP(FILLP_CPU_PAUSE_TIME)
196 #else
197 #define EPOLL_CPU_PAUSE() FILLP_SLEEP_MS(1)
198 #endif
199 
200 struct FtSocketTable {
201     FillpQueue *freeQueqe;
202     struct FtSocket **sockPool;
203     FILLP_INT size;
204     SysArchAtomic used;
205 };
206 
207 #ifdef FILLP_LINUX
208 #define SET_ERRNO(_errno) (errno = (_errno))
209 #elif defined(FILLP_WIN32)
210 #define SET_ERRNO(_errno) WSASetLastError(_errno)
211 #endif
212 
213 #ifdef FILLP_LINUX
214 #define FT_OS_GET_ERRNO errno
215 #elif defined(FILLP_WIN32)
216 #define FT_OS_GET_ERRNO WSAGetLastError()
217 #endif
218 
219 /* Should this netconn avoid blocking? */
220 #define SOCK_FLAG_NON_BLOCKING 0x0001
221 
222 /* Get the blocking status of netconn calls (@todo: write/send is missing) */
223 #define SOCK_IS_NONBLOCKING(sock) (((sock)->flags & SOCK_FLAG_NON_BLOCKING) != 0)
224 #define SOCK_IS_BLOCKING(sock) (((sock)->flags & SOCK_FLAG_NON_BLOCKING) == 0)
225 
226 /* Set the blocking status of FtSocket
227 
228     The flag (which contains the socket options is in FtSocket and NOT in netconn CB)
229     is in FtSocket structure, this is because: Application can set the socket to
230     nonblock just after calling FtSocket (before ft_connet/FtAccept), but the
231     netconn CB will be available only during FtConnect/FtAccept.
232 */
233 void SockSetNonblocking(struct FtSocket *sock, FILLP_INT val);
234 
235 struct NackDelayCfg {
236     FILLP_INT sockIndex;
237     FILLP_UINT32 nackCfgVal;
238     FILLP_LLONG nackDelayTimeout;
239 };
240 
241 FILLP_INT SysArchSetSockRcvbuf(FILLP_INT sock, FILLP_UINT size);
242 FILLP_INT SysArchSetSockSndbuf(FILLP_INT sock, FILLP_UINT size);
243 FILLP_INT SysArchSetSockBlocking(FILLP_INT sock, FILLP_BOOL blocking);
244 FILLP_INT SysSetThreadName(FILLP_CHAR *name, FILLP_UINT16 nameLen);
245 
246 #ifdef __cplusplus
247 }
248 #endif
249 
250 #endif /* FILLP_SOCKETS_H */