+ if(peer->wcsname == NULL)
+ {
+ peer->close = 1;
+ return;
+ }
+ peer->direction = mydir;
+ if(peer->direction == TRNSD_UP)
+ {
+ if(confgetint("transfer", "ulquota") && hasupload(&dcnet, peer->wcsname))
+ {
+ peer->close = 1;
+ return;
+ }
+ 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, (peer->trpipe = mktrpipe(peer))->back);
+ transfersetstate(transfer, TRNS_HS);
+ }
+ transfersetnick(transfer, peer->wcsname);
+ peer->transfer = transfer;
+ CBREG(peer->transfer, trans_filterout, (int (*)(struct transfer *, wchar_t *, wchar_t *, void *))trresumecb, NULL, peer);
+ if(peer->extended)
+ sendsupports(peer);
+ qstrf(sk, "$Direction %s %i|", (peer->direction == TRNSD_UP)?"Upload":"Download", rand() % 10000);
+ if(peer->key != NULL)
+ qstrf(sk, "$Key %s|", peer->key);
+ if(peer->direction == TRNSD_DOWN)
+ requestfile(peer);
+ }
+}
+
+static void cmd_peerlock(struct socket *sk, struct dcpeer *peer, char *cmd, char *args)
+{
+ char *p, *key;
+ struct transfer *transfer;
+
+ if((p = strchr(args, ' ')) == NULL)
+ return;
+ *p = 0;
+ if(!strncmp(args, "EXTENDEDPROTOCOL", 16))
+ peer->extended = 1;
+ key = dcmakekey(args);
+ if(peer->accepted)
+ {
+ if(peer->wcsname == NULL)
+ {
+ peer->close = 1;
+ return;
+ }
+ sendmynick(peer);
+ sendpeerlock(peer);
+ if(peer->extended)
+ sendsupports(peer);
+ if((transfer = finddownload(peer->wcsname)) == NULL)
+ {
+ if(confgetint("transfer", "ulquota") && hasupload(&dcnet, peer->wcsname))
+ {
+ peer->close = 1;
+ return;
+ }
+ peer->direction = TRNSD_UP;
+ transfer = newupload(peer->fn, &dcnet, peer->wcsname, (peer->trpipe = mktrpipe(peer))->back);
+ } else {
+ peer->direction = TRNSD_DOWN;
+ transferattach(transfer, (peer->trpipe = mktrpipe(peer))->back);
+ transfersetstate(transfer, TRNS_HS);
+ }
+ transfersetnick(transfer, peer->wcsname);
+ peer->transfer = transfer;
+ CBREG(peer->transfer, trans_filterout, (int (*)(struct transfer *, wchar_t *, wchar_t *, void *))trresumecb, NULL, peer);
+ qstrf(sk, "$Direction %s %i|", (peer->direction == TRNSD_UP)?"Upload":"Download", rand() % 10000);
+ qstrf(sk, "$Key %s|", key);
+ free(key);
+ } else {
+ if(peer->key != NULL)
+ free(peer->key);
+ peer->key = key;
+ }
+}
+
+static void cmd_key(struct socket *sk, struct dcpeer *peer, char *cmd, char *args)
+{
+ /* NOP */
+}
+
+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;
+ peer->sk->errcb = (void (*)(struct socket *, int, void *))transerr;
+}
+
+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;
+ transwrite(peer->sk, peer);
+}
+
+static void cmd_filelength(struct socket *sk, struct dcpeer *peer, char *cmd, char *args)
+{
+ off_t size;
+ struct transfer *transfer;
+
+ if(peer->transfer == NULL)
+ {
+ peer->close = 1;
+ return;
+ }
+ size = strtoll(args, NULL, 10);
+ if(peer->transfer->size != size)
+ {