mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-11-01 06:58:22 +00:00
localsocket: fix cmsg
This commit is contained in:
@@ -196,7 +196,7 @@ int fd_clone(proc_t *targproc) {
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fd_insert(file_t *file, int *fdp) {
|
int fd_insert(file_t *file, int *fdp, int flags) {
|
||||||
proc_t *proc = current_thread()->proc;
|
proc_t *proc = current_thread()->proc;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
MUTEX_ACQUIRE(&proc->fdmutex);
|
MUTEX_ACQUIRE(&proc->fdmutex);
|
||||||
@@ -210,7 +210,7 @@ int fd_insert(file_t *file, int *fdp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
proc->fd[fd].file = file;
|
proc->fd[fd].file = file;
|
||||||
proc->fd[fd].flags = 0;
|
proc->fd[fd].flags = flags;
|
||||||
FILE_HOLD(file);
|
FILE_HOLD(file);
|
||||||
*fdp = fd;
|
*fdp = fd;
|
||||||
|
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ typedef struct {
|
|||||||
#define SOCK_DGRAM 2
|
#define SOCK_DGRAM 2
|
||||||
#define SOCK_RAW 3
|
#define SOCK_RAW 3
|
||||||
|
|
||||||
|
#define MSG_CMSG_CLOEXEC 0x40000000
|
||||||
#define MSG_CTRUNC 0x8
|
#define MSG_CTRUNC 0x8
|
||||||
#define MSG_PEEK 2
|
#define MSG_PEEK 2
|
||||||
#define MSG_WAITALL 0x100
|
#define MSG_WAITALL 0x100
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ int fd_dup(int oldfd, int newfd, bool exact, int flags, int *ret);
|
|||||||
int fd_clone(proc_t *proc);
|
int fd_clone(proc_t *proc);
|
||||||
int fd_setflags(int fd, int flags);
|
int fd_setflags(int fd, int flags);
|
||||||
int fd_getflags(int fd, int *flags);
|
int fd_getflags(int fd, int *flags);
|
||||||
int fd_insert(file_t *file, int *fdp);
|
int fd_insert(file_t *file, int *fdp, int flags);
|
||||||
|
|
||||||
#define FILE_LOCK(x) MUTEX_ACQUIRE(&(x)->mutex)
|
#define FILE_LOCK(x) MUTEX_ACQUIRE(&(x)->mutex)
|
||||||
#define FILE_UNLOCK(x) MUTEX_RELEASE(&(x)->mutex)
|
#define FILE_UNLOCK(x) MUTEX_RELEASE(&(x)->mutex)
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ typedef struct {
|
|||||||
#define SOCKET_RECV_FLAGS_PEEK 0x8000000000000000l
|
#define SOCKET_RECV_FLAGS_PEEK 0x8000000000000000l
|
||||||
#define SOCKET_RECV_FLAGS_WAITALL 0x4000000000000000l
|
#define SOCKET_RECV_FLAGS_WAITALL 0x4000000000000000l
|
||||||
#define SOCKET_RECV_FLAGS_CTRLTRUNCATED 0x2000000000000000l
|
#define SOCKET_RECV_FLAGS_CTRLTRUNCATED 0x2000000000000000l
|
||||||
|
#define SOCKET_RECV_FLAGS_CLOEXEC_CTRL 0x1000000000000000l
|
||||||
#define SOCKET_SEND_FLAGS_NOSIGNAL 0x8000000000000000l
|
#define SOCKET_SEND_FLAGS_NOSIGNAL 0x8000000000000000l
|
||||||
|
|
||||||
typedef struct socketops_t {
|
typedef struct socketops_t {
|
||||||
|
|||||||
@@ -71,11 +71,14 @@ static int datapoll(localsocket_t *local, localsocket_t *peer, int events) {
|
|||||||
int revents = 0;
|
int revents = 0;
|
||||||
|
|
||||||
// data to read?
|
// data to read?
|
||||||
if ((events & POLLIN) && RINGBUFFER_DATACOUNT(&local->ringbuffer))
|
if ((events & POLLIN) && (RINGBUFFER_DATACOUNT(&local->ringbuffer) || (peer->socket.shutdown & SOCKET_SHUTDOWN_WRITE)))
|
||||||
revents |= POLLIN;
|
revents |= POLLIN;
|
||||||
|
|
||||||
|
// XXX is this the correct behaviour?
|
||||||
|
if ((events & POLLOUT) && (peer->socket.shutdown & SOCKET_SHUTDOWN_READ))
|
||||||
|
revents |= POLLHUP;
|
||||||
// space to write?
|
// space to write?
|
||||||
if ((events & POLLOUT) && RINGBUFFER_DATACOUNT(&peer->ringbuffer) != SOCKET_BUFFER)
|
else if ((events & POLLOUT) && RINGBUFFER_DATACOUNT(&peer->ringbuffer) != SOCKET_BUFFER)
|
||||||
revents |= POLLOUT;
|
revents |= POLLOUT;
|
||||||
|
|
||||||
return revents;
|
return revents;
|
||||||
@@ -177,7 +180,7 @@ static int sendctrl(socket_t *socket, sockctrl_t *ctrl, size_t len, size_t datas
|
|||||||
if (ctrl == NULL) {
|
if (ctrl == NULL) {
|
||||||
// if there is no control data, there is no need to add a barrier
|
// if there is no control data, there is no need to add a barrier
|
||||||
// increase the bytes in the current section
|
// increase the bytes in the current section
|
||||||
peer->bytesremaining[peer->barrierwrite] += datasent;
|
peer->bytesremaining[peer->barrierwrite % BARRIER_SIZE] += datasent;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,9 +236,10 @@ static int sendctrl(socket_t *socket, sockctrl_t *ctrl, size_t len, size_t datas
|
|||||||
|
|
||||||
// create a new barrier secion
|
// create a new barrier secion
|
||||||
__assert(peer->barrierwrite != peer->barriercurrent + BARRIER_SIZE);
|
__assert(peer->barrierwrite != peer->barriercurrent + BARRIER_SIZE);
|
||||||
peer->barrierwrite++;
|
|
||||||
peer->filesremaining[peer->barrierwrite % BARRIER_SIZE] = fdcount;
|
peer->filesremaining[peer->barrierwrite % BARRIER_SIZE] = fdcount;
|
||||||
peer->bytesremaining[peer->barrierwrite % BARRIER_SIZE] = datasent;
|
peer->bytesremaining[peer->barrierwrite % BARRIER_SIZE] = datasent;
|
||||||
|
++peer->barrierwrite;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctrl = SOCK_CTRL_NEXT(ctrl);
|
ctrl = SOCK_CTRL_NEXT(ctrl);
|
||||||
@@ -244,7 +248,7 @@ static int sendctrl(socket_t *socket, sockctrl_t *ctrl, size_t len, size_t datas
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int recvctrl(socket_t *socket, sockctrl_t *ctrl, size_t len, bool *truncated, size_t *receivedlen) {
|
static int recvctrl(socket_t *socket, sockctrl_t *ctrl, size_t len, bool *truncated, size_t *receivedlen, uintmax_t flags) {
|
||||||
localsocket_t *localsocket = (localsocket_t *)socket;
|
localsocket_t *localsocket = (localsocket_t *)socket;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
*receivedlen = 0;
|
*receivedlen = 0;
|
||||||
@@ -258,7 +262,7 @@ static int recvctrl(socket_t *socket, sockctrl_t *ctrl, size_t len, bool *trunca
|
|||||||
// - number fds that fit in the data of the control
|
// - number fds that fit in the data of the control
|
||||||
// - files in the current section
|
// - files in the current section
|
||||||
// - files actually in the ringbuffer
|
// - files actually in the ringbuffer
|
||||||
size_t actualcount = min(min((len - sizeof(sockctrl_t)) / sizeof(int), filecount), localsocket->filesremaining[localsocket->barriercurrent]);
|
size_t actualcount = min(min((len - sizeof(sockctrl_t)) / sizeof(int), filecount), localsocket->filesremaining[localsocket->barriercurrent % BARRIER_SIZE]);
|
||||||
if (actualcount == 0)
|
if (actualcount == 0)
|
||||||
goto discard;
|
goto discard;
|
||||||
|
|
||||||
@@ -269,8 +273,7 @@ static int recvctrl(socket_t *socket, sockctrl_t *ctrl, size_t len, bool *trunca
|
|||||||
// read the file pointers and insert them into the process fd table
|
// read the file pointers and insert them into the process fd table
|
||||||
file_t *file;
|
file_t *file;
|
||||||
__assert(ringbuffer_read(&localsocket->fds, &file, sizeof(file_t *)) == sizeof(file_t *));
|
__assert(ringbuffer_read(&localsocket->fds, &file, sizeof(file_t *)) == sizeof(file_t *));
|
||||||
|
if (fd_insert(file, &fds[donecount], (flags & SOCKET_RECV_FLAGS_CLOEXEC_CTRL) ? O_CLOEXEC : 0)) {
|
||||||
if (fd_insert(file, &fds[donecount])) {
|
|
||||||
fd_release(file);
|
fd_release(file);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -286,7 +289,7 @@ static int recvctrl(socket_t *socket, sockctrl_t *ctrl, size_t len, bool *trunca
|
|||||||
memcpy(ctrl->data, fds, donecount * sizeof(int));
|
memcpy(ctrl->data, fds, donecount * sizeof(int));
|
||||||
|
|
||||||
// prepare for discarding the rest later
|
// prepare for discarding the rest later
|
||||||
localsocket->filesremaining[localsocket->barriercurrent] -= donecount;
|
localsocket->filesremaining[localsocket->barriercurrent % BARRIER_SIZE] -= donecount;
|
||||||
|
|
||||||
*receivedlen += ctrl->length;
|
*receivedlen += ctrl->length;
|
||||||
}
|
}
|
||||||
@@ -294,14 +297,14 @@ static int recvctrl(socket_t *socket, sockctrl_t *ctrl, size_t len, bool *trunca
|
|||||||
discard:
|
discard:
|
||||||
// discard the rest
|
// discard the rest
|
||||||
file_t *file = NULL;
|
file_t *file = NULL;
|
||||||
for (int i = 0; i < localsocket->filesremaining[localsocket->barriercurrent]; ++i) {
|
for (int i = 0; i < localsocket->filesremaining[localsocket->barriercurrent % BARRIER_SIZE]; ++i) {
|
||||||
ringbuffer_read(&localsocket->fds, &file, sizeof(file_t *));
|
ringbuffer_read(&localsocket->fds, &file, sizeof(file_t *));
|
||||||
fd_release(file);
|
fd_release(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
*truncated = file != NULL;
|
*truncated = file != NULL;
|
||||||
|
|
||||||
localsocket->filesremaining[localsocket->barriercurrent] = 0;
|
localsocket->filesremaining[localsocket->barriercurrent % BARRIER_SIZE] = 0;
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@@ -447,7 +450,7 @@ static int localsock_recv(socket_t *socket, sockdesc_t *sockdesc) {
|
|||||||
|
|
||||||
// receive control data
|
// receive control data
|
||||||
bool truncated;
|
bool truncated;
|
||||||
error = recvctrl(socket, sockdesc->ctrl, sockdesc->ctrllen, &truncated, &sockdesc->ctrldone);
|
error = recvctrl(socket, sockdesc->ctrl, sockdesc->ctrllen, &truncated, &sockdesc->ctrldone, flags);
|
||||||
if (error)
|
if (error)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
@@ -458,7 +461,7 @@ static int localsock_recv(socket_t *socket, sockdesc_t *sockdesc) {
|
|||||||
|
|
||||||
// check for a barrier from control data
|
// check for a barrier from control data
|
||||||
if (localsocket->bytesremaining[localsocket->barriercurrent % BARRIER_SIZE]) {
|
if (localsocket->bytesremaining[localsocket->barriercurrent % BARRIER_SIZE]) {
|
||||||
recvcount = min(recvcount, localsocket->bytesremaining[localsocket->barriercurrent]);
|
recvcount = min(recvcount, localsocket->bytesremaining[localsocket->barriercurrent % BARRIER_SIZE]);
|
||||||
|
|
||||||
// check if we should step forward from that barrier
|
// check if we should step forward from that barrier
|
||||||
localsocket->bytesremaining[localsocket->barriercurrent % BARRIER_SIZE] -= recvcount;
|
localsocket->bytesremaining[localsocket->barriercurrent % BARRIER_SIZE] -= recvcount;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#include <kernel/file.h>
|
#include <kernel/file.h>
|
||||||
#include <kernel/alloc.h>
|
#include <kernel/alloc.h>
|
||||||
|
|
||||||
#define KNOWN_FLAGS (MSG_PEEK | MSG_WAITALL)
|
#define KNOWN_FLAGS (MSG_PEEK | MSG_WAITALL | MSG_CMSG_CLOEXEC)
|
||||||
|
|
||||||
syscallret_t syscall_recvmsg(context_t *, int fd, msghdr_t *umsghdr, int flags) {
|
syscallret_t syscall_recvmsg(context_t *, int fd, msghdr_t *umsghdr, int flags) {
|
||||||
__assert((flags & ~KNOWN_FLAGS) == 0);
|
__assert((flags & ~KNOWN_FLAGS) == 0);
|
||||||
@@ -55,6 +55,9 @@ syscallret_t syscall_recvmsg(context_t *, int fd, msghdr_t *umsghdr, int flags)
|
|||||||
if (flags & MSG_WAITALL)
|
if (flags & MSG_WAITALL)
|
||||||
recvflags |= SOCKET_RECV_FLAGS_WAITALL;
|
recvflags |= SOCKET_RECV_FLAGS_WAITALL;
|
||||||
|
|
||||||
|
if (flags & MSG_CMSG_CLOEXEC)
|
||||||
|
recvflags |= SOCKET_RECV_FLAGS_CLOEXEC_CTRL;
|
||||||
|
|
||||||
iovec_iterator_t iovec_iterator;
|
iovec_iterator_t iovec_iterator;
|
||||||
sockdesc_t desc = {
|
sockdesc_t desc = {
|
||||||
.addr = &sockaddr,
|
.addr = &sockaddr,
|
||||||
|
|||||||
Reference in New Issue
Block a user