1 /*
2 * Copyright (c) 2006-2018, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2018-05-17 ChenYong First version
9 */
10
11 #include <rtthread.h>
12
13 #include <lwip/sockets.h>
14 #include <lwip/netdb.h>
15 #include <lwip/api.h>
16 #include <lwip/init.h>
17
18 #ifdef SAL_USING_POSIX
19 #include <dfs_poll.h>
20 #endif
21
22 #include <sal.h>
23 #include <af_inet.h>
24
25 #if LWIP_VERSION < 0x2000000
26 #define SELWAIT_T int
27 #else
28 #ifndef SELWAIT_T
29 #define SELWAIT_T u8_t
30 #endif
31 #endif
32
33 #ifdef SAL_USING_LWIP
34
35 #ifdef SAL_USING_POSIX
36
37 #if LWIP_VERSION >= 0x20100ff
38 #include <lwip/priv/sockets_priv.h>
39 #else /* LWIP_VERSION < 0x20100ff */
40 /*
41 * Re-define lwip socket
42 *
43 * NOTE: please make sure the definitions same in lwip::net_socket.c
44 */
45 struct lwip_sock {
46 /** sockets currently are built on netconns, each socket has one netconn */
47 struct netconn *conn;
48 /** data that was left from the previous read */
49 void *lastdata;
50 /** offset in the data that was left from the previous read */
51 u16_t lastoffset;
52 /** number of times data was received, set by event_callback(),
53 tested by the receive and select functions */
54 s16_t rcvevent;
55 /** number of times data was ACKed (free send buffer), set by event_callback(),
56 tested by select */
57 u16_t sendevent;
58 /** error happened for this socket, set by event_callback(), tested by select */
59 u16_t errevent;
60 /** last error that occurred on this socket */
61 #if LWIP_VERSION < 0x2000000
62 int err;
63 #else
64 u8_t err;
65 #endif
66 /** counter of how many threads are waiting for this socket using select */
67 SELWAIT_T select_waiting;
68
69 rt_wqueue_t wait_head;
70 };
71 #endif /* LWIP_VERSION >= 0x20100ff */
72
73 extern struct lwip_sock *lwip_tryget_socket(int s);
74
event_callback(struct netconn * conn,enum netconn_evt evt,u16_t len)75 static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
76 {
77 int s;
78 struct lwip_sock *sock;
79 uint32_t event = 0;
80 SYS_ARCH_DECL_PROTECT(lev);
81
82 LWIP_UNUSED_ARG(len);
83
84 /* Get socket */
85 if (conn)
86 {
87 s = conn->socket;
88 if (s < 0)
89 {
90 /* Data comes in right away after an accept, even though
91 * the server task might not have created a new socket yet.
92 * Just count down (or up) if that's the case and we
93 * will use the data later. Note that only receive events
94 * can happen before the new socket is set up. */
95 SYS_ARCH_PROTECT(lev);
96 if (conn->socket < 0)
97 {
98 if (evt == NETCONN_EVT_RCVPLUS)
99 {
100 conn->socket--;
101 }
102 SYS_ARCH_UNPROTECT(lev);
103 return;
104 }
105 s = conn->socket;
106 SYS_ARCH_UNPROTECT(lev);
107 }
108
109 sock = lwip_tryget_socket(s);
110 if (!sock)
111 {
112 return;
113 }
114 }
115 else
116 {
117 return;
118 }
119
120 SYS_ARCH_PROTECT(lev);
121 /* Set event as required */
122 switch (evt)
123 {
124 case NETCONN_EVT_RCVPLUS:
125 sock->rcvevent++;
126 break;
127 case NETCONN_EVT_RCVMINUS:
128 sock->rcvevent--;
129 break;
130 case NETCONN_EVT_SENDPLUS:
131 sock->sendevent = 1;
132 break;
133 case NETCONN_EVT_SENDMINUS:
134 sock->sendevent = 0;
135 break;
136 case NETCONN_EVT_ERROR:
137 sock->errevent = 1;
138 break;
139 default:
140 LWIP_ASSERT("unknown event", 0);
141 break;
142 }
143
144 #if LWIP_VERSION >= 0x20100ff
145 if ((void*)(sock->lastdata.pbuf) || (sock->rcvevent > 0))
146 #else
147 if ((void*)(sock->lastdata) || (sock->rcvevent > 0))
148 #endif
149 event |= POLLIN;
150 if (sock->sendevent)
151 event |= POLLOUT;
152 if (sock->errevent)
153 event |= POLLERR;
154
155 SYS_ARCH_UNPROTECT(lev);
156
157 if (event)
158 {
159 rt_wqueue_wakeup(&sock->wait_head, (void*) event);
160 }
161 }
162 #endif /* SAL_USING_POSIX */
163
inet_socket(int domain,int type,int protocol)164 static int inet_socket(int domain, int type, int protocol)
165 {
166 #ifdef SAL_USING_POSIX
167 int socket;
168
169 socket = lwip_socket(domain, type, protocol);
170 if (socket >= 0)
171 {
172 struct lwip_sock *lwsock;
173
174 lwsock = lwip_tryget_socket(socket);
175 lwsock->conn->callback = event_callback;
176
177 rt_wqueue_init(&lwsock->wait_head);
178 }
179
180 return socket;
181 #else
182 return lwip_socket(domain, type, protocol);
183 #endif /* SAL_USING_POSIX */
184 }
185
inet_accept(int socket,struct sockaddr * addr,socklen_t * addrlen)186 static int inet_accept(int socket, struct sockaddr *addr, socklen_t *addrlen)
187 {
188 #ifdef SAL_USING_POSIX
189 int new_socket;
190
191 new_socket = lwip_accept(socket, addr, addrlen);
192 if (new_socket >= 0)
193 {
194 struct lwip_sock *lwsock;
195
196 lwsock = lwip_tryget_socket(new_socket);
197
198 rt_wqueue_init(&lwsock->wait_head);
199 }
200
201 return new_socket;
202 #else
203 return lwip_accept(socket, addr, addrlen);
204 #endif /* SAL_USING_POSIX */
205 }
206
inet_getsockname(int socket,struct sockaddr * name,socklen_t * namelen)207 static int inet_getsockname(int socket, struct sockaddr *name, socklen_t *namelen)
208 {
209 #if LWIP_VERSION_MAJOR < 2U
210 rt_kprintf("ERROR: Your lwIP version is not supported. Please using lwIP 2.0.0+.\n");
211 RT_ASSERT(LWIP_VERSION_MAJOR >= 2U);
212 #endif
213
214 return lwip_getsockname(socket, name, namelen);
215 }
216
217 #ifdef SAL_USING_POSIX
inet_poll(struct dfs_fd * file,struct rt_pollreq * req)218 static int inet_poll(struct dfs_fd *file, struct rt_pollreq *req)
219 {
220 int mask = 0;
221 struct lwip_sock *sock;
222 struct sal_socket *sal_sock;
223
224 sal_sock = sal_get_socket((int) file->data);
225 if(!sal_sock)
226 {
227 return -1;
228 }
229
230 sock = lwip_tryget_socket((int)sal_sock->user_data);
231 if (sock != NULL)
232 {
233 rt_base_t level;
234
235 rt_poll_add(&sock->wait_head, req);
236
237 level = rt_hw_interrupt_disable();
238
239 #if LWIP_VERSION >= 0x20100ff
240 if ((void*)(sock->lastdata.pbuf) || sock->rcvevent)
241 #else
242 if ((void*)(sock->lastdata) || sock->rcvevent)
243 #endif
244 {
245 mask |= POLLIN;
246 }
247 if (sock->sendevent)
248 {
249 mask |= POLLOUT;
250 }
251 if (sock->errevent)
252 {
253 mask |= POLLERR;
254 }
255 rt_hw_interrupt_enable(level);
256 }
257
258 return mask;
259 }
260 #endif
261
262 static const struct sal_socket_ops lwip_socket_ops =
263 {
264 inet_socket,
265 lwip_close,
266 lwip_bind,
267 lwip_listen,
268 lwip_connect,
269 inet_accept,
270 (int (*)(int, const void *, size_t, int, const struct sockaddr *, socklen_t))lwip_sendto,
271 (int (*)(int, void *, size_t, int, struct sockaddr *, socklen_t *))lwip_recvfrom,
272 lwip_getsockopt,
273 //TODO fix on 1.4.1
274 lwip_setsockopt,
275 lwip_shutdown,
276 lwip_getpeername,
277 inet_getsockname,
278 lwip_ioctl,
279 #ifdef SAL_USING_POSIX
280 inet_poll,
281 #endif
282 };
283
inet_create(struct sal_socket * socket,int type,int protocol)284 static int inet_create(struct sal_socket *socket, int type, int protocol)
285 {
286 RT_ASSERT(socket);
287
288 //TODO Check type & protocol
289
290 socket->ops = &lwip_socket_ops;
291
292 return 0;
293 }
294
295 static struct sal_proto_ops lwip_proto_ops =
296 {
297 lwip_gethostbyname,
298 lwip_gethostbyname_r,
299 lwip_getaddrinfo,
300 lwip_freeaddrinfo,
301 };
302
303 static const struct sal_proto_family lwip_inet_family =
304 {
305 AF_INET,
306 AF_INET,
307 inet_create,
308 &lwip_proto_ops,
309 };
310
lwip_inet_init(void)311 int lwip_inet_init(void)
312 {
313 sal_proto_family_register(&lwip_inet_family);
314
315 return 0;
316 }
317 INIT_COMPONENT_EXPORT(lwip_inet_init);
318
319 #endif /* SAL_USING_LWIP */
320