36071edc0403574d51170357bab076e39d076826 galt Thu Mar 23 16:42:09 2017 -0700 Adds ftp proxy capability to system. Works with Squid 3.5 ftp_port at least. refs #19124 diff --git src/lib/net.c src/lib/net.c index 0acfb05..a4492d0 100644 --- src/lib/net.c +++ src/lib/net.c @@ -944,70 +944,96 @@ } dataPos += rd; if (params->npu.byteRangeEnd != -1 && dataPos >= params->npu.byteRangeEnd) break; } if (rd == -1) // Again, avoid abort in child process. errnoWarn("error reading ftp socket"); close(params->pipefd[1]); /* we are done with it */ close(params->sd); close(params->sdata); return NULL; } static int netGetOpenFtpSockets(char *url, int *retCtrlSd) -/* Return a socket descriptor for url data (url can end in ";byterange:start-end", +/* Return a socket descriptor for url data (url can end in ";byterange:start-end)", * or -1 if error. * If retCtrlSd is non-null, keep the control socket alive and set *retCtrlSd. * Otherwise, create a pipe and fork to keep control socket alive in the child * process until we are done fetching data. */ { char cmd[256]; /* Parse the URL and connect. */ struct netParsedUrl npu; +struct netParsedUrl pxy; netParseUrl(url, &npu); if (!sameString(npu.protocol, "ftp")) errAbort("netGetOpenFtpSockets: url (%s) is not for ftp.", url); -int sd = openFtpControlSocket(npu.host, atoi(npu.port), npu.user, npu.password); + +boolean noProxy = checkNoProxy(npu.host); +char *proxyUrl = getenv("ftp_proxy"); +if (noProxy) + proxyUrl = NULL; + +int sd = -1; +if (proxyUrl) + { + netParseUrl(proxyUrl, &pxy); + if (!sameString(pxy.protocol, "ftp")) + errAbort("Unknown proxy protocol %s in %s.", pxy.protocol, proxyUrl); + char proxyUser[4096]; + safef(proxyUser, sizeof proxyUser, "%s@%s:%s", npu.user, npu.host, npu.port); + sd = openFtpControlSocket(pxy.host, atoi(pxy.port), proxyUser, npu.password); + verbose(2, "%s as %s via proxy %s\n", url, proxyUser, proxyUrl); + } +else + { + sd = openFtpControlSocket(npu.host, atoi(npu.port), npu.user, npu.password); + } + if (sd == -1) return -1; struct dyString *rs = NULL; if (!sendFtpCommand(sd, "PASV\r\n", &rs, NULL)) { close(sd); return -1; } /* 227 Entering Passive Mode (128,231,210,81,222,250) */ if (npu.byteRangeStart != -1) { safef(cmd,sizeof(cmd),"REST %lld\r\n", (long long) npu.byteRangeStart); if (!sendFtpCommand(sd, cmd, NULL, NULL)) { close(sd); return -1; } } /* RETR for files, LIST for directories ending in / */ safef(cmd,sizeof(cmd),"%s %s\r\n",((npu.file[strlen(npu.file)-1]) == '/') ? "LIST" : "RETR", npu.file); sendFtpCommandOnly(sd, cmd); -int sdata = netConnect(npu.host, parsePasvPort(rs->string)); +int sdata = -1; +if (proxyUrl) + sdata = netConnect(pxy.host, parsePasvPort(rs->string)); +else + sdata = netConnect(npu.host, parsePasvPort(rs->string)); dyStringFree(&rs); if (sdata < 0) { close(sd); return -1; } int secondsWaited = 0; while (TRUE) { if (secondsWaited >= 10) { warn("ftp server error on cmd=[%s] timed-out waiting for data or error", cmd); close(sd); close(sdata); @@ -1025,31 +1051,31 @@ return -1; } } ++secondsWaited; } if (retCtrlSd != NULL) { *retCtrlSd = sd; return sdata; } else { /* Because some FTP servers will kill the data connection * as soon as the control connection closes, - * we have to develop a workaround using a partner process. */ + * we have to develop a workaround using a partner thread. */ fflush(stdin); fflush(stdout); fflush(stderr); struct netConnectFtpParams *params; AllocVar(params); params->sd = sd; params->sdata = sdata; params->npu = npu; /* make a pipe (fds go in pipefd[0] and pipefd[1]) */ if (pipe(params->pipefd) != 0) errAbort("netGetOpenFtpSockets: failed to create pipe: %s", strerror(errno)); int rc; rc = pthread_create(¶ms->thread, NULL, sendFtpDataToPipeThread, (void *)params); if (rc)