Fix dc_iostream_{read,write} debugging implementation
The dc_iostream_{read,write}() implementation had multiple issues:
(a) it would return DC_STATUS_SUCCESS even if no iostream
implementation existed.
Yes, it would also return a zero "actual" bytes, but most backends
don't even pass an "actual" pointer, so returning success was still
completely insane.
This one probably didn't matter, because all iostreams should have
read and write members, but the return value was completely wrong
if that ever were to happen.
(b) The write side actually tested not whether a write function
existed, but whether a read one existed.
Again, this one probably didn't matter in practice, since an
iostream without a read and write member doesn't make much sense,
but the test was completely wrong regardless.
(c) If the user passed in a NULL 'actual' pointer, the wrapper would
ignore that, and pass in its own pointer instead, in order to know
how many bytes to print for the debug message.
But that means that the low-level read/write functions cannot know
whether the user actually is able to handle a partial read or not.
This one _definitely_ matters, because some protocols need to have
a buffer for the whole incoming packet, but packerts may not always
be full-size. The low-level protocol needs to know whether to wait
for further packets (in order to fill the buffer) or to just return
the partial data.
This fixes all of these issues. If the user passes in a NULL actual
pointer (indicating that it needs all-or-nothing and is not ready to
handle a partial success), just loop over the IO until the buffer is
fully exhausted.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
8120b11258
commit
e97886a994
@ -186,43 +186,74 @@ dc_iostream_configure (dc_iostream_t *iostream, unsigned int baudrate, unsigned
|
||||
dc_status_t
|
||||
dc_iostream_read (dc_iostream_t *iostream, void *data, size_t size, size_t *actual)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
if (actual)
|
||||
*actual = 0;
|
||||
|
||||
if (iostream == NULL || iostream->vtable->read == NULL)
|
||||
return DC_STATUS_IO;
|
||||
|
||||
while (size) {
|
||||
dc_status_t status;
|
||||
size_t nbytes = 0;
|
||||
|
||||
if (iostream == NULL || iostream->vtable->read == NULL) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
status = iostream->vtable->read (iostream, data, size, &nbytes);
|
||||
|
||||
HEXDUMP (iostream->context, DC_LOGLEVEL_INFO, "Read", (unsigned char *) data, nbytes);
|
||||
|
||||
out:
|
||||
if (actual)
|
||||
/*
|
||||
* If the reader is able to handle partial results,
|
||||
* return them as such. NOTE! No need to add up a
|
||||
* total, we will go through this loop only once
|
||||
* in this case.
|
||||
*/
|
||||
if (actual) {
|
||||
*actual = nbytes;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
if (status != DC_STATUS_SUCCESS)
|
||||
return status;
|
||||
|
||||
/*
|
||||
* Continue reading to fill up the whole buffer,
|
||||
* since the reader is not able to handle a
|
||||
* partial result.
|
||||
*/
|
||||
data = (void *)(nbytes + (char *)data);
|
||||
size -= nbytes;
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
dc_status_t
|
||||
dc_iostream_write (dc_iostream_t *iostream, const void *data, size_t size, size_t *actual)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
if (actual)
|
||||
*actual = 0;
|
||||
|
||||
if (iostream == NULL || iostream->vtable->write == NULL)
|
||||
return DC_STATUS_IO;
|
||||
|
||||
while (size) {
|
||||
dc_status_t status;
|
||||
size_t nbytes = 0;
|
||||
|
||||
if (iostream == NULL || iostream->vtable->read == NULL) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
status = iostream->vtable->write (iostream, data, size, &nbytes);
|
||||
|
||||
HEXDUMP (iostream->context, DC_LOGLEVEL_INFO, "Write", (const unsigned char *) data, nbytes);
|
||||
|
||||
out:
|
||||
if (actual)
|
||||
if (actual) {
|
||||
*actual = nbytes;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
if (status != DC_STATUS_SUCCESS)
|
||||
return status;
|
||||
|
||||
data = (void *)(nbytes + (char *)data);
|
||||
size -= nbytes;
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
dc_status_t
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user