From c69045c50129a4fd5cc8936a78d04ed98119a4a6 Mon Sep 17 00:00:00 2001 From: Nikolay Arhipov Date: Tue, 26 Sep 2023 17:02:21 +0300 Subject: [PATCH] Implemented non-blocking pipe and socketpair --- newlib/libc/sys/vita/Makefile.am | 2 +- newlib/libc/sys/vita/pipe.c | 24 +++++++++++++ newlib/libc/sys/vita/socket.c | 57 +++++++++++++++++++++++++++++++ newlib/libc/sys/vita/sys/socket.h | 1 + newlib/libc/sys/vita/syscalls.c | 10 +++--- 5 files changed, 89 insertions(+), 5 deletions(-) diff --git a/newlib/libc/sys/vita/Makefile.am b/newlib/libc/sys/vita/Makefile.am index 585fd31c30..637a835b00 100755 --- a/newlib/libc/sys/vita/Makefile.am +++ b/newlib/libc/sys/vita/Makefile.am @@ -8,7 +8,7 @@ AM_CCASFLAGS = $(INCLUDES) noinst_LIBRARIES = lib.a -SOCKET_OBJS = accept.o bind.o connect.o getpeername.o getsockname.o getsockopt.o listen.o recv.o recvfrom.o recvmsg.o send.o sendto.o sendmsg.o setsockopt.o shutdown.o socket.o +SOCKET_OBJS = accept.o bind.o connect.o getpeername.o getsockname.o getsockopt.o listen.o recv.o recvfrom.o recvmsg.o send.o sendto.o sendmsg.o setsockopt.o shutdown.o socket.o socketpair.o DIRENT_OBJS = dirfd.o closedir.o opendir.o readdir.o readdir_r.o rewinddir.o scandir.o seekdir.o telldir.o NET_SOURCES = net/gethostbyaddr.c \ diff --git a/newlib/libc/sys/vita/pipe.c b/newlib/libc/sys/vita/pipe.c index bbad5578ef..d8713ed37d 100644 --- a/newlib/libc/sys/vita/pipe.c +++ b/newlib/libc/sys/vita/pipe.c @@ -28,7 +28,9 @@ DEALINGS IN THE SOFTWARE. #include #include #include +#include #include +#include #include #include @@ -75,4 +77,26 @@ int pipe(int pipefd[2]) pipefd[1] = fd2; return 0; +} + + +int pipe2(int pipefd[2], int flags) { + if (flags & O_NONBLOCK) { + if (socketpair(AF_INET, SOCK_STREAM, 0, pipefd) == -1) { + return -1; + } + + int val = 1; + if (setsockopt(pipefd[0], SOL_SOCKET, SO_NONBLOCK, &val, sizeof(val)) == -1 || + setsockopt(pipefd[1], SOL_SOCKET, SO_NONBLOCK, &val, sizeof(val)) == -1) { + + close(pipefd[0]); + close(pipefd[1]); + return -1; + } + + return 0; + } else { + return pipe(pipefd); + } } \ No newline at end of file diff --git a/newlib/libc/sys/vita/socket.c b/newlib/libc/sys/vita/socket.c index 4dfee9e784..1852771435 100644 --- a/newlib/libc/sys/vita/socket.c +++ b/newlib/libc/sys/vita/socket.c @@ -26,6 +26,8 @@ DEALINGS IN THE SOFTWARE. #include #include #include +#include +#include #include #include @@ -491,3 +493,58 @@ int socket(int domain, int type, int protocol) return s; } #endif + +#ifdef F_socket +int socketpair(int domain, int type, int protocol, int sockfds[2]) +{ + // Usually socketpair is used with AF_UNIX, simulate that with INET. + int listener; + if ((listener = socket(AF_INET, type, protocol)) == -1) { + return -1; + } + + struct sockaddr_in server_addr; + socklen_t addr_len = sizeof(struct sockaddr_in); + + memset(&server_addr, 0, sizeof(server_addr)); + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + server_addr.sin_port = 0; + + if (bind(listener, (struct sockaddr*)&server_addr, addr_len) == -1) { + close(listener); + return -1; + } + + if (listen(listener, 1) == -1) { + close(listener); + return -1; + } + + if (getsockname(listener, (struct sockaddr *)&server_addr, &addr_len) == -1) { + close(listener); + return -1; + } + + if ((sockfds[1] = socket(AF_INET, type, protocol)) == -1) { + close(listener); + return -1; + } + + if (connect(sockfds[1], (struct sockaddr*)&server_addr, addr_len) == -1) { + close(sockfds[1]); + close(listener); + return -1; + } + + if ((sockfds[0] = accept(listener, (struct sockaddr*)&server_addr, &addr_len)) == -1) { + close(sockfds[1]); + close(listener); + return -1; + } + + close(listener); + + return 0; +} +#endif diff --git a/newlib/libc/sys/vita/sys/socket.h b/newlib/libc/sys/vita/sys/socket.h index 116aa441ae..98763285ca 100644 --- a/newlib/libc/sys/vita/sys/socket.h +++ b/newlib/libc/sys/vita/sys/socket.h @@ -279,6 +279,7 @@ ssize_t sendmsg(int s, const struct msghdr *msg, int flags); int setsockopt(int, int, int, const void *, socklen_t); int shutdown(int, int); int socket(int, int, int); +int socketpair(int, int, int, int *); #ifdef __cplusplus } diff --git a/newlib/libc/sys/vita/syscalls.c b/newlib/libc/sys/vita/syscalls.c index 5f5fef0d38..3f3a5dd16a 100755 --- a/newlib/libc/sys/vita/syscalls.c +++ b/newlib/libc/sys/vita/syscalls.c @@ -54,8 +54,9 @@ _write_r(struct _reent * reent, int fd, const void *buf, size_t nbytes) { size_t len = nbytes; if (len > 4 * 4096) len = 4 * 4096; - ret = sceKernelSendMsgPipe(fdmap->sce_uid, buf, len, 1, NULL, NULL); - if (ret == 0) ret = len; + size_t p_res = 0; + ret = sceKernelSendMsgPipe(fdmap->sce_uid, buf, len, 1, &p_res, NULL); + if (ret == 0) ret = p_res; break; } } @@ -336,8 +337,9 @@ _read_r(struct _reent *reent, int fd, void *ptr, size_t len) { size_t rlen = len; if (rlen > 4 * 4096) rlen = 4 * 4096; - ret = sceKernelReceiveMsgPipe(fdmap->sce_uid, ptr, rlen, 1, NULL, NULL); - if (ret == 0) ret = rlen; + size_t p_res = 0; + ret = sceKernelReceiveMsgPipe(fdmap->sce_uid, ptr, rlen, 1, &p_res, NULL); + if (ret == 0) ret = p_res; break; } }