Time out inactive peers after 3 minutes.
[doldaconnect.git] / daemon / fnet-dc.c
index d77179d..3fe4950 100644 (file)
@@ -128,6 +128,7 @@ struct dcpeer
     size_t inbufdata, inbufsize;
     size_t curread, totalsize;
     int freeing;
+    struct timer *timeout;
     struct qcommand *queue;
     struct transfer *transfer;
     int state;
@@ -136,7 +137,7 @@ struct dcpeer
     int extended;
     int direction;    /* Using the constants from transfer.h */
     int compress;
-    int hascurpos, notthl;
+    int hascurpos, fetchingtthl, notthl;
     struct tigertreehash tth;
     void *cprsdata;
     char *key;
@@ -444,6 +445,14 @@ static void hubrecvchat(struct socket *sk, struct fnetnode *fn, char *from, char
     free(chat);
 }
 
+static void peertimeout(int cancelled, struct dcpeer *peer)
+{
+    peer->timeout = NULL;
+    if(cancelled)
+       return;
+    freedcpeer(peer);
+}
+
 static void sendadc(struct socket *sk, char *arg)
 {
     char *buf;
@@ -676,6 +685,7 @@ static void requestfile(struct dcpeer *peer)
            sendadc(peer->sk, "0");
            sendadc(peer->sk, "-1");
            qstr(peer->sk, "|");
+           peer->fetchingtthl = 1;
            return;
        }
     }
