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 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 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 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 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 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 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 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