Properly parse search size expressions as off_t, not int.
[doldaconnect.git] / daemon / fnet-dc.c
index f48d63d..fd7a79d 100644 (file)
@@ -161,6 +161,7 @@ static void updatexmllist(void);
 static void updatexmlbz2list(void);
 static void requestfile(struct dcpeer *peer);
 static void updatelists(int now);
+static int trdestroycb(struct transfer *transfer, struct dcpeer *peer);
 
 static int reservedchar(unsigned char c)
 {
@@ -738,7 +739,6 @@ static void requestfile(struct dcpeer *peer)
            peer->close = 1;
            return;
        }
-       CBREG(peer->transfer, trans_filterout, (int (*)(struct transfer *, wchar_t *, wchar_t *, void *))trresumecb, NULL, peer);
        return;
     }
     if(supports(peer, "adcget"))
@@ -872,7 +872,7 @@ static void cmd_hubname(struct socket *sk, struct fnetnode *fn, char *cmd, char
     struct dchub *hub;
     
     hub = fn->data;
-    if(hub->nativename == NULL)
+    if(hub->nativename != NULL)
        free(hub->nativename);
     hub->nativename = sstrdup(args);
     buf = icmbstowcs(args, hub->charset);
@@ -1586,6 +1586,13 @@ static void cmd_mynick(struct socket *sk, struct dcpeer *peer, char *cmd, char *
     }
 }
 
+static void peerattach(struct dcpeer *peer, struct transfer *transfer)
+{
+    peer->transfer = transfer;
+    CBREG(peer->transfer, trans_filterout, (int (*)(struct transfer *, wchar_t *, wchar_t *, void *))trresumecb, NULL, peer);
+    CBREG(peer->transfer, trans_destroy, (int (*)(struct transfer *, void *))trdestroycb, NULL, peer);
+}
+
 static void cmd_direction(struct socket *sk, struct dcpeer *peer, char *cmd, char *args)
 {
     char *p;
@@ -1633,7 +1640,7 @@ static void cmd_direction(struct socket *sk, struct dcpeer *peer, char *cmd, cha
            transfersetstate(transfer, TRNS_HS);
        }
        transfersetnick(transfer, peer->wcsname);
-       peer->transfer = transfer;
+       peerattach(peer, transfer);
        if(peer->extended)
            sendsupports(peer);
        qstrf(sk, "$Direction %s %i|", (peer->direction == TRNSD_UP)?"Upload":"Download", rand() % 10000);
@@ -1681,7 +1688,7 @@ static void cmd_peerlock(struct socket *sk, struct dcpeer *peer, char *cmd, char
            transfersetstate(transfer, TRNS_HS);
        }
        transfersetnick(transfer, peer->wcsname);
-       peer->transfer = transfer;
+       peerattach(peer, transfer);
        qstrf(sk, "$Direction %s %i|", (peer->direction == TRNSD_UP)?"Upload":"Download", rand() % 10000);
        qstrf(sk, "$Key %s|", key);
        free(key);
@@ -1714,6 +1721,7 @@ static void startul(struct dcpeer *peer)
     peer->state = PEER_TRNS;
     transferstartul(peer->transfer, peer->sk);
     peer->sk->writecb = (void (*)(struct socket *, void *))transwrite;
+    transwrite(peer->sk, peer);
 }
 
 static void cmd_filelength(struct socket *sk, struct dcpeer *peer, char *cmd, char *args)
@@ -2117,6 +2125,7 @@ static void cmd_adcget(struct socket *sk, struct dcpeer *peer, char *cmd, char *
     } else if(fd >= 0) {
        if((wbuf = adc2path(argv[1])) != NULL)
            transfersetpath(peer->transfer, wbuf);
+       free(wbuf);
        peer->transfer->flags.b.minislot = 1;
     }
     if(fd < 0)
@@ -2420,9 +2429,9 @@ static int hubsendchat(struct fnetnode *fn, int public, wchar_t *to, wchar_t *st
     return(0);
 }
 
