Merge branch 'socket' into transsock
authorFredrik Tolf <fredrik@dolda2000.com>
Fri, 17 Oct 2008 23:12:36 +0000 (01:12 +0200)
committerFredrik Tolf <fredrik@dolda2000.com>
Fri, 17 Oct 2008 23:12:36 +0000 (01:12 +0200)
1  2 
daemon/fnet-dc.c
daemon/net.c

diff --combined daemon/fnet-dc.c
@@@ -122,7 -122,6 +122,7 @@@ struct dcpee
      struct timer *timeout;
      struct qcmdqueue queue;
      struct transfer *transfer;
 +    struct socket *trpipe;
      int state;
      int ptclose;      /* Close after transfer is complete */
      int accepted;     /* If false, we connected, otherwise, we accepted */
  };
  
  static struct fnet dcnet;
 -static struct transferiface dctransfer;
  static struct socket *udpsock = NULL;
  static struct lport *tcpsock = NULL;
  static struct dcpeer *peers = NULL;
@@@ -150,7 -150,6 +150,7 @@@ static char *xmllistname = NULL
  static char *xmlbz2listname = NULL;
  static struct timer *listwritetimer = NULL;
  
 +static struct socket *mktrpipe(struct dcpeer *peer);
  static void peerconnect(struct socket *sk, int err, struct fnetnode *fn);
  static void freedcpeer(struct dcpeer *peer);
  static void transread(struct socket *sk, struct dcpeer *peer);
@@@ -1323,6 -1322,7 +1323,6 @@@ static void cmd_connecttome(struct sock
  {
      char *p;
      struct dchub *hub;
 -    struct socket *newsk;
      struct sockaddr_in addr;
      
      hub = fn->data;
      addr.sin_port = htons(atoi(p));
      if(!inet_aton(args, &addr.sin_addr))
        return;
 -    newsk = netcsconn((struct sockaddr *)&addr, sizeof(addr), (void (*)(struct socket *, int, void *))peerconnect, fn);
 +    putsock(netcsconn((struct sockaddr *)&addr, sizeof(addr), (void (*)(struct socket *, int, void *))peerconnect, fn));
      getfnetnode(fn);
      hubhandleaction(sk, fn, cmd, args);
  }
@@@ -1622,14 -1622,14 +1622,14 @@@ static void cmd_direction(struct socke
                peer->close = 1;
                return;
            }
 -          transfer = newupload(peer->fn, &dcnet, peer->wcsname, &dctransfer, peer);
 +          transfer = newupload(peer->fn, &dcnet, peer->wcsname, (peer->trpipe = mktrpipe(peer))->back);
        } else {
            if((transfer = finddownload(peer->wcsname)) == NULL)
            {
                peer->close = 1;
                return;
            }
 -          transferattach(transfer, &dctransfer, peer);
 +          transferattach(transfer, (peer->trpipe = mktrpipe(peer))->back);
            transfersetstate(transfer, TRNS_HS);
        }
        transfersetnick(transfer, peer->wcsname);
@@@ -1674,10 -1674,10 +1674,10 @@@ static void cmd_peerlock(struct socket 
                return;
            }
            peer->direction = TRNSD_UP;
 -          transfer = newupload(peer->fn, &dcnet, peer->wcsname, &dctransfer, peer);
 +          transfer = newupload(peer->fn, &dcnet, peer->wcsname, (peer->trpipe = mktrpipe(peer))->back);
        } else {
            peer->direction = TRNSD_DOWN;
 -          transferattach(transfer, &dctransfer, peer);
 +          transferattach(transfer, (peer->trpipe = mktrpipe(peer))->back);
            transfersetstate(transfer, TRNS_HS);
        }
        transfersetnick(transfer, peer->wcsname);
@@@ -1714,7 -1714,6 +1714,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)
@@@ -2118,6 -2117,7 +2118,7 @@@ static void cmd_adcget(struct socket *s
      } 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)
