summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Toso <victortoso@redhat.com>2021-08-25 19:34:00 +0200
committerVictor Toso <victortoso@redhat.com>2021-11-04 11:16:47 +0100
commit7b0d9d26042054b7a29076804d8d33d75a179cf5 (patch)
tree941adf7f5aa7769c636611857b3041f6e061393c
parentf298f497584d7535cf4c5ddc30d036c0a3f62502 (diff)
usbredirparser: introduce usbredirparser_get_bufferered_output_size()
The application does not have a way to know how much data is being queued by usbredirparser due data output being slower than input. This function is a simple way to get that value. Also, this function can be used in usbredirhost to allow dropping isoc packets before calling usbredirparser's functions. Related: https://gitlab.freedesktop.org/spice/usbredir/-/issues/19 Signed-off-by: Victor Toso <victortoso@redhat.com>
-rw-r--r--usbredirparser/usbredirparser.c33
-rw-r--r--usbredirparser/usbredirparser.h5
-rw-r--r--usbredirparser/usbredirparser.map6
3 files changed, 39 insertions, 5 deletions
diff --git a/usbredirparser/usbredirparser.c b/usbredirparser/usbredirparser.c
index e4d5f0e..b36608a 100644
--- a/usbredirparser/usbredirparser.c
+++ b/usbredirparser/usbredirparser.c
@@ -82,8 +82,9 @@ struct usbredirparser_priv {
int data_len;
int data_read;
int to_skip;
- struct usbredirparser_buf *write_buf;
int write_buf_count;
+ struct usbredirparser_buf *write_buf;
+ uint64_t write_buf_total_size;
};
static void
@@ -128,6 +129,7 @@ usbredirparser_assert_invariants(const struct usbredirparser_priv *parser)
assert((parser->data_len != 0) ^ (parser->data == NULL));
int write_buf_count = 0;
+ uint64_t total_size = 0;
const struct usbredirparser_buf *write_buf = parser->write_buf;
for (; write_buf != NULL ; write_buf = write_buf->next) {
assert(write_buf->pos >= 0);
@@ -135,8 +137,10 @@ usbredirparser_assert_invariants(const struct usbredirparser_priv *parser)
assert(write_buf->pos <= write_buf->len);
assert(write_buf->len == 0 || write_buf->buf != NULL);
write_buf_count++;
+ total_size += write_buf->len;
}
assert(parser->write_buf_count == write_buf_count);
+ assert(parser->write_buf_total_size == total_size);
#endif
}
@@ -249,6 +253,19 @@ void usbredirparser_destroy(struct usbredirparser *parser_pub)
free(parser);
}
+USBREDIR_VISIBLE
+uint64_t usbredirparser_get_bufferered_output_size(struct usbredirparser *parser_pub)
+{
+ struct usbredirparser_priv *parser =
+ (struct usbredirparser_priv *)parser_pub;
+ uint64_t size;
+
+ LOCK(parser);
+ size = parser->write_buf_total_size;
+ UNLOCK(parser);
+ return size;
+}
+
static int usbredirparser_caps_get_cap(struct usbredirparser_priv *parser,
uint32_t *caps, int cap)
{
@@ -1166,8 +1183,10 @@ int usbredirparser_do_write(struct usbredirparser *parser_pub)
parser->write_buf = wbuf->next;
if (!(parser->flags & usbredirparser_fl_write_cb_owns_buffer))
free(wbuf->buf);
- free(wbuf);
+
+ parser->write_buf_total_size -= wbuf->len;
parser->write_buf_count--;
+ free(wbuf);
}
}
UNLOCK(parser);
@@ -1197,7 +1216,7 @@ static void usbredirparser_queue(struct usbredirparser *parser_pub,
uint8_t *buf, *type_header_out, *data_out;
struct usb_redir_header *header;
struct usbredirparser_buf *wbuf, *new_wbuf;
- int header_len, type_header_len;
+ int header_len, type_header_len, total_size;
header_len = usbredirparser_get_header_len(parser_pub);
type_header_len = usbredirparser_get_type_header_len(parser_pub, type, 1);
@@ -1212,8 +1231,9 @@ static void usbredirparser_queue(struct usbredirparser *parser_pub,
return;
}
+ total_size = header_len + type_header_len + data_len;
new_wbuf = calloc(1, sizeof(*new_wbuf));
- buf = malloc(header_len + type_header_len + data_len);
+ buf = malloc(total_size);
if (!new_wbuf || !buf) {
ERROR("Out of memory allocating buffer to send packet, dropping!");
free(new_wbuf); free(buf);
@@ -1221,7 +1241,7 @@ static void usbredirparser_queue(struct usbredirparser *parser_pub,
}
new_wbuf->buf = buf;
- new_wbuf->len = header_len + type_header_len + data_len;
+ new_wbuf->len = total_size;
header = (struct usb_redir_header *)buf;
type_header_out = buf + header_len;
@@ -1247,6 +1267,7 @@ static void usbredirparser_queue(struct usbredirparser *parser_pub,
wbuf->next = new_wbuf;
}
+ parser->write_buf_total_size += total_size;
parser->write_buf_count++;
UNLOCK(parser);
}
@@ -1796,6 +1817,7 @@ int usbredirparser_unserialize(struct usbredirparser *parser_pub,
}
if (!(parser->write_buf_count == 0 && parser->write_buf == NULL &&
+ parser->write_buf_total_size == 0 &&
parser->data == NULL && parser->header_read == 0 &&
parser->type_header_read == 0 && parser->data_read == 0)) {
ERROR("unserialization must use a pristine parser");
@@ -1962,6 +1984,7 @@ int usbredirparser_unserialize(struct usbredirparser *parser_pub,
wbuf->len = l;
*next = wbuf;
next = &wbuf->next;
+ parser->write_buf_total_size += wbuf->len;
parser->write_buf_count++;
i--;
}
diff --git a/usbredirparser/usbredirparser.h b/usbredirparser/usbredirparser.h
index fbadbb8..9f87d39 100644
--- a/usbredirparser/usbredirparser.h
+++ b/usbredirparser/usbredirparser.h
@@ -245,6 +245,11 @@ int usbredirparser_do_read(struct usbredirparser *parser);
/* This returns the number of usbredir packets queued up for writing */
int usbredirparser_has_data_to_write(struct usbredirparser *parser);
+/* This returns the number of bytes queued to be written out. Can be used by control plane
+ * to drop data from being queued, see issue:
+ * https://gitlab.freedesktop.org/spice/usbredir/-/issues/19 */
+uint64_t usbredirparser_get_bufferered_output_size(struct usbredirparser *parser_pub);
+
/* Call this when usbredirparser_has_data_to_write returns > 0
returns 0 on success, -1 if a write error happened.
If a write error happened, this function will retry writing any queued data
diff --git a/usbredirparser/usbredirparser.map b/usbredirparser/usbredirparser.map
index ab45fed..7ae2fd5 100644
--- a/usbredirparser/usbredirparser.map
+++ b/usbredirparser/usbredirparser.map
@@ -59,4 +59,10 @@ global:
usbredirfilter_free;
} USBREDIRPARSER_0.8.0;
+USBREDIRPARSER_0.11.0 {
+global:
+ usbredirparser_get_bufferered_output_size;
+} USBREDIRPARSER_0.10.0;
+
+
# .... define new API here using predicted next version number ....