xref: /nrf52832-nimble/rt-thread/components/net/sal_socket/impl/af_inet_lwip.c (revision 104654410c56c573564690304ae786df310c91fc)
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