-static void findsizelimit(struct sexpr *sexpr, int *min, int *max)
+static void findsizelimit(struct sexpr *sexpr, off_t *min, off_t *max)
 {
-    int minl, maxl, minr, maxr, retmin, retmax;
+    off_t minl, maxl, minr, maxr, retmin, retmax;
     
     switch(sexpr->op)
     {
@@ -2466,14 +2475,14 @@ static void findsizelimit(struct sexpr *sexpr, int *min, int *max)
        }
     case SOP_SIZELT:
        retmin = 0;
-       retmax = sexpr->d.n - 1;
+       retmax = sexpr->d.sz - 1;
        break;
     case SOP_SIZEEQ:
-       retmin = sexpr->d.n;
-       retmax = sexpr->d.n;
+       retmin = sexpr->d.sz;
+       retmax = sexpr->d.sz;
        break;
     case SOP_SIZEGT:
-       retmin = sexpr->d.n + 1;
+       retmin = sexpr->d.sz + 1;
        retmax = -1;
        break;
     default:
@@ -2524,7 +2533,7 @@ static int hubsearch(struct fnetnode *fn, struct search *srch, struct srchfnnlis
     size_t sstrsize, sstrdata;
     struct sockaddr *name;
     socklen_t namelen;
-    int minsize, maxsize;
+    off_t minsize, maxsize;
     struct hash *hash;
     
     hub = fn->data;
@@ -2557,10 +2566,10 @@ static int hubsearch(struct fnetnode *fn, struct search *srch, struct srchfnnlis
        if(minsize != 0)
        {
            sizebuf2(sstr, sstrdata + 32, 1);
-           sstrdata += snprintf(sstr + sstrdata, sstrsize - sstrdata, "T?F?%i?1?", minsize);
+           sstrdata += snprintf(sstr + sstrdata, sstrsize - sstrdata, "T?F?%ji?1?", (intmax_t)minsize);
        } else if(maxsize != -1) {
            sizebuf2(sstr, sstrdata + 32, 1);
-           sstrdata += snprintf(sstr + sstrdata, sstrsize - sstrdata, "T?T?%i?1?", maxsize);
+           sstrdata += snprintf(sstr + sstrdata, sstrsize - sstrdata, "T?T?%ji?1?", (intmax_t)maxsize);
        } else {
            bufcat(sstr, "F?F?0?1?", 8);
        }
@@ -2688,28 +2697,24 @@ static void dctransgotdata(struct transfer *transfer, struct dcpeer *peer)
        {
            if((buf = sockgetinbuf(peer->trpipe, &bufsize)) != NULL)
            {
-               if((transfer->endpos >= 0) && (transfer->curpos + bufsize >= transfer->endpos))
-                   bufsize = transfer->endpos - transfer->curpos;
-               if(bufsize > 0) {
-                   if(peer->compress == CPRS_NONE)
+               if(peer->compress == CPRS_NONE)
+               {
+                   sockqueue(peer->sk, buf, bufsize);
+               } else if(peer->compress == CPRS_ZLIB) {
+                   cstr = peer->cprsdata;
+                   cstr->next_in = buf;
+                   cstr->avail_in = bufsize;
+                   while(cstr->avail_in > 0)
                    {
-                       sockqueue(peer->sk, buf, bufsize);
-                   } else if(peer->compress == CPRS_ZLIB) {
-                       cstr = peer->cprsdata;
-                       cstr->next_in = buf;
-                       cstr->avail_in = bufsize;
-                       while(cstr->avail_in > 0)
+                       cstr->next_out = outbuf;
+                       cstr->avail_out = sizeof(outbuf);
+                       if((ret = deflate(cstr, 0)) != Z_OK)
                        {
-                           cstr->next_out = outbuf;
-                           cstr->avail_out = sizeof(outbuf);
-                           if((ret = deflate(cstr, 0)) != Z_OK)
-                           {
-                               flog(LOG_WARNING, "bug? deflate() did not return Z_OK (but rather %i)", ret);
-                               freedcpeer(peer);
-                               return;
-                           }
-                           sockqueue(peer->sk, outbuf, sizeof(outbuf) - cstr->avail_out);
+                           flog(LOG_WARNING, "bug? deflate() did not return Z_OK (but rather %i)", ret);
+                           freedcpeer(peer);
+                           return;
                        }
+                       sockqueue(peer->sk, outbuf, sizeof(outbuf) - cstr->avail_out);
                    }
                }
                free(buf);
@@ -2737,7 +2742,7 @@ static void dctransgotdata(struct transfer *transfer, struct dcpeer *peer)
                }
                if(peer->ptclose)
                {
-                   freedcpeer(peer);
+                   peer->close = 1;
                } else {
                    if(peer->timeout == NULL)
                        peer->timeout = timercallback(ntime() + 180, (void (*)(int, void *))peertimeout, peer);
@@ -2753,32 +2758,22 @@ static void dctransgotdata(struct transfer *transfer, struct dcpeer *peer)
     }
 }
 
-void trpiperead(struct socket *sk, struct dcpeer *peer)
-{
-    dctransgotdata(peer->transfer, peer);
-}
-
-void trpipewrite(struct socket *sk, struct dcpeer *peer)
+static void peerdetach(struct dcpeer *peer)
 {
-}
-
-void trpipeerr(struct socket *sk, int errno, struct dcpeer *peer)
-{
-    peer->state = PEER_SYNC;
-    dctransgotdata(peer->transfer, peer);
     CBUNREG(peer->transfer, trans_filterout, peer);
+    CBUNREG(peer->transfer, trans_destroy, peer);
+    peer->trpipe->pnext = NULL;
+    closesock(peer->trpipe);
+    quitsock(peer->trpipe);
+    peer->trpipe = NULL;
+    peer->transfer = NULL;
 }
 
-static struct socket *mktrpipe(struct dcpeer *peer)
+static int trdestroycb(struct transfer *transfer, struct dcpeer *peer)
 {
-    struct socket *sk;
-    
-    sk = netsockpipe();
-    sk->data = peer;
-    sk->readcb = (void (*)(struct socket *, void *))trpiperead;
-    sk->writecb = (void (*)(struct socket *, void *))trpipewrite;
-    sk->errcb = (void (*)(struct socket *, int, void *))trpipeerr;
-    return(sk);
+    peerdetach(peer);
+    peer->close = 1;
+    return(0);
 }
 
 static void transread(struct socket *sk, struct dcpeer *peer)
@@ -2786,22 +2781,26 @@ static void transread(struct socket *sk, struct dcpeer *peer)
     void *buf;
     size_t bufsize;
     
-    if(sockqueueleft(peer->trpipe) < 0)
+    if(peer->transfer == NULL) {
+       freedcpeer(peer);
        return;
-    if((buf = sockgetinbuf(sk, &bufsize)) == NULL)
+    }
+    if(sockqueueleft(peer->trpipe) < 0)
        return;
-    if(peer->transfer == NULL)
+    if((buf = sockgetinbuf(sk, &bufsize)) != NULL)
     {
+       if(peer->transfer == NULL)
+       {
+           free(buf);
+           freedcpeer(peer);
+           return;
+       }
+       sockqueue(peer->trpipe, buf, bufsize);
        free(buf);
-       freedcpeer(peer);
-       return;
     }
-    sockqueue(peer->trpipe, buf, bufsize);
-    free(buf);
     if(peer->transfer->curpos >= peer->transfer->size)
     {
-       closesock(peer->trpipe);
-       quitsock(peer->trpipe);
+       peerdetach(peer);
        peer->close = 1;
        return;
     }
@@ -2816,8 +2815,7 @@ static void transerr(struct socket *sk, int err, struct dcpeer *peer)
        freedcpeer(peer);
        return;
     }
-    closesock(peer->trpipe);
-    quitsock(peer->trpipe);
+    peerdetach(peer);
     peer->close = 1;
 }
 
@@ -2831,6 +2829,39 @@ static void transwrite(struct socket *sk, struct dcpeer *peer)
        return;
     }
     dctransgotdata(peer->transfer, peer);
+    sockread(peer->trpipe);
+}
+
+static void trpiperead(struct socket *sk, struct dcpeer *peer)
+{
+    dctransgotdata(peer->transfer, peer);
+}
+
+static void trpipewrite(struct socket *sk, struct dcpeer *peer)
+{
+    transread(peer->sk, peer);
+}
+
+static void trpipeerr(struct socket *sk, int errno, struct dcpeer *peer)
+{
+    peer->state = PEER_SYNC;
+    dctransgotdata(peer->transfer, peer);
+    peerdetach(peer);
+    if(peer->state != PEER_CMD)
+       peer->close = 1;
+}
+
+static struct socket *mktrpipe(struct dcpeer *peer)
+{
+    struct socket *sk;
+    
+    sk = netsockpipe();
+    sk->pnext = peer->sk;
+    sk->data = peer;
+    sk->readcb = (void (*)(struct socket *, void *))trpiperead;
+    sk->writecb = (void (*)(struct socket *, void *))trpipewrite;
+    sk->errcb = (void (*)(struct socket *, int, void *))trpipeerr;
+    return(sk);
 }
 
 static void udpread(struct socket *sk, void *data)
