+ void *buf;
+ size_t blen;
+
+ if((transfer->datapipe != NULL) && (sockqueueleft(transfer->datapipe) > 0)) {
+ buf = sockgetinbuf(sk, &blen);
+ if((transfer->endpos >= 0) && (transfer->curpos + blen > transfer->endpos))
+ blen = transfer->endpos - transfer->curpos;
+ sockqueue(transfer->datapipe, buf, blen);
+ free(buf);
+ time(&transfer->activity);
+ transfer->curpos += blen;
+ bytesupload += blen;
+ CBCHAINDOCB(transfer, trans_p, transfer);
+ }
+}
+
+static void dataread(struct socket *sk, struct transfer *transfer)
+{
+ void *buf;
+ size_t blen;
+
+ if((transfer->localend != NULL) && (sockqueueleft(transfer->localend) > 0)) {
+ buf = sockgetinbuf(sk, &blen);
+ if((transfer->endpos >= 0) && (transfer->curpos + blen > transfer->endpos))
+ blen = transfer->endpos - transfer->curpos;
+ sockqueue(transfer->localend, buf, blen);
+ free(buf);
+ transfer->curpos += blen;
+ bytesdownload += blen;
+ CBCHAINDOCB(transfer, trans_p, transfer);
+ }
+}
+
+static void localwrite(struct socket *sk, struct transfer *transfer)
+{
+ if(transfer->datapipe != NULL)
+ dataread(transfer->datapipe, transfer);
+}
+
+static void datawrite(struct socket *sk, struct transfer *transfer)
+{
+ if(transfer->localend != NULL)
+ localread(transfer->localend, transfer);
+}
+
+static void localerr(struct socket *sk, int errno, struct transfer *transfer)
+{
+ if(transfer->datapipe != NULL)
+ closesock(transfer->datapipe);
+}
+
+static void dataerr(struct socket *sk, int errno, struct transfer *transfer)
+{
+ if(transfer->dir == TRNSD_DOWN) {
+ if(transfer->curpos >= transfer->size) {
+ transfersetstate(transfer, TRNS_DONE);
+ if(transfer->localend != NULL) {
+ closesock(transfer->localend);
+ quitsock(transfer->localend);
+ transfer->localend = NULL;
+ }
+ } else {
+ resettransfer(transfer);
+ }
+ } else if(transfer->dir == TRNSD_UP) {
+ transfer->close = 1;
+ }
+}
+
+void transferattach(struct transfer *transfer, struct socket *dpipe)
+{
+ transferdetach(transfer);
+ getsock(transfer->datapipe = dpipe);
+ dpipe->readcb = (void (*)(struct socket *, void *))dataread;
+ dpipe->writecb = (void (*)(struct socket *, void *))datawrite;
+ dpipe->errcb = (void (*)(struct socket *, int, void *))dataerr;
+ dpipe->data = transfer;