]> www.infradead.org Git - users/borneoa/openocd-next.git/commitdiff
rtt server: fix for dropped data when target has no space
authorfanoush <fanoush@gmail.com>
Mon, 2 Sep 2024 11:49:19 +0000 (13:49 +0200)
committerAntonio Borneo <borneo.antonio@gmail.com>
Sun, 22 Dec 2024 09:43:37 +0000 (09:43 +0000)
rtt_write_channel may write less data than requested,
default device buffer size for channel 0 is 16 bytes,
so currently anything larger than this is dropped.

This fix implements per connection buffer and uses the
connection->input_pending flag to retry writes.

Change-Id: I00c845fccb0248550ad0f0fd9cda7bac7976b92b
Signed-off-by: fanoush <fanoush@gmail.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/8360
Reviewed-by: zapb <dev@zapb.de>
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
src/server/rtt_server.c

index 97691534751caf1e29c44023d8cc8f87b7040ea7..b44101c3dcd12d3cc6cfc53477e3cbb760f03bde 100644 (file)
@@ -28,6 +28,12 @@ struct rtt_service {
        char *hello_message;
 };
 
+struct rtt_connection_data {
+       unsigned char buffer[64];
+       unsigned int length;
+       unsigned int offset;
+};
+
 static int read_callback(unsigned int channel, const uint8_t *buffer,
                size_t length, void *user_data)
 {
@@ -56,7 +62,16 @@ static int rtt_new_connection(struct connection *connection)
 {
        int ret;
        struct rtt_service *service;
+       struct rtt_connection_data *data;
+
+       data = calloc(1, sizeof(struct rtt_connection_data));
 
+       if (!data) {
+               LOG_ERROR("Out of memory");
+               return ERROR_FAIL;
+       }
+
+       connection->priv = data;
        service = connection->service->priv;
 
        LOG_DEBUG("rtt: New connection for channel %u", service->channel);
@@ -79,31 +94,53 @@ static int rtt_connection_closed(struct connection *connection)
        service = (struct rtt_service *)connection->service->priv;
        rtt_unregister_sink(service->channel, &read_callback, connection);
 
-       LOG_DEBUG("rtt: Connection for channel %u closed", service->channel);
+       free(connection->priv);
 
+       LOG_DEBUG("rtt: Connection for channel %u closed", service->channel);
        return ERROR_OK;
 }
 
 static int rtt_input(struct connection *connection)
 {
-       int bytes_read;
-       unsigned char buffer[1024];
        struct rtt_service *service;
-       size_t length;
+       struct rtt_connection_data *data;
 
-       service = (struct rtt_service *)connection->service->priv;
-       bytes_read = connection_read(connection, buffer, sizeof(buffer));
+       data = connection->priv;
+       service = connection->service->priv;
 
-       if (!bytes_read)
-               return ERROR_SERVER_REMOTE_CLOSED;
-       else if (bytes_read < 0) {
-               LOG_ERROR("error during read: %s", strerror(errno));
-               return ERROR_SERVER_REMOTE_CLOSED;
-       }
+       if (!connection->input_pending) {
+               int bytes_read;
 
-       length = bytes_read;
-       rtt_write_channel(service->channel, buffer, &length);
+               bytes_read = connection_read(connection, data->buffer, sizeof(data->buffer));
+
+               if (!bytes_read) {
+                       return ERROR_SERVER_REMOTE_CLOSED;
+               } else if (bytes_read < 0) {
+                       LOG_ERROR("error during read: %s", strerror(errno));
+                       return ERROR_SERVER_REMOTE_CLOSED;
+               }
 
+               data->length = bytes_read;
+               data->offset = 0;
+       }
+       if (data->length > 0) {
+               unsigned char *ptr;
+               size_t length, to_write;
+
+               ptr = data->buffer + data->offset;
+               length = data->length - data->offset;
+               to_write = length;
+               rtt_write_channel(service->channel, ptr, &length);
+
+               if (length < to_write) {
+                       data->offset += length;
+                       connection->input_pending = true;
+               } else {
+                       data->offset = 0;
+                       data->length = 0;
+                       connection->input_pending = false;
+               }
+       }
        return ERROR_OK;
 }
 
@@ -126,8 +163,10 @@ COMMAND_HANDLER(handle_rtt_start_command)
 
        service = calloc(1, sizeof(struct rtt_service));
 
-       if (!service)
+       if (!service) {
+               LOG_ERROR("Out of memory");
                return ERROR_FAIL;
+       }
 
        COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], service->channel);