git: 9front

Download patch

ref: f400ceaf23727abedd6bd68705457206acc28f55
parent: 7539027ad54b690b40d1ef287753a8a0cac5a79a
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Sun May 6 12:33:17 EDT 2012

ip/torrent: limit number of connections

--- a/sys/src/cmd/ip/torrent.c
+++ b/sys/src/cmd/ip/torrent.c
@@ -44,6 +44,8 @@
 
 enum {
 	MAXIO = 16*1024,
+	SRVPROCS = 16,
+	CLIPROCS = 16,
 };
 
 int debug;
@@ -579,10 +581,11 @@
 server(void)
 {
 	char addr[64], adir[40], ldir[40];
-	int afd, lfd, dfd;
+	int afd, lfd, dfd, pid, nprocs;
 	NetConnInfo *ni;
 
 	afd = -1;
+	nprocs = 0;
 	for(port=6881; port<6890; port++){
 		snprint(addr, sizeof(addr), "tcp!*!%d", port);
 		if((afd = announce(addr, adir)) >= 0)
@@ -599,7 +602,13 @@
 			fprint(2, "listen: %r");
 			break;
 		}
-		if(rfork(RFFDG|RFPROC|RFMEM)){
+		while(nprocs >= SRVPROCS)
+			if(waitpid() > 0)
+				nprocs--;
+		nprocs++;
+		if(pid = rfork(RFFDG|RFPROC|RFMEM)){
+			if(pid < 0)
+				nprocs--;
 			close(lfd);
 			continue;
 		}
@@ -610,16 +619,16 @@
 		ni = getnetconninfo(ldir, dfd);
 		peer(dfd, 1, ni ? ni->raddr : "???");
 		if(ni) freenetconninfo(ni);	
-		break;
+		exits(0);
 	}
-	exits(0);
 }
 
 void
 client(char *ip, char *port)
 {
-	static Dict *peers;
+	static Dict *peers, *peerqh, *peerqt;
 	static QLock peerslk;
+	static int nprocs;
 	int try, fd;
 	char *addr;
 	Dict *d;
@@ -630,7 +639,7 @@
 	d = mallocz(sizeof(*d) + 64, 1);
 	snprint(addr = d->str, 64, "tcp!%s!%s", ip, port);
 	qlock(&peerslk);
-	if(dlook(peers, addr)){
+	if(dlook(peers, addr) || dlook(peerqh, addr)){
 		qunlock(&peerslk);
 		free(d);
 		return;
@@ -638,23 +647,44 @@
 	d->len = strlen(addr);
 	d->typ = 'd';
 	d->val = d;
-	d->next = peers;
-	peers = d;
+	d->next = nil;
+	if(peerqt == nil)
+		peerqh = d;
+	else
+		peerqt->next = d;
+	peerqt = d;
+	if(nprocs >= CLIPROCS){
+		qunlock(&peerslk);
+		return;
+	}
+	nprocs++;
 	qunlock(&peerslk);
 
-	if(debug) fprint(2, "client %s\n", addr);
-
-	if(rfork(RFFDG|RFPROC|RFMEM))
+	if(rfork(RFFDG|RFPROC|RFMEM|RFNOWAIT))
 		return;
-	for(try = 0; try < 10; try++){
-		if((fd = dial(addr, nil, nil, nil)) >= 0){
-			if(!peer(fd, 0, addr))
-				break;
-			close(fd);
+	for(;;){
+		qlock(&peerslk);
+		if(d = peerqh){
+			if((peerqh = d->next) == nil)
+				peerqt = nil;
+			d->next = peers;
+			peers = d;
+		} else
+			nprocs--;
+		qunlock(&peerslk);
+		if(d == nil)
+			exits(0);
+		addr = d->str;
+		if(debug) fprint(2, "client %s\n", addr);
+		for(try = 0; try < 5; try++){
+			if((fd = dial(addr, nil, nil, nil)) >= 0){
+				if(!peer(fd, 0, addr))
+					break;
+				close(fd);
+			}
+			sleep((1000<<try)+nrand(5000));
 		}
-		sleep((1000<<try)+nrand(5000));
 	}
-	exits(0);
 }
 
 int
--