X-Git-Url: http://git.dolda2000.com/gitweb/?a=blobdiff_plain;f=daemon%2Ffnet-dc.c;h=a20aa0567b0e3ef1ce9733d2dd70604332345745;hb=1d85f24bb4bdc0f15f9560bc867befeff8eabc36;hp=1bd90111b04e098816b23f2feb5feb533e156858;hpb=a478552c065cf714a051990b8b72b12ee2de39f8;p=doldaconnect.git diff --git a/daemon/fnet-dc.c b/daemon/fnet-dc.c index 1bd9011..a20aa05 100644 --- a/daemon/fnet-dc.c +++ b/daemon/fnet-dc.c @@ -106,7 +106,8 @@ struct dchub char *inbuf; size_t inbufdata, inbufsize; struct qcommand *queue; - int extended; + int extended, dcppemu; + char *charset; char *nativename; char *nativenick; }; @@ -128,16 +129,18 @@ struct dcpeer size_t inbufdata, inbufsize; size_t curread, totalsize; int freeing; + struct timer *timeout; struct qcommand *queue; struct transfer *transfer; int state; int ptclose; /* Close after transfer is complete */ int accepted; /* If false, we connected, otherwise, we accepted */ - int extended; + int extended, dcppemu; int direction; /* Using the constants from transfer.h */ int compress; - int hascurpos, notthl; + int hascurpos, fetchingtthl, notthl; struct tigertreehash tth; + char *charset; void *cprsdata; char *key; char *nativename; @@ -387,7 +390,9 @@ static void hubrecvchat(struct socket *sk, struct fnetnode *fn, char *from, char wchar_t *chat, *wfrom, *wpeer; char *p, *end; struct fnetpeer *peer; + struct dchub *hub; + hub = fn->data; end = string + strlen(string); while((p = strchr(string, 13)) != NULL) memmove(p, p + 1, (end-- - p)); @@ -395,7 +400,7 @@ static void hubrecvchat(struct socket *sk, struct fnetnode *fn, char *from, char { if((strlen(string) > strlen(from) + 2) && (*string == '<') && !memcmp(string + 1, from, strlen(from)) && (*(string + strlen(from) + 1) == '>')) string += strlen(from) + 2; - if((wfrom = icmbstowcs(from, DCCHARSET)) == NULL) + if((wfrom = icmbstowcs(from, hub->charset)) == NULL) return; wpeer = swcsdup(wfrom); } else { @@ -413,7 +418,7 @@ static void hubrecvchat(struct socket *sk, struct fnetnode *fn, char *from, char *(p++) = 0; if(*p == ' ') p++; - if((wpeer = icmbstowcs(string + 1, DCCHARSET)) == NULL) + if((wpeer = icmbstowcs(string + 1, hub->charset)) == NULL) return; string = p; } @@ -421,7 +426,7 @@ static void hubrecvchat(struct socket *sk, struct fnetnode *fn, char *from, char if(wpeer == NULL) wpeer = swcsdup(L""); } - if((chat = icmbstowcs(string, DCCHARSET)) == NULL) + if((chat = icmbstowcs(string, hub->charset)) == NULL) { if(wfrom != NULL) free(wfrom); @@ -444,6 +449,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; @@ -575,8 +588,11 @@ static char *getadcid(struct dcpeer *peer) { char *buf; char *ret; + int isfilelist; - if((peer->transfer->hash != NULL) && isdchash(peer->transfer->hash) && supports(peer, "tthf")) + if(!wcscmp(peer->transfer->path, L"files.xml") || !wcscmp(peer->transfer->path, L"files.xml.bz2") || !wcscmp(peer->transfer->path, L"MyList.DcLst")) + isfilelist = 1; + if(!isfilelist && (peer->transfer->hash != NULL) && isdchash(peer->transfer->hash) && supports(peer, "tthf")) { buf = base32encode(peer->transfer->hash->buf, 24); ret = sprintf2("TTH/%.39s", buf); @@ -611,31 +627,29 @@ static int trresumecb(struct transfer *transfer, wchar_t *cmd, wchar_t *arg, str static void sendmynick(struct dcpeer *peer) { - struct dchub *hub; + struct fnetnode *fn; - hub = (peer->fn == NULL)?NULL:(peer->fn->data); - if(hub == NULL) - qstrf(peer->sk, "$MyNick %s|", icswcstombs(confgetstr("cli", "defnick"), DCCHARSET, "DoldaConnectUser-IN")); + fn = peer->fn; + if(fn == NULL) + qstrf(peer->sk, "$MyNick %s|", icswcstombs(confgetstr("cli", "defnick"), peer->charset, "DoldaConnectUser-IN")); else - qstrf(peer->sk, "$MyNick %s|", hub->nativenick); + qstrf(peer->sk, "$MyNick %s|", icswcstombs(fn->mynick, peer->charset, "DoldaConnectUser-IN")); } static void sendpeerlock(struct dcpeer *peer) { -#ifdef DCPP_MASQUERADE - qstrf(peer->sk, "$Lock EXTENDEDPROTOCOLABCABCABCABCABCABC Pk=DCPLUSPLUS0.674ABCABC|"); -#else - qstrf(peer->sk, "$Lock EXTENDEDPROTOCOLABCABCABCABCABCABC Pk=DOLDA%sABCABCABC|", VERSION); -#endif + if(peer->dcppemu) + qstrf(peer->sk, "$Lock EXTENDEDPROTOCOLABCABCABCABCABCABC Pk=DCPLUSPLUS0.674ABCABC|"); + else + qstrf(peer->sk, "$Lock EXTENDEDPROTOCOLABCABCABCABCABCABC Pk=DOLDA%sABCABCABC|", VERSION); } static void sendsupports(struct dcpeer *peer) { -#ifdef DCPP_MASQUERADE - qstr(peer->sk, "$Supports MiniSlots XmlBZList ADCGet TTHL TTHF GetZBlock ZLIG |"); -#else - qstr(peer->sk, "$Supports MiniSlots XmlBZList ADCGet TTHL TTHF GetZBlock ZLIG|"); -#endif + 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|"); } static void requestfile(struct dcpeer *peer) @@ -644,6 +658,7 @@ static void requestfile(struct dcpeer *peer) if(peer->transfer->size == -1) { + /* Use DCCHARSET for $Get paths until further researched... */ if((buf = icswcstombs(peer->transfer->path, DCCHARSET, NULL)) == NULL) { transferseterror(peer->transfer, TRNSE_NOTFOUND); @@ -673,6 +688,7 @@ static void requestfile(struct dcpeer *peer) sendadc(peer->sk, "0"); sendadc(peer->sk, "-1"); qstr(peer->sk, "|"); + peer->fetchingtthl = 1; return; } } @@ -711,6 +727,7 @@ static void requestfile(struct dcpeer *peer) } qstrf(peer->sk, "$UGetBlock %i %i %s|", peer->transfer->curpos, 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) { transferseterror(peer->transfer, TRNSE_NOTFOUND); @@ -726,29 +743,36 @@ static void sendmyinfo(struct socket *sk, struct fnetnode *fn) struct dchub *hub; char *buf; struct fnetnode *cfn; - int numhubs; + int hn1, hn2, hn3; hub = fn->data; qstrf(sk, "$MyINFO $ALL %s ", hub->nativenick); - buf = tr(icswcstombs(confgetstr("dc", "desc"), DCCHARSET, "Charset_conv_failure"), "$_|_"); + buf = tr(icswcstombs(confgetstr("dc", "desc"), hub->charset, "Charset_conv_failure"), "$_|_"); qstrf(sk, "%s", buf); - numhubs = 0; + hn1 = hn2 = hn3 = 0; for(cfn = fnetnodes; cfn != NULL; cfn = cfn->next) { if((cfn->state == FNN_EST) || (cfn->state == FNN_HS)) - numhubs++; + { + if(cfn->regstatus == FNNS_OP) + hn3++; + else if(cfn->regstatus == FNNS_REG) + hn2++; + else + hn1++; + } } - qstrf(sk, "<%s V:%s,M:%c,H:%i/0/0,S:%i>", - DCIDTAG, - DCIDTAGV, + qstrf(sk, "<%s V:%s,M:%c,H:%i/%i/%i,S:%i>", + (hub->dcppemu)?"++":"Dolda", + (hub->dcppemu)?"0.674":VERSION, (tcpsock == NULL)?'P':'A', - numhubs, + hn1, hn2, hn3, confgetint("transfer", "slots") ); qstrf(sk, "$ $"); - buf = tr(icswcstombs(confgetstr("dc", "speedstring"), DCCHARSET, "Charset_conv_failure"), "$_|_"); + buf = tr(icswcstombs(confgetstr("dc", "speedstring"), hub->charset, "Charset_conv_failure"), "$_|_"); qstrf(sk, "%s\x01$", buf); - buf = tr(icswcstombs(confgetstr("dc", "email"), DCCHARSET, "Charset_conv_failure"), "$_|_"); + buf = tr(icswcstombs(confgetstr("dc", "email"), hub->charset, "Charset_conv_failure"), "$_|_"); qstrf(sk, "%s$", buf); qstrf(sk, "%llu$|", sharesize); } @@ -787,11 +811,10 @@ static void cmd_lock(struct socket *sk, struct fnetnode *fn, char *cmd, char *ar *(p++) = 0; if(hub->extended) { -#ifdef DCPP_MASQUERADE - qstrf(sk, "$Supports UserCommand NoGetINFO NoHello UserIP2 TTHSearch GetZBlock |"); -#else - qstrf(sk, "$Supports UserCommand NoGetINFO NoHello UserIP2 TTHSearch GetZBlock|"); -#endif + if(hub->dcppemu) + qstrf(sk, "$Supports UserCommand NoGetINFO NoHello UserIP2 TTHSearch GetZBlock |"); + else + qstrf(sk, "$Supports UserCommand NoGetINFO NoHello UserIP2 TTHSearch GetZBlock|"); } key = dcmakekey(args); qstrf(sk, "$Key %s|", key); @@ -808,7 +831,7 @@ static void cmd_hubname(struct socket *sk, struct fnetnode *fn, char *cmd, char if(hub->nativename == NULL) free(hub->nativename); hub->nativename = sstrdup(args); - buf = icmbstowcs(args, DCCHARSET); + buf = icmbstowcs(args, hub->charset); fnetsetname(fn, (buf == NULL)?L"Hubname conv error":buf); if(buf != NULL) free(buf); @@ -821,7 +844,7 @@ static void cmd_hello(struct socket *sk, struct fnetnode *fn, char *cmd, char *a struct dchub *hub; hub = fn->data; - if((nick = icmbstowcs(args, DCCHARSET)) == NULL) + if((nick = icmbstowcs(args, hub->charset)) == NULL) return; if(strcmp(args, hub->nativenick) && (fnetfindpeer(fn, nick) == NULL)) fnetaddpeer(fn, nick, nick); @@ -836,7 +859,7 @@ static void cmd_quit(struct socket *sk, struct fnetnode *fn, char *cmd, char *ar struct dchub *hub; hub = fn->data; - if((nick = icmbstowcs(args, DCCHARSET)) == NULL) + if((nick = icmbstowcs(args, hub->charset)) == NULL) return; if((peer = fnetfindpeer(fn, nick)) != NULL) fnetdelpeer(peer); @@ -857,7 +880,7 @@ static void cmd_nicklist(struct socket *sk, struct fnetnode *fn, char *cmd, char while((p = strstr(args, "$$")) != NULL) { *p = 0; - if((buf = icmbstowcs(args, DCCHARSET)) != NULL) + if((buf = icmbstowcs(args, hub->charset)) != NULL) { if((peer = fnetfindpeer(fn, buf)) == NULL) peer = fnetaddpeer(fn, buf, buf); @@ -890,7 +913,7 @@ static void cmd_oplist(struct socket *sk, struct fnetnode *fn, char *cmd, char * while((p = strstr(args, "$$")) != NULL) { *p = 0; - if((buf = icmbstowcs(args, DCCHARSET)) != NULL) + if((buf = icmbstowcs(args, hub->charset)) != NULL) { if((peer = fnetfindpeer(fn, buf)) != NULL) peer->flags.b.op = 1; @@ -917,7 +940,7 @@ static void cmd_myinfo(struct socket *sk, struct fnetnode *fn, char *cmd, char * if((p2 = strchr(p, ' ')) == NULL) return; *p2 = 0; - if((buf = icmbstowcs(p, DCCHARSET)) == NULL) + if((buf = icmbstowcs(p, hub->charset)) == NULL) return; if((peer = fnetfindpeer(fn, buf)) == NULL) peer = fnetaddpeer(fn, buf, buf); @@ -926,9 +949,9 @@ static void cmd_myinfo(struct socket *sk, struct fnetnode *fn, char *cmd, char * if((p2 = strstr(p, "$ $")) == NULL) return; *p2 = 0; - if((buf = icmbstowcs(p, DCCHARSET)) == NULL) + if((buf = icmbstowcs(p, hub->charset)) == NULL) return; - if((wcslen(buf) > 0) && (buf[wcslen(buf) - 1] == L'>') && ((wp = wcschr(buf, L'<')) != NULL)) + if((wcslen(buf) > 0) && (buf[wcslen(buf) - 1] == L'>') && ((wp = wcsrchr(buf, L'<')) != NULL)) { buf[wcslen(buf) - 1] = L'\0'; *(wp++) = L'\0'; @@ -955,7 +978,7 @@ static void cmd_myinfo(struct socket *sk, struct fnetnode *fn, char *cmd, char * if((p2 = strchr(p, '$')) == NULL) return; *(p2 - 1) = 0; - if((buf = icmbstowcs(p, DCCHARSET)) == NULL) + if((buf = icmbstowcs(p, hub->charset)) == NULL) return; fnetpeersetstr(peer, L"dc-speed", buf); free(buf); @@ -963,7 +986,7 @@ static void cmd_myinfo(struct socket *sk, struct fnetnode *fn, char *cmd, char * if((p2 = strchr(p, '$')) == NULL) return; *p2 = 0; - if((buf = icmbstowcs(p, DCCHARSET)) == NULL) + if((buf = icmbstowcs(p, hub->charset)) == NULL) return; fnetpeersetstr(peer, L"email", buf); free(buf); @@ -993,7 +1016,7 @@ static void cmd_forcemove(struct socket *sk, struct fnetnode *fn, char *cmd, cha } else { freeargs = 0; } - if((newfn = fnetinitconnect(L"dc", args)) != NULL) + if((newfn = fnetinitconnect(L"dc", args, NULL)) != NULL) { linkfnetnode(newfn); putfnetnode(newfn); @@ -1003,7 +1026,7 @@ static void cmd_forcemove(struct socket *sk, struct fnetnode *fn, char *cmd, cha free(args); } -static char *getdcpath(struct sharecache *node, size_t *retlen) +static char *getdcpath(struct sharecache *node, size_t *retlen, char *charset) { char *buf, *buf2; size_t len, len2; @@ -1012,15 +1035,15 @@ static char *getdcpath(struct sharecache *node, size_t *retlen) return(NULL); if(node->parent == shareroot) { - if((buf = icwcstombs(node->name, DCCHARSET)) == NULL) + if((buf = icwcstombs(node->name, charset)) == NULL) return(NULL); if(retlen != NULL) *retlen = strlen(buf); return(buf); } else { - if((buf2 = icwcstombs(node->name, DCCHARSET)) == NULL) + if((buf2 = icwcstombs(node->name, charset)) == NULL) return(NULL); - if((buf = getdcpath(node->parent, &len)) == NULL) + if((buf = getdcpath(node->parent, &len, charset)) == NULL) { free(buf2); return(NULL); @@ -1149,7 +1172,7 @@ static void cmd_search(struct socket *sk, struct fnetnode *fn, char *cmd, char * memcpy(hashtth, buf, 24); free(buf); } else { - if((terms[termnum] = icmbstowcs(p, DCCHARSET)) != NULL) + if((terms[termnum] = icmbstowcs(p, hub->charset)) != NULL) termnum++; } } @@ -1197,7 +1220,8 @@ static void cmd_search(struct socket *sk, struct fnetnode *fn, char *cmd, char * } if(!skipcheck && (satisfied == termnum)) { - if((buf = getdcpath(node, NULL)) != NULL) + /* Use DCCHARSET in $Get paths until further researched... */ + if((buf = getdcpath(node, NULL, DCCHARSET)) != NULL) { if(node->f.b.hastth) { @@ -1388,8 +1412,9 @@ static void cmd_sr(struct socket *sk, struct fnetnode *fn, char *cmd, char *args if((p2 = strstr(p, " (")) == NULL) return; *p2 = 0; - if((wnick = icmbstowcs(nick, DCCHARSET)) == NULL) + if((wnick = icmbstowcs(nick, hub->charset)) == NULL) return; + /* Use DCCHARSET in $Get paths until further researched... */ if((wfile = icmbstowcs(filename, DCCHARSET)) == NULL) { free(wnick); @@ -1423,16 +1448,45 @@ static void cmd_usercommand(struct socket *sk, struct fnetnode *fn, char *cmd, c /* Do nothing for now. */ } +static void cmd_getpass(struct socket *sk, struct fnetnode *fn, char *cmd, char *args) +{ + struct dchub *hub; + wchar_t *pw; + char *mbspw; + + hub = fn->data; + pw = wpfind(fn->args, L"password"); + if((pw == NULL) || ((mbspw = icwcstombs(pw, hub->charset)) == NULL)) + { + killfnetnode(fn); + return; + } + qstrf(sk, "$MyPass %s|", mbspw); + free(mbspw); + fn->regstatus = FNNS_REG; + hubhandleaction(sk, fn, cmd, args); +} + +static void cmd_logedin(struct socket *sk, struct fnetnode *fn, char *cmd, char *args) +{ + struct dchub *hub; + + hub = fn->data; + fn->regstatus = FNNS_OP; + hubhandleaction(sk, fn, cmd, args); +} + static void cmd_mynick(struct socket *sk, struct dcpeer *peer, char *cmd, char *args) { struct dcexppeer *expect; + struct dchub *hub; if(peer->nativename != NULL) free(peer->nativename); peer->nativename = sstrdup(args); if(peer->wcsname != NULL) free(peer->wcsname); - if((peer->wcsname = icmbstowcs(peer->nativename, DCCHARSET)) == NULL) + if((peer->wcsname = icmbstowcs(peer->nativename, peer->charset)) == NULL) { freedcpeer(peer); return; @@ -1448,8 +1502,10 @@ static void cmd_mynick(struct socket *sk, struct dcpeer *peer, char *cmd, char * { peer->fn = NULL; } else { + hub = expect->fn->data; peer->fn = expect->fn; getfnetnode(peer->fn); + peer->dcppemu = hub->dcppemu; freeexppeer(expect); } } @@ -1475,7 +1531,8 @@ static void cmd_direction(struct socket *sk, struct dcpeer *peer, char *cmd, cha freedcpeer(peer); return; } - requestfile(peer); + if(peer->direction == TRNSD_DOWN) + requestfile(peer); } else { if(peer->wcsname == NULL) { @@ -1556,6 +1613,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; @@ -1564,6 +1623,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; @@ -1572,6 +1633,7 @@ static void startul(struct dcpeer *peer) static void cmd_filelength(struct socket *sk, struct dcpeer *peer, char *cmd, char *args) { int size; + struct transfer *transfer; if(peer->transfer == NULL) { @@ -1582,7 +1644,9 @@ static void cmd_filelength(struct socket *sk, struct dcpeer *peer, char *cmd, ch if(peer->transfer->size != size) { transfersetsize(peer->transfer, size); + transfer = peer->transfer; freedcpeer(peer); + trytransferbypeer(transfer->fnet, transfer->peerid); return; } startdl(peer); @@ -1591,6 +1655,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); @@ -1724,15 +1795,11 @@ 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; - } + /* Use DCCHARSET in $Get paths until further researched... */ if((node = resdcpath(args, DCCHARSET, '\\')) == NULL) { qstrf(sk, "$Error File not in share|"); @@ -1760,6 +1827,14 @@ 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)) { + close(fd); + qstr(sk, "$MaxedOut|"); + freedcpeer(peer); + return; + } if((offset != 0) && (lseek(fd, offset, SEEK_SET) < 0)) { close(fd); @@ -1853,6 +1928,7 @@ static void cmd_getblock(struct socket *sk, struct dcpeer *peer, char *cmd, char if(!strcmp(cmd, "$UGetBlock") || !strcmp(cmd, "$UGetZBlock")) charset = "UTF-8"; else + /* Use DCCHARSET in $Get paths until further researched... */ charset = DCCHARSET; if(!strcmp(cmd, "$GetZBlock") || !strcmp(cmd, "$UGetZBlock")) initcompress(peer, CPRS_ZLIB); @@ -1863,14 +1939,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|"); @@ -1895,6 +1967,13 @@ 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)) { + close(fd); + qstr(sk, "$MaxedOut|"); + return; + } if((start != 0) && ((start >= sb.st_size) || (lseek(fd, start, SEEK_SET) < 0))) { close(fd); @@ -1947,14 +2026,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) @@ -1994,6 +2069,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|"); @@ -2053,9 +2134,12 @@ static void handletthl(struct dcpeer *peer) { pushtigertree(&peer->tth, peer->inbuf); memmove(peer->inbuf, peer->inbuf + 24, peer->inbufdata -= 24); + peer->curread += 24; } - if((peer->curread += 24) >= peer->totalsize) + 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); @@ -2094,9 +2178,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")) { @@ -2112,6 +2199,12 @@ static void cmd_adcsnd(struct socket *sk, struct dcpeer *peer, char *cmd, char * goto out; } startdl(peer); + if(peer->inbufdata > 0) + { + sockpushdata(sk, peer->inbuf, peer->inbufdata); + peer->inbufdata = 0; + transread(sk, peer); + } } else { /* We certainly didn't request this...*/ freedcpeer(peer); @@ -2139,6 +2232,12 @@ static void cmd_sending(struct socket *sk, struct dcpeer *peer, char *cmd, char return; } startdl(peer); + if(peer->inbufdata > 0) + { + sockpushdata(sk, peer->inbuf, peer->inbufdata); + peer->inbufdata = 0; + transread(sk, peer); + } } /* @@ -2173,7 +2272,7 @@ static int hubreqconn(struct fnetpeer *peer) errno = EFAULT; return(1); } - if((mbsnick = icwcstombs(peer->id, DCCHARSET)) == NULL) + if((mbsnick = icwcstombs(peer->id, hub->charset)) == NULL) return(1); /* Shouldn't happen, of course, but who knows... */ if(tcpsock != NULL) { @@ -2192,12 +2291,12 @@ static int hubsendchat(struct fnetnode *fn, int public, wchar_t *to, wchar_t *st char *mbsstring, *mbsto; hub = fn->data; - if((mbsto = icwcstombs(to, DCCHARSET)) == NULL) + if((mbsto = icwcstombs(to, hub->charset)) == NULL) { errno = EILSEQ; return(1); } - if((mbsstring = icwcstombs(string, DCCHARSET)) == NULL) + if((mbsstring = icwcstombs(string, hub->charset)) == NULL) { errno = EILSEQ; return(1); @@ -2367,10 +2466,10 @@ static int hubsearch(struct fnetnode *fn, struct search *srch, struct srchfnnlis if(minsize != 0) { sizebuf2(sstr, sstrdata + 32, 1); - snprintf(sstr + sstrdata, sstrsize - sstrdata, "T?F?%i?1?", minsize); + sstrdata += snprintf(sstr + sstrdata, sstrsize - sstrdata, "T?F?%i?1?", minsize); } else if(maxsize != -1) { sizebuf2(sstr, sstrdata + 32, 1); - snprintf(sstr + sstrdata, sstrsize - sstrdata, "T?T?%i?1?", maxsize); + sstrdata += snprintf(sstr + sstrdata, sstrsize - sstrdata, "T?T?%i?1?", maxsize); } else { bufcat(sstr, "F?F?0?1?", 8); } @@ -2378,6 +2477,7 @@ static int hubsearch(struct fnetnode *fn, struct search *srch, struct srchfnnlis { for(cur = list; cur != NULL; cur = cur->next) { + /* Use DCCHARSET in $Get paths until further researched... */ if((buf = icwcstombs(cur->str, DCCHARSET)) == NULL) { /* Can't find anything anyway if the search expression @@ -2454,6 +2554,8 @@ struct command hubcmds[] = {"$To:", cc(cmd_to)}, {"$SR", cc(cmd_sr)}, {"$UserCommand", cc(cmd_usercommand)}, + {"$GetPass", cc(cmd_getpass)}, + {"$LogedIn", cc(cmd_logedin)}, /* sic */ {NULL, NULL} }; @@ -2550,10 +2652,13 @@ 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); socksettos(peer->sk, confgetint("fnet", "fnptos")); + transfer->flags.b.minislot = 0; peer->sk->writecb = NULL; } } @@ -2630,6 +2735,7 @@ static void udpread(struct socket *sk, void *data) char *buf, *p, *p2, *hashbuf; size_t buflen, hashlen; char *nick, *filename, *hubname; + struct sockaddr_in hubaddr; int size, slots; struct fnetnode *fn, *myfn; struct dchub *hub; @@ -2689,14 +2795,30 @@ static void udpread(struct socket *sk, void *data) return; } *p2 = 0; - if((wnick = icmbstowcs(nick, DCCHARSET)) == NULL) + p = p2 + 2; + if((p2 = strchr(p, ':')) == NULL) { free(buf); return; } + *(p2++) = 0; + hubaddr.sin_family = AF_INET; + if(!inet_aton(p, &hubaddr.sin_addr)) + { + free(buf); + return; + } + p = p2; + if((p2 = strchr(p, ')')) == NULL) + { + free(buf); + return; + } + *p2 = 0; + hubaddr.sin_port = htons(atoi(p)); + /* Use DCCHARSET in $Get paths until further researched... */ if((wfile = icmbstowcs(filename, DCCHARSET)) == NULL) { - free(wnick); free(buf); return; } @@ -2728,6 +2850,25 @@ static void udpread(struct socket *sk, void *data) } } } + if(myfn == NULL) + { + for(fn = fnetnodes; fn != NULL; fn = fn->next) + { + if((fn->fnet == &dcnet) && (fn->sk != NULL) && addreq(fn->sk->remote, (struct sockaddr *)&hubaddr)) + { + myfn = fn; + break; + } + } + } + hub = NULL; + if(myfn != NULL) + hub = myfn->data; + if((wnick = icmbstowcs(nick, (hub == NULL)?DCCHARSET:(hub->charset))) == NULL) + { + free(buf); + return; + } sr = newsrchres(&dcnet, wfile, wnick); if(sr->peernick != NULL) free(sr->peernick); @@ -2784,7 +2925,7 @@ static int hubsetnick(struct fnetnode *fn, wchar_t *newnick) char *buf; hub = fn->data; - if((buf = icwcstombs(newnick, DCCHARSET)) == NULL) + if((buf = icwcstombs(newnick, (hub == NULL)?DCCHARSET:(hub->charset))) == NULL) return(1); if((strchr(buf, ' ') != NULL) || (strchr(buf, '|') != NULL) || (strchr(buf, '$') != NULL)) { @@ -2805,10 +2946,38 @@ static int hubsetnick(struct fnetnode *fn, wchar_t *newnick) static struct dchub *newdchub(struct fnetnode *fn) { struct dchub *new; + wchar_t *emu; + wchar_t *wcharset; + char *charset; new = smalloc(sizeof(*new)); memset(new, 0, sizeof(*new)); fn->data = new; + if(confgetint("dc", "dcppemu")) + new->dcppemu = 1; + if((emu = wpfind(fn->args, L"dcppemu")) != NULL) + { + if(*emu == L'y') + new->dcppemu = 1; + if(*emu == L'n') + new->dcppemu = 0; + } + charset = NULL; + if((wcharset = wpfind(fn->args, L"charset")) != NULL) + { + if((charset = icwcstombs(wcharset, "US-ASCII")) != NULL) + { + if(!havecharset(charset)) + { + free(charset); + charset = NULL; + } + } + } + if(charset != NULL) + new->charset = charset; + else + new->charset = sstrdup(DCCHARSET); if(hubsetnick(fn, fn->mynick)) fnetsetnick(fn, L"DoldaConnectUser-IN"); /* IN as in Invalid Nick */ @@ -2824,6 +2993,8 @@ static struct dcpeer *newdcpeer(struct socket *sk) new->transfer = NULL; getsock(sk); new->sk = sk; + if(confgetint("dc", "dcppemu")) + new->dcppemu = 1; new->next = peers; new->prev = NULL; if(peers != NULL) @@ -2853,6 +3024,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; @@ -2874,6 +3047,8 @@ static void freedcpeer(struct dcpeer *peer) free(peer->wcsname); if(peer->nativename != NULL) free(peer->nativename); + if(peer->charset != NULL) + free(peer->charset); if(peer->fn != NULL) putfnetnode(peer->fn); while((qcmd = ulqcmd(&peer->queue)) != NULL) @@ -2914,6 +3089,8 @@ static void hubdestroy(struct fnetnode *fn) free(hub->nativename); if(hub->nativenick != NULL) free(hub->nativenick); + if(hub->charset != NULL) + free(hub->charset); if(hub->inbuf != NULL) free(hub->inbuf); free(hub); @@ -2969,15 +3146,15 @@ static void peerread(struct socket *sk, struct dcpeer *peer) newqcmd(&peer->queue, peer->inbuf); for(cmd = peercmds; cmd->handler != NULL; cmd++) { - if(!memcmp(peer->inbuf, cmd->name, strlen(cmd->name)) && (peer->inbuf[strlen(cmd->name)] == 0)) + if(!memcmp(peer->inbuf, cmd->name, strlen(cmd->name)) && ((peer->inbuf[strlen(cmd->name)] == ' ') || (peer->inbuf[strlen(cmd->name)] == '|'))) break; } + memmove(peer->inbuf, p, peer->inbufdata -= p - peer->inbuf); if(cmd->stop) { peer->state = PEER_STOP; break; } - memmove(peer->inbuf, p, peer->inbufdata -= p - peer->inbuf); } } else if(peer->state == PEER_TTHL) { handletthl(peer); @@ -2992,20 +3169,24 @@ static void peererror(struct socket *sk, int err, struct dcpeer *peer) static void peerconnect(struct socket *sk, int err, struct fnetnode *fn) { struct dcpeer *peer; + struct dchub *hub; if(err != 0) { putfnetnode(fn); return; } + hub = fn->data; peer = newdcpeer(sk); peer->fn = fn; peer->accepted = 0; + peer->dcppemu = hub->dcppemu; sk->readcb = (void (*)(struct socket *, void *))peerread; 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); } @@ -3020,6 +3201,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) @@ -3037,6 +3219,7 @@ static void updatehmlist(void) while(1) { ic = 0; + /* Use DCCHARSET in $Get paths until further researched... */ if((buf2 = icwcstombs(node->name, DCCHARSET)) != NULL) { for(i = 0; i < lev; i++) @@ -3201,7 +3384,10 @@ static void updatexmllist(void) for(i = 0; i < sizeof(cidbuf) - 1; i++) cidbuf[i] = (rand() % ('Z' - 'A' + 1)) + 'A'; cidbuf[i] = 0; - fprintf(fs, "\r\n", cidbuf, DCIDFULL); + if(confgetint("dc", "dcppemu")) + fprintf(fs, "\r\n", cidbuf); + else + fprintf(fs, "\r\n", cidbuf, "DoldaConnect" VERSION); node = shareroot->child; lev = 0; @@ -3246,11 +3432,10 @@ static void updatexmllist(void) } } -#ifdef DCPP_MASQUERADE - fprintf(fs, ""); -#else - fprintf(fs, "\r\n"); -#endif + if(confgetint("dc", "dcppemu")) + fprintf(fs, ""); + else + fprintf(fs, "\r\n"); fclose(fs); } @@ -3379,6 +3564,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); @@ -3488,6 +3676,7 @@ static struct configvar myvars[] = {CONF_VAR_STRING, "email", {.str = L"spam@spam.org"}}, {CONF_VAR_INT, "udpport", {.num = 0}}, {CONF_VAR_INT, "tcpport", {.num = 0}}, + {CONF_VAR_BOOL, "dcppemu", {.num = 0}}, {CONF_VAR_END} };