+ sockdebug(2, sk, "read %zi bytes", *size);
+ return(buf);
+}
+
+void sockqueue(struct socket *sk, void *data, size_t size)
+{
+ struct dgrambuf *new;
+ struct sockaddr *remote;
+ socklen_t remotelen;
+
+ sockdebug(2, sk, "queued %zi bytes", size);
+ if(size == 0)
+ return;
+ if(sk->state == SOCK_STL)
+ return;
+ if(sk->dgram) {
+ if(sockpeeraddr(sk, &remote, &remotelen))
+ return;
+ new = smalloc(sizeof(*new));
+ new->next = NULL;
+ memcpy(new->data = smalloc(size), data, new->size = size);
+ new->addr = remote;
+ new->addrlen = remotelen;
+ if(sk->back->buf.d.l == NULL)
+ {
+ sk->back->buf.d.l = sk->back->buf.d.f = new;
+ } else {
+ sk->back->buf.d.l->next = new;
+ sk->back->buf.d.l = new;
+ }
+ } else {
+ sizebuf(&(sk->back->buf.s.buf), &(sk->back->buf.s.bufsize), sk->back->buf.s.datasize + size, 1, 1);
+ memcpy(sk->back->buf.s.buf + sk->back->buf.s.datasize, data, size);
+ sk->back->buf.s.datasize += size;
+ }
+ linksock(&rbatch, sk->back);
+}
+
+void sockqueuedg(struct socket *sk, struct dgrambuf *dg)
+{
+ if(sk->state == SOCK_STL) {
+ freedgbuf(dg);
+ return;
+ }
+ if(!sk->dgram) {
+ flog(LOG_ERR, "BUG: sockqueuedg called on non-dgram socket");
+ freedgbuf(dg);
+ return;
+ }
+ dg->next = NULL;
+ if(sk->back->buf.d.l == NULL)
+ {
+ sk->back->buf.d.l = sk->back->buf.d.f = dg;
+ } else {
+ sk->back->buf.d.l->next = dg;
+ sk->back->buf.d.l = dg;
+ }
+ linksock(&rbatch, sk->back);
+}
+
+void sockerror(struct socket *sk, int en)
+{
+ sksetstate(sk, SOCK_STL);
+ if(sk->back->errcb != NULL)
+ sk->back->errcb(sk->back, en, sk->back->data);