unix: Implement SO_RCVBUF
Implemented `UnixBufferQueue::SetCapacity` so that `setsockopt` with `SO_RCVBUF` will not always return an error. Change-Id: I2d9be84633f84474fac64b379e9f89ef2751a094 Reviewed-on: https://review.haiku-os.org/c/haiku/+/6816 Reviewed-by: waddlesplash <[email protected]> Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
2b514ce830
commit
303ff56a5f
@@ -44,6 +44,7 @@ ssize_t ring_buffer_user_write(struct ring_buffer *buffer, const uint8 *data, ss
|
||||
size_t ring_buffer_peek(struct ring_buffer *buffer, size_t offset, void *data,
|
||||
size_t length);
|
||||
int32 ring_buffer_get_vecs(struct ring_buffer *buffer, struct iovec *vecs);
|
||||
size_t ring_buffer_move(struct ring_buffer *to, ssize_t length, struct ring_buffer *from);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -316,8 +316,20 @@ UnixBufferQueue::Write(UnixRequest& request)
|
||||
status_t
|
||||
UnixBufferQueue::SetCapacity(size_t capacity)
|
||||
{
|
||||
// TODO:...
|
||||
return B_ERROR;
|
||||
if (capacity <= fCapacity)
|
||||
return B_OK;
|
||||
|
||||
ring_buffer* newBuffer = create_ring_buffer(capacity);
|
||||
if (newBuffer == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
ring_buffer_move(newBuffer, ring_buffer_readable(fBuffer), fBuffer);
|
||||
delete_ring_buffer(fBuffer);
|
||||
|
||||
fBuffer = newBuffer;
|
||||
fCapacity = capacity;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -302,6 +302,47 @@ ring_buffer_get_vecs(struct ring_buffer* buffer, struct iovec* vecs)
|
||||
}
|
||||
|
||||
|
||||
/*! Moves data from one ring buffer to another.
|
||||
|
||||
\param to The destination ring buffer.
|
||||
\param length The maximum number of bytes to move.
|
||||
\param from The source ring buffer.
|
||||
\return The number of bytes actually moved.
|
||||
*/
|
||||
size_t
|
||||
ring_buffer_move(struct ring_buffer *to, ssize_t length,
|
||||
struct ring_buffer *from)
|
||||
{
|
||||
if (length > from->in)
|
||||
length = from->in;
|
||||
|
||||
if (length > (to->size - to->in))
|
||||
length = to->size - to->in;
|
||||
|
||||
size_t bytesMoved = 0;
|
||||
|
||||
if ((from->first + length) <= from->size) {
|
||||
// simple move
|
||||
bytesMoved = ring_buffer_write(to, from->buffer + from->first, length);
|
||||
} else {
|
||||
// need to move both ends
|
||||
size_t upper = from->size - from->first;
|
||||
size_t lower = length - upper;
|
||||
|
||||
bytesMoved = ring_buffer_write(to, from->buffer + from->first, upper);
|
||||
if (bytesMoved == upper) {
|
||||
// only continue writing if the first part was completely written
|
||||
bytesMoved += ring_buffer_write(to, from->buffer, lower);
|
||||
}
|
||||
}
|
||||
|
||||
from->first = (from->first + bytesMoved) % from->size;
|
||||
from->in -= bytesMoved;
|
||||
|
||||
return bytesMoved;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/** Sends the contents of the ring buffer to a port.
|
||||
* The buffer will be empty afterwards only if sending the data actually works.
|
||||
|
||||
Reference in New Issue
Block a user