@@@ -2675,6 -2675,13 +2676,6 @@@ static struct command peercmds[] 
  };
  #undef cc
  
 -static void dctransdetach(struct transfer *transfer, struct dcpeer *peer)
 -{
 -    CBUNREG(transfer, trans_filterout, peer);
 -    peer->transfer = NULL;
 -    peer->close = 1;
 -}
 -
  static void dctransgotdata(struct transfer *transfer, struct dcpeer *peer)
  {
      int ret;
      {
        if(sockqueueleft(peer->sk) > 0)
        {
 -          if((buf = transfergetdata(transfer, &bufsize)) != NULL)
 +          if((buf = sockgetinbuf(peer->trpipe, &bufsize)) != NULL)
            {
                if(peer->compress == CPRS_NONE)
                {
      }
  }
  
 -static void dctransendofdata(struct transfer *transfer, struct dcpeer *peer)
 -{
 -    peer->state = PEER_SYNC;
 -    dctransgotdata(transfer, peer);
 -}
 -
  static void transread(struct socket *sk, struct dcpeer *peer)
  {
      void *buf;
      size_t bufsize;
 -    struct transfer *transfer;
      
 -    if(transferdatasize(peer->transfer) < 0)
 +    if(sockqueueleft(peer->trpipe) < 0)
        return;
 -    if((buf = sockgetinbuf(sk, &bufsize)) == NULL)
 -      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;
      }
 -    transferputdata(peer->transfer, buf, bufsize);
 -    free(buf);
      if(peer->transfer->curpos >= peer->transfer->size)
      {
 -      transfer = peer->transfer;
 -      transferdetach(transfer);
 -      transferendofdata(transfer);
 +      closesock(peer->trpipe);
 +      quitsock(peer->trpipe);
 +      peer->trpipe = NULL;
 +      peer->transfer = NULL;
 +      peer->close = 1;
        return;
      }
  }
  
 -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)
  {
      struct transfer *transfer;
        freedcpeer(peer);
        return;
      }
 -    transferdetach(transfer);
 -    transferendofdata(transfer);
 +    closesock(peer->trpipe);
 +    quitsock(peer->trpipe);
 +    peer->trpipe = NULL;
 +    peer->transfer = NULL;
 +    peer->close = 1;
  }
  
  static void transwrite(struct socket *sk, struct dcpeer *peer)
      dctransgotdata(peer->transfer, peer);
  }
  
 +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);
 +    CBUNREG(peer->transfer, trans_filterout, peer);
 +}
 +
 +static struct socket *mktrpipe(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);
 +}
 +
  static void udpread(struct socket *sk, void *data)
  {
      char *buf, *p, *p2, *hashbuf;
@@@ -3137,13 -3122,8 +3138,13 @@@ static void freedcpeer(struct dcpeer *p
        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)
@@@ -3229,6 -3209,14 +3230,6 @@@ static void hubkill(struct fnetnode *fn
      closesock(hub->sk);
  }
  
 -static struct transferiface dctransfer =
 -{
 -    .detach = (void (*)(struct transfer *, void *))dctransdetach,
 -    .gotdata = (void (*)(struct transfer *, void *))dctransgotdata,
 -    .endofdata = (void (*)(struct transfer *, void *))dctransendofdata,
 -    .wantdata = (void (*)(struct transfer *, void *))dcwantdata
 -};
 -
  static struct fnet dcnet =
  {
      .name = L"dc",
@@@ -3250,9 -3238,6 +3251,9 @@@ static void peerread(struct socket *sk
      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;
@@@ -3299,6 -3284,7 +3300,6 @@@ static void peerconnect(struct socket *
      if(err != 0)
      {
        putfnetnode(fn);
 -      putsock(sk);
        return;
      }
      hub = fn->data;
      sk->errcb = (void (*)(struct socket *, int, void *))peererror;
      sk->data = peer;
      socksettos(sk, confgetint("fnet", "fnptos"));
 -    putsock(sk);
      peer->timeout = timercallback(ntime() + 180, (void (*)(int, void *))peertimeout, peer);
      sendmynick(peer);
      sendpeerlock(peer);
diff --combined daemon/net.c
@@@ -66,8 -66,6 +66,6 @@@ static struct configvar myvars[] 
       * and net.visibleipv4 are unspecified the address of the hub
       * connection is used. */
      {CONF_VAR_STRING, "publicif", {.str = L""}},
-     /* Diffserv should be supported on IPv4, too, but I don't know the
-      * API to do that. */
      /** The Diffserv value to use on IPv6 connections when the
       * minimize cost TOS value is used (see the TOS VALUES
       * section). */
       * minimize delay TOS value is used (see the TOS VALUES
       * section). */
      {CONF_VAR_INT, "diffserv-mindelay", {.num = 0}},
+     /** If enabled, the IP TOS interface will be used to set Diffserv
+      * codepoints on IPv4 sockets, by shifting the DSCP value two bits
+      * to the left (remember, the DSCP field in the IPv4 header is
+      * defined as the 6 uppermost bits of the TOS field, the lower two
+      * being left for ECN). This may only work on Linux. */
+     {CONF_VAR_BOOL, "dscp-tos", {.num = 0}},
      {CONF_VAR_END}
  };
  
@@@ -234,15 -238,6 +238,15 @@@ static void sksetstate(struct socket *s
      sk->back->state = state;
  }
  
 +struct socket *netsockpipe(void)
 +{
 +    struct socket *sk;
 +    
 +    sk = sockpair(0);
 +    sksetstate(sk, SOCK_EST);
 +    return(sk);
 +}
 +
  static void closeufd(struct ufd *ufd)
  {
      if(ufd->fd != -1)
@@@ -358,41 -353,10 +362,41 @@@ void getsock(struct socket *sk
      sk->refcount++;
  }
  
 +static void sockdebug(int level, struct socket *sk, char *format, ...)
 +{
 +    va_list args;
 +    char *tb;
 +    
 +    if((sk->dbgnm == NULL) || (level > sk->dbglvl))
 +      return;
 +    va_start(args, format);
 +    tb = vsprintf2(format, args);
 +    va_end(args);
 +    fprintf(stderr, "%s: %s\n", sk->dbgnm, tb);
 +    free(tb);
 +}
 +
 +void socksetdebug(struct socket *sk, int level, char *nm, ...)
 +{
 +    va_list args;
 +    char *tb;
 +    
 +    va_start(args, nm);
 +    tb = vsprintf2(nm, args);
 +    va_end(args);
 +    sk->dbgnm = sprintf2("%s (f)", tb);
 +    sk->back->dbgnm = sprintf2("%s (b)", tb);
 +    free(tb);
 +    sk->dbglvl = level;
 +    sk->back->dbglvl = level;
 +    sockdebug(1, sk, "enabled debugging");
 +}
 +
  static void freesock(struct socket *sk)
  {
      struct dgrambuf *buf;
      
 +    sockdebug(1, sk, "freeing socket");
      if(sk->dgram) {
        while((buf = sk->buf.d.f) != NULL) {
            sk->buf.d.f = buf->next;
        if(sk->buf.s.buf != NULL)
            free(sk->buf.s.buf);
      }
 +    if(sk->dbgnm != NULL)
 +      free(sk->dbgnm);
      free(sk);
      numsocks--;
  }
@@@ -423,14 -385,6 +427,14 @@@ void putsock(struct socket *sk
      }
  }
  
 +void quitsock(struct socket *sk)
 +{
 +    sk->readcb = NULL;
 +    sk->writecb = NULL;
 +    sk->errcb = NULL;
 +    putsock(sk);
 +}
 +
  static void linksock(struct scons **list, struct socket *sk)
  {
      struct scons *sc;
@@@ -509,7 -463,6 +513,7 @@@ void *sockgetinbuf(struct socket *sk, s
        if((sk->buf.s.buf == NULL) || (sk->buf.s.datasize == 0))
        {
            *size = 0;
 +          sockdebug(2, sk, "read 0 bytes", *size);
            return(NULL);
        }
        buf = sk->buf.s.buf;
        sk->buf.s.bufsize = sk->buf.s.datasize = 0;
        sockread(sk);
      }
 +    sockdebug(2, sk, "read %zi bytes", *size);
      return(buf);
  }
  
@@@ -528,7 -480,6 +532,7 @@@ void sockqueue(struct socket *sk, void 
      struct sockaddr *remote;
      socklen_t remotelen;
      
 +    sockdebug(2, sk, "queued %zi bytes", size);
      if(size == 0)
        return;
      if(sk->state == SOCK_STL)
@@@ -789,7 -740,6 +793,7 @@@ static int sockflush(struct ufd *ufd
  
  void closesock(struct socket *sk)
  {
 +    sockdebug(1, sk, "closed");
      sksetstate(sk, SOCK_STL);
      if(sk->back->eos == 0)
        sk->back->eos = 1;
@@@ -816,18 -766,6 +820,18 @@@ size_t sockgetdatalen(struct socket *sk
  /*     return(sockgetdatalen(sk->back)); */
  /* } */
  
 +size_t socktqueuesize(struct socket *sk)
 +{
 +    size_t ret;
 +    
 +    ret = 0;
 +    while(1) {
 +      ret += sockgetdatalen(sk->back);
 +      if((sk = sk->back->pnext) == NULL)
 +          return(ret);
 +    }
 +}
 +
  ssize_t sockqueueleft(struct socket *sk)
  {
      return(sk->back->maxbuf - sockgetdatalen(sk->back));
@@@ -1003,8 -941,6 +1007,8 @@@ struct socket *netcsconn(struct sockadd
        memcpy(sk->ufd->d.s.remote = smalloc(addrlen), addr, sk->ufd->d.s.remotelen = addrlen);
        sk->back->conncb = func;
        sk->back->data = data;
 +      getsock(sk->back);
 +      putsock(sk);
        if(!connect(sk->ufd->fd, addr, addrlen))
        {
            sksetstate(sk, SOCK_EST);
@@@ -1076,18 -1012,10 +1080,18 @@@ static void runbatches(void
  static void cleansocks(void)
  {
      struct ufd *ufd, *next;
 +    int dead;
      
      for(ufd = ufds; ufd != NULL; ufd = next) {
        next = ufd->next;
 -      if(ufd->sk && ((ufd->fd < 0) || (sockgetdatalen(ufd->sk) == 0))) {
 +      if(ufd->sk) {
 +          dead = (ufd->fd < 0);
 +          if(ufd->sk->state == SOCK_STL)
 +              dead = 1;
 +          if((ufd->sk->state == SOCK_EST) && (sockgetdatalen(ufd->sk) == 0))
 +              dead = 1;
 +          if(!dead)
 +              continue;
            if(ufd->sk->eos == 1) {
                ufd->sk->eos = 2;
                closeufd(ufd);
@@@ -1231,6 -1159,7 +1235,7 @@@ int socksettos(struct socket *sk, int t
  {
      int buf;
      struct ufd *ufd;
+     int dscp2tos;
      
      ufd = getskufd(sk);
      if(ufd->type != UFD_SOCK) {
        return(0); /* Unix sockets are always perfect. :) */
      if(ufd->d.s.family == AF_INET)
      {
+       dscp2tos = confgetint("net", "dscp-tos");
        switch(tos)
        {
        case 0:
            buf = 0;
            break;
        case SOCK_TOS_MINCOST:
-           buf = 0x02;
+           if(dscp2tos)
+               buf = confgetint("net", "diffserv-mincost") << 2;
+           else
+               buf = 0x02;
            break;
        case SOCK_TOS_MAXREL:
-           buf = 0x04;
+           if(dscp2tos)
+               buf = confgetint("net", "diffserv-maxrel") << 2;
+           else
+               buf = 0x04;
            break;
        case SOCK_TOS_MAXTP:
-           buf = 0x08;
+           if(dscp2tos)
+               buf = confgetint("net", "diffserv-maxtp") << 2;
+           else
+               buf = 0x08;
            break;
        case SOCK_TOS_MINDELAY:
-           buf = 0x10;
+           if(dscp2tos)
+               buf = confgetint("net", "diffserv-mindelay") << 2;
+           else
+               buf = 0x10;
            break;
        default:
            flog(LOG_WARNING, "attempted to set unknown TOS value %i to IPv4 sock", tos);