/*
* Dolda Connect - Modular multiuser Direct Connect-style client
- * Copyright (C) 2004 Fredrik Tolf (fredrik@dolda2000.com)
+ * Copyright (C) 2004 Fredrik Tolf <fredrik@dolda2000.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
struct dchub
{
+ struct socket *sk;
char *inbuf;
size_t inbufdata, inbufsize;
struct qcommand *queue;
struct fnetnode *fn;
char *inbuf;
size_t inbufdata, inbufsize;
- size_t curread, totalsize;
+ off_t curread, totalsize;
int freeing;
struct timer *timeout;
struct qcommand *queue;
free(buf);
}
-static void sendadcf(struct socket *sk, char *arg, ...)
+#if defined(__GNUC__)
+static void __attribute__ ((format (printf, 2, 3))) sendadcf(struct socket *sk, char *arg, ...)
+#else
+static void sendadcf(struct socket *sk, char *arg, ...)
+#endif
{
char *buf;
va_list args;
static void sendsupports(struct dcpeer *peer)
{
- if(peer->dcppemu)
+ if(peer->dcppemu) {
qstr(peer->sk, "$Supports MiniSlots XmlBZList ADCGet TTHL TTHF GetZBlock ZLIG |");
- else
- qstr(peer->sk, "$Supports MiniSlots XmlBZList ADCGet TTHL TTHF GetZBlock ZLIG|");
+ } else {
+ qstr(peer->sk, "$Supports MiniSlots XmlBZList ADCGet TTHL TTHF");
+ if(!confgetint("dc", "hidedeflate"))
+ qstr(peer->sk, " GetZBlock ZLIG");
+ qstr(peer->sk, "|");
+ }
}
static void requestfile(struct dcpeer *peer)
}
sendadc(peer->sk, buf);
free(buf);
- sendadcf(peer->sk, "%i", peer->transfer->curpos);
- sendadcf(peer->sk, "%i", peer->transfer->size - peer->transfer->curpos);
+ sendadcf(peer->sk, "%ji", (intmax_t)peer->transfer->curpos);
+ sendadcf(peer->sk, "%ji", (intmax_t)(peer->transfer->size - peer->transfer->curpos));
qstr(peer->sk, "|");
} else if(supports(peer, "xmlbzlist")) {
if((buf = icswcstombs(peer->transfer->path, "UTF-8", NULL)) == NULL)
freedcpeer(peer);
return;
}
- qstrf(peer->sk, "$UGetBlock %zi %zi %s|", peer->transfer->curpos, peer->transfer->size - peer->transfer->curpos, buf);
+ qstrf(peer->sk, "$UGetBlock %ji %ji %s|", (intmax_t)peer->transfer->curpos, (intmax_t)(peer->transfer->size - peer->transfer->curpos), buf);
} else {
/* Use DCCHARSET for $Get paths until further researched... */
if((buf = icswcstombs(peer->transfer->path, DCCHARSET, NULL)) == NULL)
freedcpeer(peer);
return;
}
- qstrf(peer->sk, "$Get %s$%zi|", buf, peer->transfer->curpos + 1);
+ qstrf(peer->sk, "$Get %s$%ji|", buf, (intmax_t)peer->transfer->curpos + 1);
}
}
*(p++) = 0;
if(hub->extended)
{
- if(hub->dcppemu)
+ if(hub->dcppemu) {
qstrf(sk, "$Supports UserCommand NoGetINFO NoHello UserIP2 TTHSearch GetZBlock |");
- else
- qstrf(sk, "$Supports UserCommand NoGetINFO NoHello UserIP2 TTHSearch GetZBlock|");
+ } else {
+ qstrf(sk, "$Supports UserCommand NoGetINFO NoHello UserIP2 TTHSearch");
+ if(!confgetint("dc", "hidedeflate"))
+ qstr(sk, " GetZBlock");
+ qstr(sk, "|");
+ }
}
key = dcmakekey(args);
qstrf(sk, "$Key %s|", key);
goto out;
prefix = sprintf2("$SR %s ", hub->nativenick);
infix = sprintf2(" %i/%i\005", slotsleft(), confgetint("transfer", "slots"));
- postfix = sprintf2(" (%s)\005%s|", formataddress(fn->sk->remote, fn->sk->remotelen), args + 4);
+ postfix = sprintf2(" (%s)\005%s|", formataddress(hub->sk->remote, hub->sk->remotelen), args + 4);
dsk = sk;
getsock(dsk);
} else {
addr.sin_port = htons(atoi(p2));
prefix = sprintf2("$SR %s ", hub->nativenick);
infix = sprintf2(" %i/%i\005", slotsleft(), confgetint("transfer", "slots"));
- postfix = sprintf2(" (%s)|", formataddress(fn->sk->remote, fn->sk->remotelen));
+ postfix = sprintf2(" (%s)|", formataddress(hub->sk->remote, hub->sk->remotelen));
netdgramconn(dsk = netdupsock(udpsock), (struct sockaddr *)&addr, sizeof(addr));
}
if(node->f.b.hastth)
{
buf2 = base32encode(node->hashtth, 24);
- qstrf(dsk, "%s%s\005%zi%sTTH:%.39s%s", prefix, buf, node->size, infix, buf2, postfix);
+ qstrf(dsk, "%s%s\005%ji%sTTH:%.39s%s", prefix, buf, (intmax_t)node->size, infix, buf2, postfix);
free(buf2);
} else {
- qstrf(dsk, "%s%s\005%zi%s%s%s", prefix, buf, node->size, infix, hub->nativename, postfix);
+ qstrf(dsk, "%s%s\005%ji%s%s%s", prefix, buf, (intmax_t)node->size, infix, hub->nativename, postfix);
}
free(buf);
}
return;
*p2 = 0;
p2 += 2;
- hubrecvchat(fn->sk, fn, p, p2);
+ hubrecvchat(hub->sk, fn, p, p2);
hubhandleaction(sk, fn, cmd, args);
}
struct dchub *hub;
char *p, *p2, *buf;
char *nick, *filename, *hubname;
- int size, slots;
+ off_t size;
+ int slots;
size_t buflen;
struct srchres *sr;
wchar_t *wnick, *wfile;
if((p2 = strchr(p, ' ')) == NULL)
return;
*p2 = 0;
- size = atoi(p);
+ size = strtoll(p, NULL, 10);
p = p2 + 1;
if((p2 = strchr(p, '/')) == NULL)
return;
static void cmd_filelength(struct socket *sk, struct dcpeer *peer, char *cmd, char *args)
{
- int size;
+ off_t size;
struct transfer *transfer;
if(peer->transfer == NULL)
freedcpeer(peer);
return;
}
- size = atoi(args);
+ size = strtoll(args, NULL, 10);
if(peer->transfer->size != size)
{
transfersetsize(peer->transfer, size);
static void cmd_get(struct socket *sk, struct dcpeer *peer, char *cmd, char *args)
{
- int offset;
+ off_t offset;
char *p, *buf;
wchar_t *buf2;
struct sharecache *node;
return;
}
*(p++) = 0;
- if((offset = (atoi(p) - 1)) < 0)
+ if((offset = (strtoll(p, NULL, 10) - 1)) < 0)
{
freedcpeer(peer);
return;
lesk = wrapsock(fd);
transferprepul(peer->transfer, sb.st_size, offset, -1, lesk);
putsock(lesk);
- qstrf(sk, "$FileLength %zi|", peer->transfer->size);
+ qstrf(sk, "$FileLength %ji|", (intmax_t)peer->transfer->size);
}
static void cmd_send(struct socket *sk, struct dcpeer *peer, char *cmd, char *args)
{
int fd;
char *p, *p2;
- int start, numbytes;
+ off_t start, numbytes;
char *charset, *buf;
wchar_t *buf2;
struct sharecache *node;
return;
}
*(p2++) = 0;
- start = atoi(p);
+ start = strtoll(p, NULL, 10);
p = p2;
if((p2 = strchr(p, ' ')) == NULL)
{
return;
}
*(p2++) = 0;
- numbytes = atoi(p);
+ numbytes = strtoll(p, NULL, 10);
p = p2;
if(!strcmp(cmd, "$UGetBlock") || !strcmp(cmd, "$UGetZBlock"))
charset = "UTF-8";
lesk = wrapsock(fd);
transferprepul(peer->transfer, sb.st_size, start, start + numbytes, lesk);
putsock(lesk);
- qstrf(sk, "$Sending %i|", numbytes);
+ qstrf(sk, "$Sending %ji|", (intmax_t)numbytes);
startul(peer);
}
{
int i;
char **argv, *buf;
- int start, numbytes;
+ off_t start, numbytes;
struct sharecache *node;
struct stat sb;
struct socket *lesk;
freedcpeer(peer);
goto out;
}
- start = atoi(argv[2]);
- numbytes = atoi(argv[3]);
+ start = strtoll(argv[2], NULL, 10);
+ numbytes = strtoll(argv[3], NULL, 10);
node = NULL;
fd = -1;
if(((fd = openfilelist(argv[1])) < 0) && (errno != 0))
qstr(sk, "$ADCSND");
sendadc(sk, "file");
sendadc(sk, argv[1]);
- sendadcf(sk, "%i", start);
- sendadcf(sk, "%i", numbytes);
+ sendadcf(sk, "%ji", (intmax_t)start);
+ sendadcf(sk, "%ji", (intmax_t)numbytes);
if(peer->compress == CPRS_ZLIB)
sendadc(sk, "ZL1");
qstr(sk, "|");
static void cmd_adcsnd(struct socket *sk, struct dcpeer *peer, char *cmd, char *args)
{
char **argv;
- int start, numbytes;
+ off_t start, numbytes;
if(peer->transfer == NULL)
{
freedcpeer(peer);
goto out;
}
- start = atoi(argv[2]);
- numbytes = atoi(argv[3]);
+ start = strtoll(argv[2], NULL, 10);
+ numbytes = strtoll(argv[3], NULL, 10);
if(!strcmp(argv[0], "tthl"))
{
if((start != 0) || (numbytes % 24 != 0))
static void cmd_sending(struct socket *sk, struct dcpeer *peer, char *cmd, char *args)
{
- int numbytes;
+ off_t numbytes;
if(peer->transfer == NULL)
{
freedcpeer(peer);
return;
}
- numbytes = atoi(args);
+ numbytes = strtoll(args, NULL, 10);
if(peer->transfer->size - peer->transfer->curpos != numbytes)
{
transfersetsize(peer->transfer, peer->transfer->curpos + numbytes);
return(1); /* Shouldn't happen, of course, but who knows... */
if(tcpsock != NULL)
{
- sendctm(peer->fn->sk, mbsnick);
+ sendctm(hub->sk, mbsnick);
expectpeer(mbsnick, peer->fn);
} else {
- qstrf(peer->fn->sk, "$RevConnectToMe %s %s|", hub->nativenick, mbsnick);
+ qstrf(hub->sk, "$RevConnectToMe %s %s|", hub->nativenick, mbsnick);
}
free(mbsnick);
return(0);
{
if(*to == L'\0')
{
- qstrf(fn->sk, "<%s> %s|", hub->nativenick, mbsstring);
+ qstrf(hub->sk, "<%s> %s|", hub->nativenick, mbsstring);
} else {
- qstrf(fn->sk, "$To: %s From: %s $<%s> %s|", mbsto, hub->nativenick, hub->nativenick, mbsstring);
+ qstrf(hub->sk, "$To: %s From: %s $<%s> %s|", mbsto, hub->nativenick, hub->nativenick, mbsstring);
}
} else {
- qstrf(fn->sk, "$To: %s From: %s $<%s> %s|", mbsto, hub->nativenick, hub->nativenick, mbsstring);
+ qstrf(hub->sk, "$To: %s From: %s $<%s> %s|", mbsto, hub->nativenick, hub->nativenick, mbsstring);
}
free(mbsto);
free(mbsstring);
struct hash *hash;
hub = fn->data;
- if((fn->state != FNN_EST) || (fn->sk == NULL) || (fn->sk->state != SOCK_EST))
+ if((fn->state != FNN_EST) || (hub->sk == NULL) || (hub->sk->state != SOCK_EST))
return(1);
list = findsexprstrs(srch->sexpr);
findsizelimit(srch->sexpr, &minsize, &maxsize);
addtobuf(sstr, 0);
if(tcpsock != NULL)
{
- if(sockgetremotename2(udpsock, fn->sk, &name, &namelen) < 0)
+ if(sockgetremotename2(udpsock, hub->sk, &name, &namelen) < 0)
{
flog(LOG_WARNING, "cannot get address of UDP socket");
} else {
- qstrf(fn->sk, "$Search %s %s|", formataddress(name, namelen), sstr);
+ qstrf(hub->sk, "$Search %s %s|", formataddress(name, namelen), sstr);
free(name);
}
} else {
- qstrf(fn->sk, "$Search Hub:%s %s|", hub->nativenick, sstr);
+ qstrf(hub->sk, "$Search Hub:%s %s|", hub->nativenick, sstr);
}
free(sstr);
freesl(&list);
size_t buflen, hashlen;
char *nick, *filename, *hubname;
struct sockaddr_in hubaddr;
- int size, slots;
+ off_t size;
+ int slots;
struct fnetnode *fn, *myfn;
struct dchub *hub;
struct srchres *sr;
return;
}
*p2 = 0;
- size = atoi(p);
+ size = strtoll(p, NULL, 10);
p = p2 + 1;
if((p2 = strchr(p, '/')) == NULL)
{
{
for(fn = fnetnodes; fn != NULL; fn = fn->next)
{
- if((fn->fnet == &dcnet) && (fn->sk != NULL) && addreq(fn->sk->remote, (struct sockaddr *)&hubaddr))
+ if((fn->fnet == &dcnet) && ((hub = fn->data) != NULL))
{
- myfn = fn;
- break;
+ if((hub->sk != NULL) && addreq(hub->sk->remote, (struct sockaddr *)&hubaddr))
+ {
+ myfn = fn;
+ break;
+ }
}
}
}
numdcpeers--;
}
-static void hubconnect(struct fnetnode *fn)
+static void hubconnect(struct fnetnode *fn, struct socket *sk)
{
- fn->sk->readcb = (void (*)(struct socket *, void *))hubread;
- fn->sk->errcb = (void (*)(struct socket *, int, void *))huberr;
- getfnetnode(fn);
- fn->data = newdchub(fn);
- fn->sk->data = fn;
+ struct dchub *hub;
+
+ sk->readcb = (void (*)(struct socket *, void *))hubread;
+ sk->errcb = (void (*)(struct socket *, int, void *))huberr;
+ fn->data = hub = newdchub(fn);
+ sk->data = fn;
+ getsock(hub->sk = sk);
return;
}
struct qcommand *qcmd;
hub = (struct dchub *)fn->data;
- if((fn->sk != NULL) && (fn->sk->data == fn))
- {
- fn->sk->data = NULL;
- fn->sk->readcb = NULL;
- fn->sk->errcb = NULL;
- putfnetnode(fn);
- }
- if(hub == NULL)
- return;
+ putsock(hub->sk);
while((qcmd = ulqcmd(&hub->queue)) != NULL)
freeqcmd(qcmd);
if(hub->supports != NULL)
free(hub);
}
+static void hubkill(struct fnetnode *fn)
+{
+ struct dchub *hub;
+
+ hub = (struct dchub *)fn->data;
+ hub->sk->close = 1;
+}
+
static wchar_t *dcbasename(wchar_t *filename)
{
wchar_t *ret;
.name = L"dc",
.connect = hubconnect,
.destroy = hubdestroy,
+ .kill = hubkill,
.setnick = hubsetnick,
.reqconn = hubreqconn,
.sendchat = hubsendchat,
if(node->f.b.type == FILE_REG)
{
addtobuf(buf, '|');
- sprintf(numbuf, "%zi", node->size);
+ sprintf(numbuf, "%ji", (intmax_t)node->size);
bufcat(buf, numbuf, strlen(numbuf));
}
addtobuf(buf, 13);
lev++;
continue;
} else {
- fprintf(fs, "<File Name=\"%s\" Size=\"%zi\"", namebuf, node->size);
+ fprintf(fs, "<File Name=\"%s\" Size=\"%ji\"", namebuf, (intmax_t)node->size);
if(node->f.b.hastth)
{
hashbuf = base32encode(node->hashtth, 24);
return(enc);
}
-static void logunimpl(char *cmd, char *args)
+static void logunimpl(char *list, char *cmd, char *args)
{
FILE *log;
flog(LOG_WARNING, "could not open unimpl log: %s", strerror(errno));
return;
}
+ fputs(list, log);
+ fputc('\t', log);
fputs(quotestr(cmd), log);
if(args != NULL)
{
break;
}
if(cmd->handler != NULL)
+ {
cmd->handler(sk, data, qcmd->string, p);
- else if(confgetint("dc", "logunimpl"))
- logunimpl(qcmd->string, p);
+ } else if(confgetint("dc", "logunimpl")) {
+ if(cmdlist == hubcmds)
+ logunimpl("hub", qcmd->string, p);
+ else if(cmdlist == peercmds)
+ logunimpl("peer", qcmd->string, p);
+ else
+ logunimpl("other?!", qcmd->string, p);
+ }
}
static int run(void)
{
if(*qcmd->string == '$')
{
- if((fn->sk != NULL) && (fn->sk->state == SOCK_EST))
- dispatchcommand(qcmd, hubcmds, fn->sk, fn);
+ if((hub->sk != NULL) && (hub->sk->state == SOCK_EST))
+ dispatchcommand(qcmd, hubcmds, hub->sk, fn);
} else if(*qcmd->string != 0) {
- hubrecvchat(fn->sk, fn, NULL, qcmd->string);
+ hubrecvchat(hub->sk, fn, NULL, qcmd->string);
}
freeqcmd(qcmd);
ret = 1;
* unknown commands it receives, and their arguments, to
* /tmp/dc-unimpl. */
{CONF_VAR_BOOL, "logunimpl", {.num = 0}},
+ /** If set to true, doldacond will hide its support for deflate
+ * compression of transfers from other clients, so that they will
+ * not request compressed uploads. Compressed transfers may
+ * consume a non-trivial amount of CPU time on slower machines. */
+ {CONF_VAR_BOOL, "hidedeflate", {.num = 0}},
{CONF_VAR_END}
};