@@ -1599,6 +1609,8 @@ static void cmd_key(struct socket *sk, struct dcpeer *peer, char *cmd, char *arg
 
 static void startdl(struct dcpeer *peer)
 {
+    if(peer->timeout != NULL)
+       canceltimer(peer->timeout);
     peer->state = PEER_TRNS;
     transferstartdl(peer->transfer, peer->sk);
     peer->sk->readcb = (void (*)(struct socket *, void *))transread;
@@ -1607,6 +1619,8 @@ static void startdl(struct dcpeer *peer)
 
 static void startul(struct dcpeer *peer)
 {
+    if(peer->timeout != NULL)
+       canceltimer(peer->timeout);
     peer->state = PEER_TRNS;
     transferstartul(peer->transfer, peer->sk);
     peer->sk->writecb = (void (*)(struct socket *, void *))transwrite;
@@ -1637,6 +1651,13 @@ static void cmd_filelength(struct socket *sk, struct dcpeer *peer, char *cmd, ch
 
 static void cmd_error(struct socket *sk, struct dcpeer *peer, char *cmd, char *args)
 {
+    if(peer->fetchingtthl)
+    {
+       peer->fetchingtthl = 0;
+       peer->notthl = 1;
+       requestfile(peer);
+       return;
+    }
     if((peer->transfer != NULL) && (peer->transfer->dir == TRNSD_DOWN))
     {
        transferseterror(peer->transfer, TRNSE_NOTFOUND);
@@ -1770,15 +1791,10 @@ static void cmd_get(struct socket *sk, struct dcpeer *peer, char *cmd, char *arg
     } else if(fd >= 0) {
        if((buf2 = icsmbstowcs(args, DCCHARSET, NULL)) != NULL)
            transfersetpath(peer->transfer, buf2);
+       peer->transfer->flags.b.minislot = 1;
     }
     if(fd < 0)
     {
-       if(slotsleft() < 1)
-       {
-           qstr(sk, "$MaxedOut|");
-           freedcpeer(peer);
-           return;
-       }
        if((node = resdcpath(args, DCCHARSET, '\\')) == NULL)
        {
            qstrf(sk, "$Error File not in share|");
@@ -1806,6 +1822,13 @@ static void cmd_get(struct socket *sk, struct dcpeer *peer, char *cmd, char *arg
        freedcpeer(peer);
        return;
     }
+    if(sb.st_size < 65536)
+       peer->transfer->flags.b.minislot = 1;
+    if(!peer->transfer->flags.b.minislot && (slotsleft() < 1)) {
+       qstr(sk, "$MaxedOut|");
+       freedcpeer(peer);
+       return;
+    }
     if((offset != 0) && (lseek(fd, offset, SEEK_SET) < 0))
     {
        close(fd);
@@ -1909,14 +1932,10 @@ static void cmd_getblock(struct socket *sk, struct dcpeer *peer, char *cmd, char
     } else if(fd >= 0) {
        if((buf2 = icsmbstowcs(args, charset, NULL)) != NULL)
            transfersetpath(peer->transfer, buf2);
+       peer->transfer->flags.b.minislot = 1;
     }
     if(fd < 0)
     {
-       if(slotsleft() < 1)
-       {
-           qstr(sk, "$MaxedOut|");
-           return;
-       }
        if((node = resdcpath(p, charset, '\\')) == NULL)
        {
            qstr(sk, "$Error File not in cache|");
@@ -1941,6 +1960,12 @@ static void cmd_getblock(struct socket *sk, struct dcpeer *peer, char *cmd, char
        qstr(sk, "$Error|");
        return;
     }
+    if(sb.st_size < 65536)
+       peer->transfer->flags.b.minislot = 1;
+    if(!peer->transfer->flags.b.minislot && (slotsleft() < 1)) {
+       qstr(sk, "$MaxedOut|");
+       return;
+    }
     if((start != 0) && ((start >= sb.st_size) || (lseek(fd, start, SEEK_SET) < 0)))
     {
        close(fd);
@@ -1993,14 +2018,10 @@ static void cmd_adcget(struct socket *sk, struct dcpeer *peer, char *cmd, char *
     } else if(fd >= 0) {
        if((wbuf = icsmbstowcs(argv[1], "UTF-8", NULL)) != NULL)
            transfersetpath(peer->transfer, wbuf);
+       peer->transfer->flags.b.minislot = 1;
     }
     if(fd < 0)
     {
-       if(slotsleft() < 1)
-       {
-           qstr(sk, "$MaxedOut|");
-           goto out;
-       }
        if(!strncmp(argv[1], "TTH/", 4))
        {
            if((node = findbytth(argv[1] + 4)) == NULL)
@@ -2040,6 +2061,12 @@ static void cmd_adcget(struct socket *sk, struct dcpeer *peer, char *cmd, char *
            qstr(sk, "$Error|");
            goto out;
        }
+       if(sb.st_size < 65536)
+           peer->transfer->flags.b.minislot = 1;
+       if(!peer->transfer->flags.b.minislot && (slotsleft() < 1)) {
+           qstr(sk, "$MaxedOut|");
+           goto out;
+       }
        if((start != 0) && ((start >= sb.st_size) || (lseek(fd, start, SEEK_SET) < 0)))
        {
            qstr(sk, "$Error Offset out of range|");
@@ -2103,6 +2130,8 @@ static void handletthl(struct dcpeer *peer)
     }
     if(peer->curread >= peer->totalsize)
     {
+       if(peer->timeout == NULL)
+           peer->timeout = timercallback(ntime() + 180, (void (*)(int, void *))peertimeout, peer);
        peer->state = PEER_CMD;
        synctigertree(&peer->tth);
        restigertree(&peer->tth, buf);
@@ -2141,9 +2170,12 @@ static void cmd_adcsnd(struct socket *sk, struct dcpeer *peer, char *cmd, char *
            freedcpeer(peer);
            goto out;
        }
+       if(peer->timeout != NULL)
+           canceltimer(peer->timeout);
        peer->state = PEER_TTHL;
        peer->totalsize = numbytes;
        peer->curread = 0;
+       peer->fetchingtthl = 0;
        inittigertree(&peer->tth);
        handletthl(peer);
     } else if(!strcmp(argv[0], "file")) {
@@ -2611,6 +2643,8 @@ static void dctransgotdata(struct transfer *transfer, struct dcpeer *peer)
                {
                    freedcpeer(peer);
                } else {
+                   if(peer->timeout == NULL)
+                       peer->timeout = timercallback(ntime() + 180, (void (*)(int, void *))peertimeout, peer);
                    peer->state = PEER_CMD;
                    endcompress(peer);
                    transfersetstate(transfer, TRNS_HS);
@@ -2914,6 +2948,8 @@ static void freedcpeer(struct dcpeer *peer)
            resettransfer(peer->transfer);
        transferdetach(peer->transfer);
     }
+    if(peer->timeout != NULL)
+       canceltimer(peer->timeout);
     if(peer->sk->data == peer)
        peer->sk->data = NULL;
     peer->sk->readcb = NULL;
@@ -3067,6 +3103,7 @@ static void peerconnect(struct socket *sk, int err, struct fnetnode *fn)
     sk->data = peer;
     socksettos(sk, confgetint("fnet", "fnptos"));
     putsock(sk);
+    peer->timeout = timercallback(ntime() + 180, (void (*)(int, void *))peertimeout, peer);
     sendmynick(peer);
     sendpeerlock(peer);
 }
@@ -3081,6 +3118,7 @@ static void peeraccept(struct socket *sk, struct socket *newsk, void *data)
     newsk->errcb = (void (*)(struct socket *, int, void *))peererror;
     newsk->data = peer;
     socksettos(newsk, confgetint("fnet", "fnptos"));
+    peer->timeout = timercallback(ntime() + 180, (void (*)(int, void *))peertimeout, peer);
 }
 
 static void updatehmlist(void)
@@ -3440,6 +3478,9 @@ static int run(void)
        nextpeer = peer->next;
        if((qcmd = ulqcmd(&peer->queue)) != NULL)
        {
+           if(peer->timeout != NULL)
+               canceltimer(peer->timeout);
+           peer->timeout = timercallback(ntime() + 180, (void (*)(int, void *))peertimeout, peer);
            if(*qcmd->string == '$')
                dispatchcommand(qcmd, peercmds, peer->sk, peer);
            freeqcmd(qcmd);