From 81286a224f14fa0494e820739587616d8c559035 Mon Sep 17 00:00:00 2001
From: Fredrik Tolf <fredrik@dolda2000.com>
Date: Fri, 21 Mar 2008 18:33:23 +0100
Subject: [PATCH] First attempt at replacing sockblock with autoblocking.

---
 daemon/fnet-dc.c  | 35 +++++++++++++++++------------------
 daemon/net.c      | 24 +++++++++++++++---------
 daemon/net.h      |  6 ++++--
 daemon/transfer.c | 12 ++++--------
 4 files changed, 40 insertions(+), 37 deletions(-)

diff --git a/daemon/fnet-dc.c b/daemon/fnet-dc.c
index 317a133..708215a 100644
--- a/daemon/fnet-dc.c
+++ b/daemon/fnet-dc.c
@@ -2691,7 +2691,7 @@ static void dctransgotdata(struct transfer *transfer, struct dcpeer *peer)
     
     if((peer->state == PEER_TRNS) || (peer->state == PEER_SYNC))
     {
-	if(sockqueuesize(peer->sk) < 65536)
+	if(sockqueueleft(peer->sk) > 0)
 	{
 	    if((buf = transfergetdata(transfer, &bufsize)) != NULL)
 	    {
@@ -2762,18 +2762,14 @@ static void dctransendofdata(struct transfer *transfer, struct dcpeer *peer)
     dctransgotdata(transfer, peer);
 }
 
-static void dcwantdata(struct transfer *transfer, struct dcpeer *peer)
-{
-    if(transferdatasize(transfer) < 65536)
-	sockblock(peer->sk, 0);
-}
-
 static void transread(struct socket *sk, struct dcpeer *peer)
 {
     void *buf;
     size_t bufsize;
     struct transfer *transfer;
     
+    if(transferdatasize(peer->transfer) < 0)
+	return;
     if((buf = sockgetinbuf(sk, &bufsize)) == NULL)
 	return;
     if(peer->transfer == NULL)
@@ -2791,8 +2787,12 @@ static void transread(struct socket *sk, struct dcpeer *peer)
 	transferendofdata(transfer);
 	return;
     }
-    if(transferdatasize(peer->transfer) > 65535)
-	sockblock(sk, 1);
+}
+
+static void dcwantdata(struct transfer *transfer, struct dcpeer *peer)
+{
+    if(transferdatasize(transfer) > 0)
+	transread(peer->sk, peer);
 }
 
 static void transerr(struct socket *sk, int err, struct dcpeer *peer)
@@ -2993,6 +2993,8 @@ static void hubread(struct socket *sk, struct fnetnode *fn)
     char *p, *p2;
     
     hub = (struct dchub *)fn->data;
+    if(hub->queue.size > 1000)
+	return;
     if((newbuf = sockgetinbuf(sk, &datalen)) == NULL)
 	return;
     if(hub->inbufdata > 500000) /* Discard possible malicious data */
@@ -3016,8 +3018,6 @@ static void hubread(struct socket *sk, struct fnetnode *fn)
 	p = p2;
     }
     memmove(hub->inbuf, p, hub->inbufdata -= p - hub->inbuf);
-    if(hub->queue.size > 1000)
-	sockblock(sk, 1);
 }
 
 static void huberr(struct socket *sk, int err, struct fnetnode *fn)
@@ -3234,6 +3234,10 @@ static void peerread(struct socket *sk, struct dcpeer *peer)
     size_t datalen, cnlen;
     struct command *cmd;
 
+    if(peer->state == PEER_CMD) {
+	if((peer->queue.size > 50) || (peer->inbufdata > 65536))
+	    return;
+    }
     if((newbuf = sockgetinbuf(sk, &datalen)) == NULL)
 	return;
     sizebuf2(peer->inbuf, peer->inbufdata + datalen, 1);
@@ -3259,16 +3263,11 @@ static void peerread(struct socket *sk, struct dcpeer *peer)
 	    {
 		peer->state = PEER_STOP;
 		break;
-	    } else {
-		if(peer->queue.size > 50)
-		    sockblock(sk, 1);
 	    }
 	}
     } else if(peer->state == PEER_TTHL) {
 	handletthl(peer);
     }
-    if(peer->inbufdata > 500000)
-	sockblock(sk, 1);
 }
 
 static void peererror(struct socket *sk, int err, struct dcpeer *peer)
@@ -3772,7 +3771,7 @@ static int run(void)
 	    quota--;
 	}
 	if(hub->queue.size < 1000)
-	    sockblock(hub->sk, 0);
+	    hubread(hub->sk, fn);
 	if(quota < 1)
 	    break;
     }
@@ -3791,7 +3790,7 @@ static int run(void)
 	    quota--;
 	}
 	if((peer->queue.size < 50) && (peer->inbufdata < 500000))
-	    sockblock(peer->sk, 0);
+	    peerread(peer->sk, peer);
 	if(quota < 1)
 	    break;
     }
diff --git a/daemon/net.c b/daemon/net.c
index 7a68dae..d64e8c8 100644
--- a/daemon/net.c
+++ b/daemon/net.c
@@ -211,6 +211,7 @@ static struct socket *newsock1(int dgram)
     new->refcount = 1;
     new->state = -1;
     new->dgram = dgram;
+    new->maxbuf = 65536;
     numsocks++;
     return(new);
 }
@@ -756,9 +757,14 @@ size_t sockgetdatalen(struct socket *sk)
     return(ret);
 }
 
