}
static uint32_t buffer_free(const struct buffer *buf) {
- return buf->maxsize - buf->used;
+ return buf->maxsize > buf->used ? buf->maxsize - buf->used : 0;
}
// Connections are stored in a sorted list.
if(!is_reliable(c)) {
c->snd.una = c->snd.nxt = c->snd.last;
buffer_discard(&c->sndbuf, c->sndbuf.used);
- c->do_poll = true;
}
if(is_reliable(c) && !timespec_isset(&c->rtrx_timeout)) {
// Packet loss or reordering occured. Store the data in the buffer.
ssize_t rxd = buffer_put_at(&c->rcvbuf, offset, data, len);
- if(rxd < 0 || (size_t)rxd < len) {
- abort();
+ if(rxd <= 0) {
+ debug(c, "packet outside receive buffer, dropping\n");
+ return;
+ }
+
+ if((size_t)rxd < len) {
+ debug(c, "packet partially outside receive buffer\n");
+ len = rxd;
}
// Make note of where we put it.
uint32_t offset = seqdiff(hdr->seq, c->rcv.nxt);
- if(offset + len > c->rcvbuf.maxsize) {
- abort();
- }
-
if(offset) {
handle_out_of_order(c, offset, data, len);
} else {
if(data_acked) {
buffer_discard(&c->sndbuf, data_acked);
- c->do_poll = true;
+
+ if(is_reliable(c)) {
+ c->do_poll = true;
+ }
}
// Also advance snd.nxt if possible
c->sndbuf.maxsize = -1;
}
- c->do_poll = buffer_free(&c->sndbuf);
+ c->do_poll = is_reliable(c) && buffer_free(&c->sndbuf);
}
size_t utcp_get_rcvbuf(struct utcp_connection *c) {
void utcp_set_poll_cb(struct utcp_connection *c, utcp_poll_t poll) {
if(c) {
c->poll = poll;
- c->do_poll = buffer_free(&c->sndbuf);
+ c->do_poll = is_reliable(c) && buffer_free(&c->sndbuf);
}
}