|
@@ -37,9 +37,13 @@ struct tcp_comm_ctx {
|
37
|
37
|
enum conn_state conn_state;
|
38
|
38
|
|
39
|
39
|
struct tcp_pcb *client_pcb;
|
|
40
|
+ // Note: sizeof(buf) is used elsewhere, so if this is changed to not
|
|
41
|
+ // be an array, those will need updating
|
40
|
42
|
uint8_t buf[(sizeof(uint32_t) * (1 + COMM_MAX_NARG)) + TCP_COMM_MAX_DATA_LEN];
|
|
43
|
+
|
|
44
|
+ uint16_t rx_start_offs;
|
41
|
45
|
uint16_t rx_bytes_received;
|
42
|
|
- uint16_t rx_bytes_remaining;
|
|
46
|
+ uint16_t rx_bytes_needed;
|
43
|
47
|
|
44
|
48
|
uint16_t tx_bytes_sent;
|
45
|
49
|
uint16_t tx_bytes_remaining;
|
|
@@ -89,10 +93,7 @@ static int tcp_comm_error_begin(struct tcp_comm_ctx *ctx);
|
89
|
93
|
static int tcp_comm_sync_begin(struct tcp_comm_ctx *ctx)
|
90
|
94
|
{
|
91
|
95
|
ctx->conn_state = CONN_STATE_WAIT_FOR_SYNC;
|
92
|
|
- ctx->rx_bytes_received = 0;
|
93
|
|
- ctx->rx_bytes_remaining = sizeof(uint32_t);
|
94
|
|
-
|
95
|
|
- DEBUG_printf("sync_begin %d\n", ctx->rx_bytes_remaining);
|
|
96
|
+ ctx->rx_bytes_needed = sizeof(uint32_t);
|
96
|
97
|
}
|
97
|
98
|
|
98
|
99
|
static int tcp_comm_sync_complete(struct tcp_comm_ctx *ctx)
|
|
@@ -108,8 +109,7 @@ static int tcp_comm_sync_complete(struct tcp_comm_ctx *ctx)
|
108
|
109
|
static int tcp_comm_opcode_begin(struct tcp_comm_ctx *ctx)
|
109
|
110
|
{
|
110
|
111
|
ctx->conn_state = CONN_STATE_READ_OPCODE;
|
111
|
|
- ctx->rx_bytes_received = 0;
|
112
|
|
- ctx->rx_bytes_remaining = sizeof(uint32_t);
|
|
112
|
+ ctx->rx_bytes_needed = sizeof(uint32_t);
|
113
|
113
|
|
114
|
114
|
return 0;
|
115
|
115
|
}
|
|
@@ -130,8 +130,7 @@ static int tcp_comm_opcode_complete(struct tcp_comm_ctx *ctx)
|
130
|
130
|
static int tcp_comm_args_begin(struct tcp_comm_ctx *ctx)
|
131
|
131
|
{
|
132
|
132
|
ctx->conn_state = CONN_STATE_READ_ARGS;
|
133
|
|
- ctx->rx_bytes_received = 0;
|
134
|
|
- ctx->rx_bytes_remaining = ctx->cmd->nargs * sizeof(uint32_t);
|
|
133
|
+ ctx->rx_bytes_needed = ctx->cmd->nargs * sizeof(uint32_t);
|
135
|
134
|
|
136
|
135
|
if (ctx->cmd->nargs == 0) {
|
137
|
136
|
return tcp_comm_args_complete(ctx);
|
|
@@ -163,8 +162,7 @@ static int tcp_comm_data_begin(struct tcp_comm_ctx *ctx, uint32_t data_len)
|
163
|
162
|
const struct comm_command *cmd = ctx->cmd;
|
164
|
163
|
|
165
|
164
|
ctx->conn_state = CONN_STATE_READ_DATA;
|
166
|
|
- ctx->rx_bytes_received = 0;
|
167
|
|
- ctx->rx_bytes_remaining = data_len;
|
|
165
|
+ ctx->rx_bytes_needed = data_len;
|
168
|
166
|
|
169
|
167
|
if (data_len == 0) {
|
170
|
168
|
return tcp_comm_data_complete(ctx);
|
|
@@ -378,8 +376,10 @@ static err_t tcp_comm_client_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *
|
378
|
376
|
if (p->tot_len > 0) {
|
379
|
377
|
DEBUG_printf("tcp_comm_server_recv %d err %d\n", p->tot_len, err);
|
380
|
378
|
|
381
|
|
- if (p->tot_len > ctx->rx_bytes_remaining) {
|
382
|
|
- DEBUG_printf("more data than expected: %d vs %d\n", p->tot_len, ctx->rx_bytes_remaining);
|
|
379
|
+ if (p->tot_len > (sizeof(ctx->buf) - ctx->rx_bytes_received)) {
|
|
380
|
+ // Doesn't fit in buffer at all. Protocol error.
|
|
381
|
+ DEBUG_printf("not enough space in buffer: %d vs %d\n", p->tot_len, sizeof(ctx->buf) - ctx->rx_bytes_received);
|
|
382
|
+
|
383
|
383
|
// TODO: Invoking the error response state here feels
|
384
|
384
|
// like a bit of a layering violation, but this is a
|
385
|
385
|
// protocol error, rather than a failure in the stack
|
|
@@ -389,23 +389,40 @@ static err_t tcp_comm_client_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *
|
389
|
389
|
return tcp_comm_client_complete(ctx, ERR_ARG);
|
390
|
390
|
}
|
391
|
391
|
return ERR_OK;
|
|
392
|
+ } else if (p->tot_len > (sizeof(ctx->buf) - (ctx->rx_start_offs + ctx->rx_bytes_received))) {
|
|
393
|
+ // There will be space, but we need to shift the data back
|
|
394
|
+ // to the start of the buffer
|
|
395
|
+ DEBUG_printf("memmove %d bytes to make space for %d bytes\n", ctx->rx_bytes_received, p->tot_len);
|
|
396
|
+ memmove(ctx->buf, ctx->buf + ctx->rx_start_offs, ctx->rx_bytes_received);
|
|
397
|
+ ctx->rx_start_offs = 0;
|
392
|
398
|
}
|
393
|
399
|
|
394
|
|
- // Receive the buffer
|
395
|
|
- if (pbuf_copy_partial(p, ctx->buf + ctx->rx_bytes_received, p->tot_len, 0) != p->tot_len) {
|
|
400
|
+ uint8_t *dst = ctx->buf + ctx->rx_start_offs + ctx->rx_bytes_received;
|
|
401
|
+
|
|
402
|
+ // We can always handle the full packet
|
|
403
|
+ if (pbuf_copy_partial(p, dst, p->tot_len, 0) != p->tot_len) {
|
396
|
404
|
DEBUG_printf("wrong copy len\n");
|
397
|
405
|
return tcp_comm_client_complete(ctx, ERR_ARG);
|
398
|
406
|
}
|
399
|
407
|
|
400
|
408
|
ctx->rx_bytes_received += p->tot_len;
|
401
|
|
- ctx->rx_bytes_remaining -= p->tot_len;
|
402
|
409
|
tcp_recved(tpcb, p->tot_len);
|
403
|
410
|
|
404
|
|
- if (ctx->rx_bytes_remaining == 0) {
|
|
411
|
+ while (ctx->rx_bytes_received >= ctx->rx_bytes_needed) {
|
|
412
|
+ uint16_t consumed = ctx->rx_bytes_needed;
|
|
413
|
+
|
405
|
414
|
int res = tcp_comm_rx_complete(ctx);
|
406
|
415
|
if (res) {
|
407
|
416
|
return tcp_comm_client_complete(ctx, ERR_ARG);
|
408
|
417
|
}
|
|
418
|
+
|
|
419
|
+ ctx->rx_start_offs += consumed;
|
|
420
|
+ ctx->rx_bytes_received -= consumed;
|
|
421
|
+
|
|
422
|
+ if (ctx->rx_bytes_received == 0) {
|
|
423
|
+ ctx->rx_start_offs = 0;
|
|
424
|
+ break;
|
|
425
|
+ }
|
409
|
426
|
}
|
410
|
427
|
}
|
411
|
428
|
pbuf_free(p);
|
|
@@ -427,7 +444,7 @@ static void tcp_comm_client_err(void *arg, err_t err)
|
427
|
444
|
|
428
|
445
|
ctx->client_pcb = NULL;
|
429
|
446
|
ctx->conn_state = CONN_STATE_CLOSED;
|
430
|
|
- ctx->rx_bytes_remaining = 0;
|
|
447
|
+ ctx->rx_bytes_needed = 0;
|
431
|
448
|
cyw43_arch_gpio_put (0, false);
|
432
|
449
|
}
|
433
|
450
|
|