From: Fredrik Tolf Date: Thu, 6 Mar 2008 23:59:30 +0000 (+0100) Subject: Merge branch 'master' of git.dolda2000.com:/srv/git/r/doldaconnect X-Git-Tag: 1.2~4 X-Git-Url: http://git.dolda2000.com/gitweb/?a=commitdiff_plain;h=e1e39065920715865b23611fa519c696bbe71bce;hp=7a00b8b0d81ccb8dc60b3482978b0aa5e7ddfc55;p=doldaconnect.git Merge branch 'master' of git.dolda2000.com:/srv/git/r/doldaconnect --- diff --git a/daemon/client.c b/daemon/client.c index bf30821..26b50f3 100644 --- a/daemon/client.c +++ b/daemon/client.c @@ -106,6 +106,7 @@ static struct timer *hashwritetimer = NULL; static pid_t hashjob = -1; struct sharecache *shareroot = NULL; static struct timer *scantimer = NULL; +int sharedfiles = 0; unsigned long long sharesize = 0; GCBCHAIN(sharechangecb, unsigned long long); @@ -648,6 +649,8 @@ static void freecache(struct sharecache *node) CBCHAINDOCB(node, share_delete, node); CBCHAINFREE(node, share_delete); sharesize -= node->size; + if(node->f.b.type == FILE_REG) + sharedfiles--; if(node->path != NULL) free(node->path); if(node->name != NULL) @@ -938,6 +941,7 @@ int doscan(int quantum) if(S_ISREG(sb.st_mode)) { sharesize += (n->size = sb.st_size); + sharedfiles++; } else { n->size = 0; } diff --git a/daemon/client.h b/daemon/client.h index 19708d2..0a301ab 100644 --- a/daemon/client.h +++ b/daemon/client.h @@ -93,6 +93,7 @@ int hashcmp(struct hash *h1, struct hash *h2); void scanshares(void); extern struct sharecache *shareroot; +extern int sharedfiles; extern unsigned long long sharesize; EGCBCHAIN(sharechangecb, unsigned long long); diff --git a/daemon/fnet-adc.c b/daemon/fnet-adc.c index 19141a2..a15575d 100644 --- a/daemon/fnet-adc.c +++ b/daemon/fnet-adc.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -49,7 +50,7 @@ struct command { wchar_t *name; - int minargs, needsender; + int minargs, needsid, needsender; void (*func)(struct fnetnode *fn, wchar_t *command, wchar_t *sender, int argc, wchar_t **argv); }; @@ -77,9 +78,10 @@ struct adchub { struct qcmdqueue queue; }; -static wchar_t *eoc; +static wchar_t *eoc, *ns, *fmt; /* I've never understood why both of these are necessary, but... */ static wchar_t *privid, *cid; +struct socket *udpsock, *tcpsock; static wchar_t **parseadc(wchar_t *cmdline) { @@ -154,20 +156,44 @@ static void sendadc1(struct socket *sk, int sep, wchar_t *arg) static void sendadc(struct socket *sk, int sep, ...) { + int i; va_list args; wchar_t *arg; - int i; + wchar_t *type, *buf; va_start(args, sep); for(i = 0; (arg = va_arg(args, wchar_t *)) != NULL; i++) { - if(arg == eoc) + if(arg == eoc) { sendeoc(sk); - else - sendadc1(sk, (i == 0)?sep:1, arg); + } else if(arg == ns) { + sep = 0; + } else if(arg == fmt) { + type = va_arg(args, wchar_t *); + if(!wcscmp(type, L"i")) { + buf = swprintf2(L"%i", va_arg(args, int)); + } else if(!wcscmp(type, L"mi")) { + buf = swprintf2(L"%ji", va_arg(args, intmax_t)); + } + sendadc1(sk, sep, buf); + free(buf); + sep = 1; + } else { + sendadc1(sk, sep, arg); + sep = 1; + } } va_end(args); } +static wchar_t *findkv(wchar_t **argv, wchar_t *name) +{ + while(*argv != NULL) { + if(!wcsncmp(*argv, name, 2)) + return((*argv) + 2); + } + return(NULL); +} + static struct qcmd *newqcmd(struct qcmdqueue *queue, wchar_t **args) { struct qcmd *new; @@ -202,6 +228,32 @@ static void freeqcmd(struct qcmd *qcmd) free(qcmd); } +static void sendinf(struct fnetnode *fn) +{ + struct adchub *hub = fn->data; + struct socket *sk = hub->sk; + struct sockaddr_in *a4; + socklen_t alen; + + sendadc(sk, 0, L"BINF", hub->sid, NULL); + sendadc(sk, 1, L"PD", ns, privid, L"ID", ns, cid, NULL); + sendadc(sk, 1, L"VEDolda ", ns, icsmbstowcs(VERSION, "us-ascii", NULL), NULL); + sendadc(sk, 1, L"NI", ns, fn->mynick, NULL); + sendadc(sk, 1, L"SS", ns, fmt, L"mi", (intmax_t)sharesize, L"SF", ns, fmt, L"i", sharedfiles, NULL); + if(sk->family == AF_INET) + sendadc(sk, 1, L"I40.0.0.0", NULL); + else if(sk->family == AF_INET6) + sendadc(sk, 1, L"I6::", NULL); + sendadc(sk, 1, L"SL", ns, fmt, L"i", confgetint("transfer", "slot"), NULL); + if(tcpsock != NULL) { + if((sk->family == AF_INET) && !sockgetremotename(udpsock, (struct sockaddr **)&a4, &alen)) { + sendadc(sk, 1, L"U4", ns, fmt, L"i", ntohs(a4->sin_port), NULL); + free(a4); + } + } + sendadc(sk, 1, eoc, NULL); +} + #define ADC_CMDFN(name) static void name(struct fnetnode *fn, wchar_t *command, wchar_t *sender, int argc, wchar_t **argv) #ifdef __GNUC__ #define UNUSED __attribute__ ((unused)) @@ -249,23 +301,26 @@ ADC_CMDFN(cmd_sid) hub->sid = swcsdup(argv[1]); if(hub->state == ADC_PROTOCOL) { hub->state = ADC_IDENTIFY; + sendinf(fn); } } ADC_CMDFN(cmd_inf) { ADC_CMDCOM; + wchar_t *p; if(sender == NULL) { - + if((p = findkv(argv, L"NI")) != NULL) + fnetsetname(fn, p); } } static struct command hubcmds[] = { - {L"SUP", 1, 0, cmd_sup}, - {L"SID", 2, 0, cmd_sid}, - {L"INF", 0, 0, cmd_inf}, - {NULL, 0, 0, NULL} + {L"SUP", 1, 0, 0, cmd_sup}, + {L"SID", 2, 0, 0, cmd_sid}, + {L"INF", 1, 0, 0, cmd_inf}, + {NULL, 0, 0, 0, NULL} }; static void dispatch(struct qcmd *qcmd, struct fnetnode *fn) @@ -297,13 +352,21 @@ static void dispatch(struct qcmd *qcmd, struct fnetnode *fn) if(!wcscmp(cmd->name, qcmd->args[0] + 1)) { if(argc < cmd->minargs) return; - cmd->func(fn, cmdnm, sender, argc, qcmd->args); + cmd->func(fn, cmdnm, sender, argc, argv); return; } } flog(LOG_DEBUG, "unknown adc command: %ls", qcmd->args[0]); } +static void peeraccept(struct socket *sk, struct socket *newsk, void *uudata) +{ +} + +static void udpread(struct socket *sk, void *uudata) +{ +} + static void hubread(struct socket *sk, struct fnetnode *fn) { int ret; @@ -379,7 +442,7 @@ static void hubconnect(struct fnetnode *fn, struct socket *sk) return; } fn->data = hub; - sendadc(sk, 0, L"HSUP", L"ADBASE", eoc, NULL); + sendadc(sk, 0, L"HSUP", L"ADBASE", L"ADTIGR", eoc, NULL); } static void hubdestroy(struct fnetnode *fn) @@ -456,18 +519,78 @@ static void preinit(int hup) regfnet(adcnet); } -static int init(int hup) +static void makepid(char *idbuf) { int i; + int fd, ret; + + i = 0; + if((fd = open("/dev/urandom", O_RDONLY)) >= 0) { + for(i = 0; i < 24; i += ret) { + if((ret = read(fd, idbuf + i, 24 - i)) <= 0) { + flog(LOG_WARNING, "could not read random data from /dev/urandom for ADC PID: %s", (errno == 0)?"EOF":strerror(errno)); + break; + } + } + close(fd); + } else { + flog(LOG_WARNING, "could not open /dev/urandom: %s", strerror(errno)); + } + if(i != 24) { + for(i = 0; i < sizeof(idbuf); i++) + idbuf[i] = rand() % 256; + } +} + +static int updateudpport(struct configvar *var, void *uudata) +{ + struct sockaddr_in addr; + struct socket *newsock; + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(var->val.num); + if((newsock = netcsdgram((struct sockaddr *)&addr, sizeof(addr))) == NULL) + { + flog(LOG_WARNING, "could not create new DC UDP socket, reverting to old: %s", strerror(errno)); + return(0); + } + newsock->readcb = udpread; + if(udpsock != NULL) + putsock(udpsock); + udpsock = newsock; + return(0); +} + +static int updatetcpport(struct configvar *var, void *uudata) +{ + struct sockaddr_in addr; + struct socket *newsock; + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(var->val.num); + if((newsock = netcslisten(SOCK_STREAM, (struct sockaddr *)&addr, sizeof(addr), peeraccept, NULL)) == NULL) + flog(LOG_INFO, "could not listen to a remote address, going into passive mode"); + if(tcpsock != NULL) + putsock(tcpsock); + tcpsock = newsock; + return(0); +} + +static int init(int hup) +{ char idbuf[24], *id32; struct tigerhash th; + struct sockaddr_in addr; if(!hup) { eoc = swcsdup(L""); + ns = swcsdup(L""); + fmt = swcsdup(L""); if((privid = fetchvar("adc.pid", NULL)) == NULL) { - for(i = 0; i < sizeof(idbuf); i++) - idbuf[i] = rand() % 256; + makepid(idbuf); id32 = base32encode(idbuf, sizeof(idbuf)); id32[39] = 0; privid = icmbstowcs(id32, "us-ascii"); @@ -485,6 +608,23 @@ static int init(int hup) id32[39] = 0; cid = icmbstowcs(id32, "us-ascii"); free(id32); + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(confgetint("adc", "udpport")); + if((udpsock = netcsdgram((struct sockaddr *)&addr, sizeof(addr))) == NULL) { + flog(LOG_CRIT, "could not create ADC UDP socket: %s", strerror(errno)); + return(1); + } + udpsock->readcb = udpread; + addr.sin_port = htons(confgetint("adc", "tcpport")); + if((tcpsock = netcslisten(SOCK_STREAM, (struct sockaddr *)&addr, sizeof(addr), peeraccept, NULL)) == NULL) { + flog(LOG_CRIT, "could not create ADC TCP socket: %s", strerror(errno)); + return(1); + } + CBREG(confgetvar("adc", "udpport"), conf_update, updateudpport, NULL, NULL); + CBREG(confgetvar("adc", "tcpport"), conf_update, updatetcpport, NULL, NULL); + CBREG(confgetvar("net", "mode"), conf_update, updatetcpport, NULL, NULL); } return(0); }