@@ -3109,7 +3140,6 @@ static struct dcpeer *newdcpeer(struct socket *sk)
     
     new = smalloc(sizeof(*new));
     memset(new, 0, sizeof(*new));
-    new->transfer = NULL;
     getsock(sk);
     new->sk = sk;
     if(confgetint("dc", "dcppemu"))
@@ -3134,18 +3164,8 @@ static void freedcpeer(struct dcpeer *peer)
        peer->next->prev = peer->prev;
     if(peer->prev != NULL)
        peer->prev->next = peer->next;
-    if(peer->trpipe != NULL) {
-       closesock(peer->trpipe);
-       quitsock(peer->trpipe);
-    }
     if(peer->transfer != NULL)
-    {
-       CBUNREG(peer->transfer, trans_filterout, peer);
-       if(peer->transfer->dir == TRNSD_UP)
-           peer->transfer->close = 1;
-       if(peer->transfer->dir == TRNSD_DOWN)
-           resettransfer(peer->transfer);
-    }
+       peerdetach(peer);
     if(peer->timeout != NULL)
        canceltimer(peer->timeout);
     if(peer->sk->data == peer)
@@ -3198,7 +3218,7 @@ static void hubdestroy(struct fnetnode *fn)
     struct qcommand *qcmd;
     
     hub = (struct dchub *)fn->data;
-    putsock(hub->sk);
+    quitsock(hub->sk);
     while((qcmd = ulqcmd(&hub->queue)) != NULL)
        freeqcmd(qcmd);
     if(hub->supports != NULL)
@@ -3247,6 +3267,9 @@ static void peerread(struct socket *sk, struct dcpeer *peer)
     if(peer->state == PEER_CMD) {
        if((peer->queue.size > 50) || (peer->inbufdata > 65536))
            return;
+    } else if(peer->state == PEER_TTHL) {
+    } else {
+       return;
     }
     if((newbuf = sockgetinbuf(sk, &datalen)) == NULL)
        return;