-size_t sockqueuesize(struct socket *sk)
+/* size_t sockqueuesize(struct socket *sk) */
+/* { */
+/*     return(sockgetdatalen(sk->back)); */
+/* } */
+
+ssize_t sockqueueleft(struct socket *sk)
 {
-    return(sockgetdatalen(sk->back));
+    return(sk->back->maxbuf - sockgetdatalen(sk->back));
 }
 
 /*
@@ -1038,7 +1044,7 @@ int pollsocks(int timeout)
     for(maxfd = 0, ufd = ufds; ufd != NULL; ufd = ufd->next) {
 	if(ufd->fd < 0)
 	    continue;
-	if(!ufd->ignread)
+	if(!ufd->ignread && ((ufd->sk == NULL) || (sockqueueleft(ufd->sk) > 0)))
 	    FD_SET(ufd->fd, &rfds);
 	if(ufd->sk != NULL) {
 	    if(sockgetdatalen(ufd->sk) > 0)
@@ -1529,13 +1535,13 @@ int getucred(struct socket *sk, uid_t *uid, gid_t *gid)
     return(0);
 }
 
-void sockblock(struct socket *sk, int block)
-{
-    struct ufd *ufd;
+/* void sockblock(struct socket *sk, int block) */
+/* { */
+/*     struct ufd *ufd; */
     
-    ufd = getskufd(sk);
-    ufd->ignread = block;
-}
+/*     ufd = getskufd(sk); */
+/*     ufd->ignread = block; */
+/* } */
 
 int sockfamily(struct socket *sk)
 {
diff --git a/daemon/net.h b/daemon/net.h
index adf4831..24e7ca5 100644
--- a/daemon/net.h
+++ b/daemon/net.h
@@ -45,6 +45,7 @@ struct socket
     int state;
     int dgram;
     int eos;
+    size_t maxbuf;
     struct socket *back, *pnext;
     union
     {
@@ -84,7 +85,8 @@ int pollsocks(int timeout);
 void freedgbuf(struct dgrambuf *dg);
 void sockqueue(struct socket *sk, void *data, size_t size);
 void sockerror(struct socket *sk, int en);
-size_t sockqueuesize(struct socket *sk);
+/* size_t sockqueuesize(struct socket *sk); */
+ssize_t sockqueueleft(struct socket *sk);
 int netresolve(char *addr, void (*callback)(struct sockaddr *addr, int addrlen, void *data), void *data);
 struct socket *netcsdgram(struct sockaddr *name, socklen_t namelen);
 struct socket *netdgramconn(struct socket *sk, struct sockaddr *addr, socklen_t addrlen);
@@ -102,7 +104,7 @@ int addreq(struct sockaddr *x, struct sockaddr *y);
 char *formataddress(struct sockaddr *arg, socklen_t arglen);
 char *formatsockpeer(struct socket *sk);
 void sockpushdata(struct socket *sk, void *buf, size_t size);
-void sockblock(struct socket *sk, int block);
+/* void sockblock(struct socket *sk, int block); */
 int sockpeeraddr(struct socket *sk, struct sockaddr **namebuf, socklen_t *lenbuf);
 int getucred(struct socket *sk, uid_t *uid, gid_t *gid);
 int sockfamily(struct socket *sk);
diff --git a/daemon/transfer.c b/daemon/transfer.c
index 433ceb1..b4765ae 100644
--- a/daemon/transfer.c
+++ b/daemon/transfer.c
@@ -234,9 +234,7 @@ static void transexpire(int cancelled, struct transfer *transfer)
 
 static void transferread(struct socket *sk, struct transfer *transfer)
 {
-    if(sockgetdatalen(sk) >= 65536)
-	sockblock(sk, 1);
-    if((transfer->iface != NULL) && (transfer->iface->gotdata != NULL))
+    if((sockgetdatalen(sk) > 0) && (transfer->iface != NULL) && (transfer->iface->gotdata != NULL))
 	transfer->iface->gotdata(transfer, transfer->ifacedata);
 }
 
@@ -278,7 +276,7 @@ void transferendofdata(struct transfer *transfer)
 
 size_t transferdatasize(struct transfer *transfer)
 {
-    return(sockqueuesize(transfer->localend));
+    return(sockqueueleft(transfer->localend));
 }
 
 void *transfergetdata(struct transfer *transfer, size_t *size)
@@ -287,7 +285,6 @@ void *transfergetdata(struct transfer *transfer, size_t *size)
     
     if(transfer->localend == NULL)
 	return(NULL);
-    sockblock(transfer->localend, 0);
     time(&transfer->activity);
     if((buf = sockgetinbuf(transfer->localend, size)) == NULL)
 	return(NULL);
@@ -311,7 +308,6 @@ void transferprepul(struct transfer *transfer, off_t size, off_t start, off_t en
     transfersetsize(transfer, size);
     transfer->curpos = start;
     transfer->endpos = end;
-    sockblock(lesk, 1);
     transfersetlocalend(transfer, lesk);
 }
 
@@ -326,7 +322,7 @@ void transferstartul(struct transfer *transfer, struct socket *sk)
     transfersetstate(transfer, TRNS_MAIN);
     socksettos(sk, confgetint("transfer", "ultos"));
     if(transfer->localend != NULL)
-	sockblock(transfer->localend, 0);
+	transferread(transfer->localend, transfer);
 }
 
 void transfersetlocalend(struct transfer *transfer, struct socket *sk)
@@ -716,7 +712,7 @@ int forkfilter(struct transfer *transfer)
      * the fd, and thus it closes it. Until I can find out whyever the
      * kernel gives a POLLIN on the fd (if I can at all...), I'll just
      * set ignread on insock for now. */
-    sockblock(insock, 1);
+/*     sockblock(insock, 1); */
     transfer->filter = pid;
     transfersetlocalend(transfer, insock);
     getsock(transfer->filterout = outsock);
-- 
2.11.0