From 547f316821a3b24e028d539f7f48b5e3e5ba5c36 Mon Sep 17 00:00:00 2001
From: compile_success <980965867@qq.com>
Date: Wed, 19 Oct 2022 12:14:08 +0000
Subject: [PATCH] add epoll_create1 and accept4

---
 src/api/posix_api.c        |  1 +
 src/api/sockets.c          | 34 ++++++++++++++++++++++++++++++----
 src/include/lwip/sockets.h | 21 +++++++++++++++++++++
 src/include/posix_api.h    |  1 +
 4 files changed, 53 insertions(+), 4 deletions(-)

diff --git a/src/api/posix_api.c b/src/api/posix_api.c
index 6afb9c6..e721381 100644
--- a/src/api/posix_api.c
+++ b/src/api/posix_api.c
@@ -104,6 +104,7 @@ int posix_api_init(void)
     CHECK_DLSYM_RET_RETURN(posix_api->fcntl64_fn = dlsym(handle, "fcntl64"));
     CHECK_DLSYM_RET_RETURN(posix_api->pipe_fn = dlsym(handle, "pipe"));
     CHECK_DLSYM_RET_RETURN(posix_api->epoll_create_fn = dlsym(handle, "epoll_create"));
+    CHECK_DLSYM_RET_RETURN(posix_api->epoll_create1_fn = dlsym(handle, "epoll_create1"));
     CHECK_DLSYM_RET_RETURN(posix_api->epoll_ctl_fn = dlsym(handle, "epoll_ctl"));
     CHECK_DLSYM_RET_RETURN(posix_api->epoll_wait_fn = dlsym(handle, "epoll_wait"));
     CHECK_DLSYM_RET_RETURN(posix_api->fork_fn = dlsym(handle, "fork"));
diff --git a/src/api/sockets.c b/src/api/sockets.c
index 129f7cc..39376a5 100644
--- a/src/api/sockets.c
+++ b/src/api/sockets.c
@@ -583,10 +583,11 @@ get_socket_by_fd(int fd)
  * @param newconn the netconn for which to allocate a socket
  * @param accepted 1 if socket has been created by accept(),
  *                 0 if socket has been created by socket()
+ * @param flags  only support SOCK_CLOEXEC and SOCK_NONBLOCK
  * @return the index of the new socket; -1 on error
  */
 static int
-alloc_socket(struct netconn *newconn, int accepted)
+alloc_socket(struct netconn *newconn, int accepted, int flags)
 {
   int i;
   SYS_ARCH_DECL_PROTECT(lev);
@@ -610,12 +611,19 @@ alloc_socket(struct netconn *newconn, int accepted)
       break;
   }
 
+  /*add CLOEXEC OR NONBLOCK OR NONE*/
+  type |= flags;
+
   SYS_ARCH_PROTECT(lev);
   i = posix_api->socket_fn(domain, type, protocol);
   if (i == -1) {
     goto err;
   }
 
+  if ((flags & O_NONBLOCK) != 0){
+    netconn_set_nonblocking(newconn, flags & O_NONBLOCK);
+  }
+
   if ((i < LWIP_SOCKET_OFFSET) || (i >= sockets_num + LWIP_SOCKET_OFFSET)) {
     goto err;
   }
@@ -764,7 +772,7 @@ free_socket(struct lwip_sock *sock, int is_tcp)
  */
 
 int
-lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
+lwip_accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
 {
   struct lwip_sock *sock, *nsock;
   struct netconn *newconn;
@@ -797,7 +805,7 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
   }
   LWIP_ASSERT("newconn != NULL", newconn != NULL);
 
-  newsock = alloc_socket(newconn, 1);
+  newsock = alloc_socket(newconn, 1, flags);
   if (newsock == -1) {
     netconn_delete(newconn);
     set_errno(ENFILE);
@@ -869,6 +877,12 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
   return newsock;
 }
 
+int
+lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
+{
+  return lwip_accept4(s, addr, addrlen, 0);
+}
+
 int
 lwip_bind(int s, const struct sockaddr *name, socklen_t namelen)
 {
@@ -1868,6 +1882,10 @@ lwip_socket(int domain, int type, int protocol)
 
   LWIP_UNUSED_ARG(domain); /* @todo: check this */
 
+  int flags = type & ~SOCK_TYPE_MASK;
+  type &= SOCK_TYPE_MASK;
+
+
   /* create a netconn */
   switch (type) {
     case SOCK_RAW:
@@ -1907,7 +1925,15 @@ lwip_socket(int domain, int type, int protocol)
     return -1;
   }
 
-  i = alloc_socket(conn, 0);
+  if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)){
+    set_errno(EINVAL);
+    return -1;
+  }
+
+  if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
+    flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
+
+  i = alloc_socket(conn, 0, flags);
 
   if (i == -1) {
     netconn_delete(conn);
diff --git a/src/include/lwip/sockets.h b/src/include/lwip/sockets.h
index 1d63e8f..ca5bf6e 100644
--- a/src/include/lwip/sockets.h
+++ b/src/include/lwip/sockets.h
@@ -592,6 +592,7 @@ void lwip_socket_thread_cleanup(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: destro
 #if LWIP_COMPAT_SOCKETS == 2
 /* This helps code parsers/code completion by not having the COMPAT functions as defines */
 #define lwip_accept       accept
+#define lwip_accept4      accept4
 #define lwip_bind         bind
 #define lwip_shutdown     shutdown
 #define lwip_getpeername  getpeername
@@ -633,7 +634,25 @@ int fcntl(int s, int cmd, ...);
 #endif /* LWIP_POSIX_SOCKETS_IO_NAMES */
 #endif /* LWIP_COMPAT_SOCKETS == 2 */
 
+#ifndef O_CLOEXEC
+#define O_CLOEXEC       02000000
+#endif
+
+#ifndef SOCK_TYPE_MASK
+#define SOCK_TYPE_MASK  0xf
+#endif
+
+#ifndef SOCK_CLOEXEC
+#define SOCK_CLOEXEC    O_CLOEXEC
+#endif
+
+#ifndef SOCK_NONBLOCK
+#define SOCK_NONBLOCK   O_NONBLOCK
+#endif
+
+
 int lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
+int lwip_accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags);
 int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen);
 int lwip_shutdown(int s, int how);
 int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen);
@@ -680,6 +699,8 @@ int lwip_inet_pton(int af, const char *src, void *dst);
 /** @ingroup socket */
 #define accept(s,addr,addrlen)                    lwip_accept(s,addr,addrlen)
 /** @ingroup socket */
+#define accept4(s,addr,addrlen,flags)             lwip_accept4(s,addr,addrlen,flags)
+/** @ingroup socket */
 #define bind(s,name,namelen)                      lwip_bind(s,name,namelen)
 /** @ingroup socket */
 #define shutdown(s,how)                           lwip_shutdown(s,how)
diff --git a/src/include/posix_api.h b/src/include/posix_api.h
index c8f2cf9..e958ded 100644
--- a/src/include/posix_api.h
+++ b/src/include/posix_api.h
@@ -66,6 +66,7 @@ typedef struct {
     int (*fcntl64_fn)(int fd, int cmd, ...);
     int (*pipe_fn)(int pipefd[2]);
     int (*epoll_create_fn)(int size);
+    int (*epoll_create1_fn)(int size);
     int (*epoll_ctl_fn)(int epfd, int op, int fd, struct epoll_event *event);
     int (*epoll_wait_fn)(int epfd, struct epoll_event *events, int maxevents, int timeout);
     int (*epoll_close_fn)(int epfd);
-- 
2.33.0

