mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 20:58:22 +00:00
sockets: use new iovec interface
This commit is contained in:
+2
-28
@@ -26,38 +26,12 @@ int sockfs_close(vnode_t *node, int flags, cred_t *cred) {
|
||||
|
||||
int sockfs_read(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc, cred_t *cred) {
|
||||
socket_t *socket = SOCKFS_SOCKET_FROM_NODE(node);
|
||||
sockdesc_t desc = {
|
||||
.addr = NULL,
|
||||
.buffer = buffer,
|
||||
.count = size,
|
||||
.flags = flags,
|
||||
.donecount = 0,
|
||||
.ctrl = NULL,
|
||||
.ctrllen = 0
|
||||
};
|
||||
|
||||
int e = socket->ops->recv(socket, &desc);
|
||||
|
||||
*readc = desc.donecount;
|
||||
return e;
|
||||
return socket_read(socket, buffer, size, flags, readc);
|
||||
}
|
||||
|
||||
int sockfs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int flags, size_t *writec, cred_t *cred) {
|
||||
socket_t *socket = SOCKFS_SOCKET_FROM_NODE(node);
|
||||
sockdesc_t desc = {
|
||||
.addr = NULL,
|
||||
.buffer = buffer,
|
||||
.count = size,
|
||||
.flags = flags,
|
||||
.donecount = 0,
|
||||
.ctrl = NULL,
|
||||
.ctrllen = 0
|
||||
};
|
||||
|
||||
int e = socket->ops->send(socket, &desc);
|
||||
|
||||
*writec = desc.donecount;
|
||||
return e;
|
||||
return socket_write(socket, buffer, size, flags, writec);
|
||||
}
|
||||
|
||||
int sockfs_poll(vnode_t *node, polldata_t *data, int events) {
|
||||
|
||||
@@ -47,12 +47,12 @@ int iovec_iterator_copy_from_buffer(iovec_iterator_t *iovec_iterator, void *buff
|
||||
// copies byte_count bytes from the iovec_iterator into the ringbuffer
|
||||
// returns the number of bytes copied
|
||||
// NOTE: the iovec can have userspace addresses. in this case, the copy can possibly fail by returning RINGBUFFER_USER_COPY_FAILED
|
||||
size_t iovec_iterator_copy_to_ringbuffer(iovec_iterator_t *iovec_iterator, ringbuffer_t *ringbuffer, size_t byte_count);
|
||||
size_t iovec_iterator_write_to_ringbuffer(iovec_iterator_t *iovec_iterator, ringbuffer_t *ringbuffer, size_t byte_count);
|
||||
|
||||
// copies byte_count bytes from the ringbuffer into the iovec_iterator
|
||||
// returns the number of bytes copied
|
||||
// NOTE: the iovec can have userspace addresses. in this case, the copy can possibly fail with RINGBUFFER_USER_COPY_FAILED
|
||||
size_t iovec_iterator_copy_from_ringbuffer(iovec_iterator_t *iovec_iterator, ringbuffer_t *ringbuffer, size_t byte_count);
|
||||
size_t iovec_iterator_read_from_ringbuffer(iovec_iterator_t *iovec_iterator, ringbuffer_t *ringbuffer, size_t byte_count);
|
||||
|
||||
// copies byte_count bytes from the ringbuffer into the iovec_iterator, without moving the ringbuffer read pointer
|
||||
// returns the number of bytes copied
|
||||
|
||||
@@ -78,7 +78,7 @@ void udp_process(netdev_t *netdev, void *buffer, uint32_t ip);
|
||||
void arp_process(netdev_t *netdev, void *buffer);
|
||||
void tcp_process(netdev_t *netdev, void *buffer, ipv4frame_t *ipv4frame);
|
||||
int arp_lookup(netdev_t *netdev, uint32_t ip, mac_t *mac);
|
||||
int udp_sendpacket(void *buffer, size_t packetsize, uint32_t ip, uint16_t srcport, uint16_t dstport, netdev_t *broadcastdev);
|
||||
int udp_sendpacket(iovec_iterator_t *iovec_iterator, size_t packetsize, uint32_t ip, uint16_t srcport, uint16_t dstport, netdev_t *broadcastdev);
|
||||
int ipv4_sendpacket(void *buffer, size_t packetsize, uint32_t ip, int proto, netdev_t *broadcastdev);
|
||||
size_t ipv4_getmtu(uint32_t ip);
|
||||
uint32_t ipv4_getnetdevip(uint32_t ip);
|
||||
|
||||
@@ -39,7 +39,7 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
sockaddr_t *addr;
|
||||
void *buffer;
|
||||
iovec_iterator_t iovec_iterator;
|
||||
size_t count;
|
||||
uintmax_t flags;
|
||||
size_t donecount;
|
||||
@@ -79,6 +79,53 @@ typedef struct {
|
||||
#define SOCKET_TYPE_TCP 2
|
||||
#define SOCKFS_SOCKET_FROM_NODE(nodep) (((socketnode_t *)(nodep))->socket)
|
||||
|
||||
static inline int socket_read(socket_t *socket, void *buffer, size_t size, uintmax_t flags, size_t *bytes_read) {
|
||||
sockdesc_t desc = {
|
||||
.addr = NULL,
|
||||
.count = size,
|
||||
.flags = flags,
|
||||
.donecount = 0,
|
||||
.ctrl = NULL,
|
||||
.ctrllen = 0
|
||||
};
|
||||
|
||||
iovec_t iovec = {
|
||||
.addr = buffer,
|
||||
.len = size
|
||||
};
|
||||
|
||||
iovec_iterator_init(&desc.iovec_iterator, &iovec, 1);
|
||||
|
||||
int e = socket->ops->recv(socket, &desc);
|
||||
|
||||
*bytes_read = desc.donecount;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static inline int socket_write(socket_t *socket, void *buffer, size_t size, uintmax_t flags, size_t *bytes_written) {
|
||||
sockdesc_t desc = {
|
||||
.addr = NULL,
|
||||
.count = size,
|
||||
.flags = flags,
|
||||
.donecount = 0,
|
||||
.ctrl = NULL,
|
||||
.ctrllen = 0
|
||||
};
|
||||
|
||||
iovec_t iovec = {
|
||||
.addr = buffer,
|
||||
.len = size
|
||||
};
|
||||
|
||||
iovec_iterator_init(&desc.iovec_iterator, &iovec, 1);
|
||||
|
||||
int e = socket->ops->send(socket, &desc);
|
||||
|
||||
*bytes_written = desc.donecount;
|
||||
return e;
|
||||
}
|
||||
|
||||
static inline int sock_convertaddress(sockaddr_t *sockaddr, abisockaddr_t *abisockaddr) {
|
||||
switch (abisockaddr->type) {
|
||||
case AF_INET:
|
||||
|
||||
@@ -119,7 +119,7 @@ int iovec_iterator_copy_from_buffer(iovec_iterator_t *iovec_iterator, void *buff
|
||||
return error;
|
||||
}
|
||||
|
||||
size_t iovec_iterator_copy_to_ringbuffer(iovec_iterator_t *iovec_iterator, ringbuffer_t *ringbuffer, size_t byte_count) {
|
||||
size_t iovec_iterator_write_to_ringbuffer(iovec_iterator_t *iovec_iterator, ringbuffer_t *ringbuffer, size_t byte_count) {
|
||||
size_t iterator_offset_save = iovec_iterator->total_offset;
|
||||
size_t remaining_total = min(byte_count, iovec_iterator->total_size - iovec_iterator->total_offset);
|
||||
size_t total_done = 0;
|
||||
@@ -140,6 +140,7 @@ size_t iovec_iterator_copy_to_ringbuffer(iovec_iterator_t *iovec_iterator, ringb
|
||||
break;
|
||||
|
||||
iovec_iterator_skip(iovec_iterator, copy_current);
|
||||
remaining_total -= current_done;
|
||||
total_done += current_done;
|
||||
|
||||
if (total_done == byte_count || iovec_iterator_finished(iovec_iterator))
|
||||
@@ -154,7 +155,7 @@ size_t iovec_iterator_copy_to_ringbuffer(iovec_iterator_t *iovec_iterator, ringb
|
||||
return total_done;
|
||||
}
|
||||
|
||||
size_t iovec_iterator_peek_from_ringbuffer(iovec_iterator_t *iovec_iterator, ringbuffer_t *ringbuffer, size_t byte_count, uintmax_t ringbuffer_offset) {
|
||||
size_t iovec_iterator_peek_from_ringbuffer(iovec_iterator_t *iovec_iterator, ringbuffer_t *ringbuffer, size_t offset, size_t byte_count) {
|
||||
size_t iterator_offset_save = iovec_iterator->total_offset;
|
||||
size_t remaining_total = min(byte_count, iovec_iterator->total_size - iovec_iterator->total_offset);
|
||||
size_t total_done = 0;
|
||||
@@ -164,12 +165,13 @@ size_t iovec_iterator_peek_from_ringbuffer(iovec_iterator_t *iovec_iterator, rin
|
||||
size_t remaining_current = iovec_iterator->current->len - iovec_iterator->current_offset;
|
||||
size_t copy_current = min(remaining_current, remaining_total);
|
||||
|
||||
current_done = ringbuffer_peek(ringbuffer, (void *)((uintptr_t)iovec_iterator->current->addr + iovec_iterator->current_offset), total_done, copy_current);
|
||||
current_done = ringbuffer_peek(ringbuffer, (void *)((uintptr_t)iovec_iterator->current->addr + iovec_iterator->current_offset), offset + total_done, copy_current);
|
||||
if (current_done == 0 || current_done == RINGBUFFER_USER_COPY_FAILED)
|
||||
break;
|
||||
|
||||
iovec_iterator_skip(iovec_iterator, copy_current);
|
||||
total_done += current_done;
|
||||
remaining_total -= current_done;
|
||||
|
||||
if (total_done == byte_count || iovec_iterator_finished(iovec_iterator))
|
||||
break;
|
||||
@@ -183,8 +185,8 @@ size_t iovec_iterator_peek_from_ringbuffer(iovec_iterator_t *iovec_iterator, rin
|
||||
return total_done;
|
||||
}
|
||||
|
||||
size_t iovec_iterator_copy_from_ringbuffer(iovec_iterator_t *iovec_iterator, ringbuffer_t *ringbuffer, size_t byte_count) {
|
||||
size_t done = iovec_iterator_peek_from_ringbuffer(iovec_iterator, ringbuffer, byte_count, 0);
|
||||
size_t iovec_iterator_read_from_ringbuffer(iovec_iterator_t *iovec_iterator, ringbuffer_t *ringbuffer, size_t byte_count) {
|
||||
size_t done = iovec_iterator_peek_from_ringbuffer(iovec_iterator, ringbuffer, 0, byte_count);
|
||||
if (done == RINGBUFFER_USER_COPY_FAILED)
|
||||
return done;
|
||||
|
||||
|
||||
@@ -363,7 +363,7 @@ static int localsock_send(socket_t *socket, sockdesc_t *sockdesc) {
|
||||
goto leave;
|
||||
}
|
||||
|
||||
sockdesc->donecount = ringbuffer_write(&peer->ringbuffer, sockdesc->buffer, sockdesc->count);
|
||||
sockdesc->donecount = iovec_iterator_write_to_ringbuffer(&sockdesc->iovec_iterator, &peer->ringbuffer, sockdesc->count);
|
||||
if (sockdesc->donecount == RINGBUFFER_USER_COPY_FAILED) {
|
||||
error = EFAULT;
|
||||
goto leave;
|
||||
@@ -467,13 +467,13 @@ static int localsock_recv(socket_t *socket, sockdesc_t *sockdesc) {
|
||||
}
|
||||
|
||||
if (flags & SOCKET_RECV_FLAGS_PEEK) {
|
||||
sockdesc->donecount = ringbuffer_peek(&localsocket->ringbuffer, sockdesc->buffer, 0, recvcount);
|
||||
sockdesc->donecount = iovec_iterator_peek_from_ringbuffer(&sockdesc->iovec_iterator, &localsocket->ringbuffer, 0, recvcount);
|
||||
if (sockdesc->donecount == RINGBUFFER_USER_COPY_FAILED) {
|
||||
error = EFAULT;
|
||||
goto leave;
|
||||
}
|
||||
} else {
|
||||
sockdesc->donecount = ringbuffer_read(&localsocket->ringbuffer, sockdesc->buffer, recvcount);
|
||||
sockdesc->donecount = iovec_iterator_read_from_ringbuffer(&sockdesc->iovec_iterator, &localsocket->ringbuffer, recvcount);
|
||||
if (sockdesc->donecount == RINGBUFFER_USER_COPY_FAILED) {
|
||||
error = EPIPE;
|
||||
goto leave;
|
||||
|
||||
@@ -1305,7 +1305,7 @@ static int tcp_send(socket_t *socket, sockdesc_t *sockdesc) {
|
||||
size_t writesize = min(TCB_RINGBUFFER_SIZE - RINGBUFFER_DATACOUNT(&tcb->transmitbuffer), sockdesc->count);
|
||||
__assert(writesize);
|
||||
|
||||
sockdesc->donecount = ringbuffer_write(&tcb->transmitbuffer, sockdesc->buffer, writesize);
|
||||
sockdesc->donecount = iovec_iterator_write_to_ringbuffer(&sockdesc->iovec_iterator, &tcb->transmitbuffer, writesize);
|
||||
if (sockdesc->donecount == RINGBUFFER_USER_COPY_FAILED) {
|
||||
error = EFAULT;
|
||||
goto leave;
|
||||
@@ -1386,13 +1386,13 @@ static int tcp_recv(socket_t *socket, sockdesc_t *sockdesc) {
|
||||
|
||||
size_t copycount = min(RINGBUFFER_DATACOUNT(&tcb->receivebuffer), sockdesc->count);
|
||||
if (flags & SOCKET_RECV_FLAGS_PEEK) {
|
||||
sockdesc->donecount = ringbuffer_peek(&tcb->receivebuffer, sockdesc->buffer, 0, copycount);
|
||||
sockdesc->donecount = iovec_iterator_peek_from_ringbuffer(&sockdesc->iovec_iterator, &tcb->receivebuffer, 0, copycount);
|
||||
if (sockdesc->donecount == RINGBUFFER_USER_COPY_FAILED) {
|
||||
error = EFAULT;
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
sockdesc->donecount = ringbuffer_read(&tcb->receivebuffer, sockdesc->buffer, copycount);
|
||||
sockdesc->donecount = iovec_iterator_read_from_ringbuffer(&sockdesc->iovec_iterator, &tcb->receivebuffer, copycount);
|
||||
if (sockdesc->donecount == RINGBUFFER_USER_COPY_FAILED) {
|
||||
error = EFAULT;
|
||||
goto cleanup;
|
||||
|
||||
+11
-10
@@ -32,7 +32,7 @@ typedef struct {
|
||||
static socket_t *ports[65536];
|
||||
static spinlock_t portlock;
|
||||
|
||||
int udp_sendpacket(void *buffer, size_t size, uint32_t ip, uint16_t srcport, uint16_t dstport, netdev_t *broadcastnetdev) {
|
||||
int udp_sendpacket(iovec_iterator_t *iovec_iterator, size_t size, uint32_t ip, uint16_t srcport, uint16_t dstport, netdev_t *broadcastnetdev) {
|
||||
void *newbuff = alloc(size + sizeof(udpframe_t));
|
||||
if (newbuff == NULL)
|
||||
return ENOMEM;
|
||||
@@ -45,7 +45,7 @@ int udp_sendpacket(void *buffer, size_t size, uint32_t ip, uint16_t srcport, uin
|
||||
};
|
||||
|
||||
memcpy(newbuff, &frame, sizeof(udpframe_t));
|
||||
int error = USERCOPY_POSSIBLY_FROM_USER((void *)((uintptr_t)newbuff + sizeof(udpframe_t)), buffer, size);
|
||||
int error = iovec_iterator_copy_to_buffer(iovec_iterator, (void *)((uintptr_t)newbuff + sizeof(udpframe_t)), size);
|
||||
if (error)
|
||||
goto leave;
|
||||
|
||||
@@ -203,7 +203,7 @@ static int udp_send(socket_t *socket, sockdesc_t *sockdesc) {
|
||||
socket->state = SOCKET_STATE_BOUND;
|
||||
}
|
||||
|
||||
e = udp_sendpacket(sockdesc->buffer, sockdesc->count, sockdesc->addr ? sockdesc->addr->ipv4addr.addr : udpsocket->peeraddress,
|
||||
e = udp_sendpacket(&sockdesc->iovec_iterator, sockdesc->count, sockdesc->addr ? sockdesc->addr->ipv4addr.addr : udpsocket->peeraddress,
|
||||
udpsocket->port, sockdesc->addr ? sockdesc->addr->ipv4addr.port : udpsocket->peerport, udpsocket->socket.netdev);
|
||||
|
||||
sockdesc->donecount = sockdesc->count;
|
||||
@@ -261,16 +261,20 @@ static int udp_recv(socket_t *socket, sockdesc_t *sockdesc) {
|
||||
|
||||
// this abuses an asterisk on the ringbuffer implementation that makes it not need locking when
|
||||
// something is reading and something is writing simultaneously.
|
||||
// this is done to not need to disable interrupts as the ringbuffer_peek could take a fault
|
||||
// this is done to not need to disable interrupts as the iovec_peek_from_ringbuffer could take a fault
|
||||
// multiple readers cannot happen because of the socket mutex and the write on the side of the
|
||||
// NIC is protected by the ringbuffer lock
|
||||
// NIC is protected by the ringbuffer lock. The ringbuffer lock is taken when reading the desc to ensure that
|
||||
// the whole packet has reached the ringbuffer
|
||||
size_t copycount;
|
||||
dataheader_t header;
|
||||
|
||||
long ipl = spinlock_acquireraiseipl(&udpsocket->ringbufferlock, IPL_DPC);
|
||||
__assert(ringbuffer_peek(&udpsocket->ringbuffer, &header, 0, sizeof(header)) == sizeof(header));
|
||||
spinlock_releaseloweripl(&udpsocket->ringbufferlock, ipl);
|
||||
|
||||
copycount = min(header.length, sockdesc->count);
|
||||
|
||||
sockdesc->donecount = ringbuffer_peek(&udpsocket->ringbuffer, sockdesc->buffer, sizeof(header), copycount);
|
||||
sockdesc->donecount = iovec_iterator_peek_from_ringbuffer(&sockdesc->iovec_iterator, &udpsocket->ringbuffer, sizeof(header), copycount);
|
||||
if (sockdesc->donecount == RINGBUFFER_USER_COPY_FAILED) {
|
||||
e = EFAULT;
|
||||
goto cleanup;
|
||||
@@ -279,11 +283,8 @@ static int udp_recv(socket_t *socket, sockdesc_t *sockdesc) {
|
||||
__assert(sockdesc->donecount == copycount);
|
||||
|
||||
// remove the message if not asked to peek
|
||||
if ((flags & SOCKET_RECV_FLAGS_PEEK) == 0) {
|
||||
bool status = spinlock_acquireirqclear(&udpsocket->ringbufferlock);
|
||||
if ((flags & SOCKET_RECV_FLAGS_PEEK) == 0)
|
||||
ringbuffer_truncate(&udpsocket->ringbuffer, sizeof(header) + header.length);
|
||||
spinlock_releaseirqrestore(&udpsocket->ringbufferlock, status);
|
||||
}
|
||||
|
||||
sockdesc->donecount = copycount;
|
||||
sockdesc->addr->ipv4addr.addr = header.peer;
|
||||
|
||||
@@ -28,10 +28,10 @@ syscallret_t syscall_recvmsg(context_t *, int fd, msghdr_t *umsghdr, int flags)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *buffer = vmm_map(NULL, buffersize, VMM_FLAGS_ALLOCATE, ARCH_MMU_FLAGS_READ | ARCH_MMU_FLAGS_WRITE | ARCH_MMU_FLAGS_NOEXEC, NULL);
|
||||
if (buffer == NULL) {
|
||||
ret.errno = ENOMEM;
|
||||
goto cleanup;
|
||||
if (iovec_user_check(msghdr.iov, msghdr.iovcount) == false) {
|
||||
ret.errno = EFAULT;
|
||||
sock_freemsghdr(&msghdr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
file = fd_get(fd);
|
||||
@@ -57,7 +57,6 @@ syscallret_t syscall_recvmsg(context_t *, int fd, msghdr_t *umsghdr, int flags)
|
||||
|
||||
sockdesc_t desc = {
|
||||
.addr = &sockaddr,
|
||||
.buffer = buffer,
|
||||
.count = buffersize,
|
||||
.flags = fileflagstovnodeflags(file->flags) | recvflags,
|
||||
.donecount = 0,
|
||||
@@ -66,18 +65,12 @@ syscallret_t syscall_recvmsg(context_t *, int fd, msghdr_t *umsghdr, int flags)
|
||||
.ctrldone = 0
|
||||
};
|
||||
|
||||
iovec_iterator_init(&desc.iovec_iterator, msghdr.iov, msghdr.iovcount);
|
||||
|
||||
ret.errno = socket->ops->recv(socket, &desc);
|
||||
if (ret.errno)
|
||||
goto cleanup;
|
||||
|
||||
uintmax_t iovoffset = 0;
|
||||
for (int i = 0; i < msghdr.iovcount; ++i) {
|
||||
ret.errno = usercopy_touser(msghdr.iov[i].addr, (void *)((uintptr_t)buffer + iovoffset), msghdr.iov[i].len);
|
||||
if (ret.errno)
|
||||
goto cleanup;
|
||||
iovoffset += msghdr.iov[i].len;
|
||||
}
|
||||
|
||||
if (msghdr.addr) {
|
||||
abisockaddr_t abisockaddr;
|
||||
ret.errno = sock_addrtoabiaddr(socket->type, &sockaddr, &abisockaddr);
|
||||
@@ -120,9 +113,6 @@ syscallret_t syscall_recvmsg(context_t *, int fd, msghdr_t *umsghdr, int flags)
|
||||
if (file)
|
||||
fd_release(file);
|
||||
|
||||
if (buffer)
|
||||
vmm_unmap(buffer, buffersize, 0);
|
||||
|
||||
sock_freemsghdr(&msghdr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -23,20 +23,10 @@ syscallret_t syscall_sendmsg(context_t *, int fd, msghdr_t *umsghdr, int flags)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *buffer = vmm_map(NULL, buffersize, VMM_FLAGS_ALLOCATE, ARCH_MMU_FLAGS_READ | ARCH_MMU_FLAGS_WRITE | ARCH_MMU_FLAGS_NOEXEC, NULL);
|
||||
if (buffer == NULL) {
|
||||
ret.errno = ENOMEM;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
uintmax_t iovoffset = 0;
|
||||
|
||||
for (int i = 0; i < msghdr.iovcount; ++i) {
|
||||
ret.errno = usercopy_fromuser((void *)((uintptr_t)buffer + iovoffset), msghdr.iov[i].addr, msghdr.iov[i].len);
|
||||
if (ret.errno)
|
||||
goto cleanup;
|
||||
|
||||
iovoffset += msghdr.iov[i].len;
|
||||
if (iovec_user_check(msghdr.iov, msghdr.iovcount) == false) {
|
||||
ret.errno = EFAULT;
|
||||
sock_freemsghdr(&msghdr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
file = fd_get(fd);
|
||||
@@ -61,7 +51,6 @@ syscallret_t syscall_sendmsg(context_t *, int fd, msghdr_t *umsghdr, int flags)
|
||||
|
||||
sockdesc_t desc = {
|
||||
.addr = msghdr.addr ? &sockaddr : NULL,
|
||||
.buffer = buffer,
|
||||
.count = buffersize,
|
||||
.flags = fileflagstovnodeflags(file->flags) | ((flags & MSG_NOSIGNAL) ? SOCKET_SEND_FLAGS_NOSIGNAL : 0),
|
||||
.donecount = 0,
|
||||
@@ -70,6 +59,8 @@ syscallret_t syscall_sendmsg(context_t *, int fd, msghdr_t *umsghdr, int flags)
|
||||
.ctrldone = 0
|
||||
};
|
||||
|
||||
iovec_iterator_init(&desc.iovec_iterator, msghdr.iov, msghdr.iovcount);
|
||||
|
||||
ret.errno = socket->ops->send(socket, &desc);
|
||||
ret.ret = ret.errno ? -1 : desc.donecount;
|
||||
|
||||
@@ -77,9 +68,6 @@ syscallret_t syscall_sendmsg(context_t *, int fd, msghdr_t *umsghdr, int flags)
|
||||
if (file)
|
||||
fd_release(file);
|
||||
|
||||
if (buffer)
|
||||
vmm_unmap(buffer, buffersize, 0);
|
||||
|
||||
sock_freemsghdr(&msghdr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user