mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-29 05:38:21 +00:00
sockets: use new iovec interface
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user