// TODO: convert to ringbuffers to avoid memmove() operations.
// Store data into the buffer
-static ssize_t buffer_put(struct buffer *buf, const void *data, size_t len) {
+static ssize_t buffer_put_at(struct buffer *buf, size_t offset, const void *data, size_t len) {
if(buf->maxsize <= buf->used)
return 0;
- if(len > buf->maxsize - buf->used)
- len = buf->maxsize - buf->used;
- if(len > buf->size - buf->used) {
+
+ debug("buffer_put_at %zu %zu %zu\n", buf->used, offset, len);
+
+ size_t required = offset + len;
+ if(required > buf->maxsize) {
+ if(offset >= buf->maxsize)
+ return 0;
+ abort();
+ len = buf->maxsize - offset;
+ required = buf->maxsize;
+ }
+
+ if(required > buf->size) {
size_t newsize = buf->size;
- do {
- newsize *= 2;
- } while(newsize < buf->used + len);
+ if(!newsize) {
+ newsize = required;
+ } else {
+ do {
+ newsize *= 2;
+ } while(newsize < buf->used + len);
+ }
if(newsize > buf->maxsize)
newsize = buf->maxsize;
char *newdata = realloc(buf->data, newsize);
buf->data = newdata;
buf->size = newsize;
}
- memcpy(buf->data + buf->used, data, len);
- buf->used += len;
+
+ memcpy(buf->data + offset, data, len);
+ if(required > buf->used)
+ buf->used = required;
return len;
}
+static ssize_t buffer_put(struct buffer *buf, const void *data, size_t len) {
+ return buffer_put_at(buf, buf->used, data, len);
+}
+
// Get data from the buffer. data can be NULL.
static ssize_t buffer_get(struct buffer *buf, void *data, size_t len) {
if(len > buf->used)
c->src = src;
c->dst = dst;
+#ifdef UTCP_DEBUG
+#warning debugging
+ c->snd.iss = 0;
+#else
c->snd.iss = rand();
+#endif
c->snd.una = c->snd.iss;
c->snd.nxt = c->snd.iss + 1;
c->rcv.wnd = utcp->mtu;
} *pkt;
pkt = malloc(sizeof pkt->hdr + c->utcp->mtu);
- if(!pkt->data)
+ if(!pkt)
return;
pkt->hdr.src = c->src;
len--;
pkt->hdr.ctl |= FIN;
}
+ c->snd.nxt = c->snd.una + len;
buffer_copy(&c->sndbuf, pkt->data, 0, len);
print_packet(c->utcp, "rtrx", pkt, sizeof pkt->hdr + len);
utcp->send(utcp, pkt, sizeof pkt->hdr + len);
}
int utcp_shutdown(struct utcp_connection *c, int dir) {
- debug("%p shutdown %d at %u\n", c ? c->utcp : NULL, dir, c->snd.last);
+ debug("%p shutdown %d at %u\n", c ? c->utcp : NULL, dir, c ? c->snd.last : 0);
if(!c) {
errno = EFAULT;
return -1;