Add pause/resume support to libxpnet's ftp and download impls.

b  = 67247
r  = ssu
sr = mscott
This commit is contained in:
sgehani%netscape.com 2001-05-03 02:15:07 +00:00
Родитель 136c629c2f
Коммит 882fe0046f
7 изменённых файлов: 203 добавлений и 27 удалений

Просмотреть файл

@ -32,8 +32,10 @@ DIRS = src
# solaris tbox doesn't like this!
ifneq (,$(filter Linux,$(OS_ARCH)))
ifdef ENABLE_TESTS
DIRS += test
endif
endif
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -24,7 +24,11 @@
DEPTH=..\..\..
DIRS=src test
DIRS=src \
!if !defined(DISABLE_TESTS)
test \
!endif
$(NULL)
include <$(DEPTH)\config\rules.mak>

Просмотреть файл

@ -121,8 +121,36 @@ nsFTPConn::Open(char *aHost)
}
int
nsFTPConn::Get(char *aSrvPath, char *aLoclPath, int aType, int aOvWrite,
FTPGetCB aCBFunc)
nsFTPConn::ResumeOrGet(char *aSrvPath, char *aLoclPath, int aType,
int aOvWrite, FTPGetCB aCBFunc)
{
struct stat stbuf;
int err = OK;
int resPos = 0;
if (!aLoclPath)
return E_PARAM;
/* stat local file */
err = stat(aLoclPath, &stbuf);
if (err == 0)
resPos = stbuf.st_size;
return Get(aSrvPath, aLoclPath, aType, resPos, aOvWrite, aCBFunc);
}
int
nsFTPConn::Get(char *aSrvPath, char *aLoclPath, int aType,
int aOvWrite, FTPGetCB aCBFunc)
{
// deprecated API; wrapper for backwards compatibility
return ResumeOrGet(aSrvPath, aLoclPath, aType, aOvWrite, aCBFunc);
}
int
nsFTPConn::Get(char *aSrvPath, char *aLoclPath, int aType, int aResumePos,
int aOvWrite, FTPGetCB aCBFunc)
{
struct stat dummy;
int err = OK, wrote = 0, totBytesRd = 0;
@ -155,6 +183,13 @@ nsFTPConn::Get(char *aSrvPath, char *aLoclPath, int aType, int aOvWrite,
if (err == OK && (resp[0] == '2'))
fileSize = atoi(&resp[4]);
if (aResumePos > 0)
{
/* issue restart command */
sprintf(cmd, "REST %d\r\n", aResumePos);
ERR_CHECK(IssueCmd(cmd, resp, kRespBufSize, mCntlSock));
}
/* issue RETR command on control connection */
sprintf(cmd, "RETR %s\r\n", aSrvPath);
ERR_CHECK(IssueCmd(cmd, resp, kRespBufSize, mCntlSock));
@ -164,11 +199,22 @@ nsFTPConn::Get(char *aSrvPath, char *aLoclPath, int aType, int aOvWrite,
ERR_CHECK(mDataSock->SrvAccept());
/* initialize locl file */
if (!(loclfd = fopen(aLoclPath, aType==BINARY ? "wb" : "w")) ||
(fseek(loclfd, 0, SEEK_SET) != 0))
if (aResumePos <= 0)
{
err = E_LOCL_INIT;
goto BAIL;
if (!(loclfd = fopen(aLoclPath, aType==BINARY ? "w+b" : "w+")))
{
err = E_LOCL_INIT;
goto BAIL;
}
}
else
{
if (!(loclfd = fopen(aLoclPath, aType==BINARY ? "r+b" : "r+")) ||
(fseek(loclfd, aResumePos, SEEK_SET) != 0))
{
err = E_LOCL_INIT;
goto BAIL;
}
}
totBytesRd = 0;
@ -296,6 +342,27 @@ nsFTPConn::IssueCmd(char *aCmd, char *aResp, int aRespSize, nsSocket *aSock)
}
}
/* restart command case */
else if (strncmp(aCmd, "REST", 4) == 0)
{
switch (*aResp)
{
case '1':
case '2':
err = E_CMD_ERR;
break;
case '3':
break;
case '4':
case '5':
err = E_CMD_FAIL;
break;
default:
err = E_CMD_UNEXPECTED;
break;
}
}
/* regular interpretation of err codes */
else
{

Просмотреть файл

@ -52,8 +52,12 @@ public:
int Open();
int Open(char *aHost);
int Get(char *aSrvPath, char *aLoclPath, int aType, int aOvWrite,
FTPGetCB aCBFunc);
int ResumeOrGet(char *aSrvPath, char *aLoclPath, int aType,
int aOvWrite, FTPGetCB aCBFunc);
int Get(char *aSrvPath, char *aLoclPath, int aType,
int aOvWrite, FTPGetCB aCBFunc);
int Get(char *aSrvPath, char *aLoclPath, int aType, int aResumePos,
int aOvWrite, FTPGetCB aCBFunc);
int Close();
/*--------------------------------------------------------------------*

Просмотреть файл

@ -112,7 +112,36 @@ nsHTTPConn::Open()
}
int
nsHTTPConn::ResumeOrGet(HTTPGetCB aCallback, char *aDestFile)
{
struct stat stbuf;
int rv = 0;
int resPos = 0;
if (!aDestFile)
return E_PARAM;
/* stat local file */
rv = stat(aDestFile, &stbuf);
if (rv == 0)
resPos = stbuf.st_size;
return Get(aCallback, aDestFile, resPos);
// XXX TO DO:
// XXX handle proxies
}
int
nsHTTPConn::Get(HTTPGetCB aCallback, char *aDestFile)
{
// deprecated API; wrapper for backwards compatibility
return ResumeOrGet(aCallback, aDestFile);
}
int
nsHTTPConn::Get(HTTPGetCB aCallback, char *aDestFile, int aResumePos)
{
int rv;
char *pathToUse;
@ -136,11 +165,11 @@ nsHTTPConn::Get(HTTPGetCB aCallback, char *aDestFile)
}
// issue request
rv = Request();
rv = Request(aResumePos);
// recv response
if (rv == OK)
rv = Response(aCallback, aDestFile);
rv = Response(aCallback, aDestFile, aResumePos);
return rv;
}
@ -169,7 +198,7 @@ nsHTTPConn::SetProxyInfo(char *aProxiedURL, char *aProxyUser,
}
int
nsHTTPConn::Request()
nsHTTPConn::Request(int aResumePos)
{
char req[kReqBufSize];
char hdr[kHdrBufSize];
@ -249,6 +278,13 @@ nsHTTPConn::Request()
}
// byte range support
if (aResumePos > 0)
{
sprintf(hdr, "Range: bytes=%d-%s", aResumePos, kCRLF);
strcat(req, hdr);
}
// headers all done so indicate
strcat(req, kCRLF);
@ -264,7 +300,7 @@ nsHTTPConn::Request()
}
int
nsHTTPConn::Response(HTTPGetCB aCallback, char *aDestFile)
nsHTTPConn::Response(HTTPGetCB aCallback, char *aDestFile, int aResumePos)
{
// NOTE: overwrites dest file if it already exists
@ -279,9 +315,24 @@ nsHTTPConn::Response(HTTPGetCB aCallback, char *aDestFile)
return E_PARAM;
// open dest file
destFd = fopen(aDestFile, "w+b");
if (!destFd)
return E_OPEN_FILE;
if (aResumePos > 0)
{
destFd = fopen(aDestFile, "r+b");
if (!destFd)
return E_OPEN_FILE;
if (fseek(destFd, aResumePos, SEEK_SET) != 0)
{
fclose(destFd);
return E_SEEK_FILE;
}
}
else
{
destFd = fopen(aDestFile, "w+b");
if (!destFd)
return E_OPEN_FILE;
}
// iteratively recv response
do
@ -324,9 +375,10 @@ nsHTTPConn::Response(HTTPGetCB aCallback, char *aDestFile)
if (fwriteLen > 0)
bytesWritten += fwriteLen;
if (aCallback && (aCallback(bytesWritten, expectedSize) == E_USER_CANCEL))
rv = E_USER_CANCEL; /* we want to ignore all errors returned
* from aCallback() except E_USER_CANCEL */
if (aCallback &&
(aCallback(bytesWritten, expectedSize) == E_USER_CANCEL))
rv = E_USER_CANCEL; // we want to ignore all errors returned
// from aCallback() except E_USER_CANCEL
} while (rv == nsSocket::E_READ_MORE || rv == nsSocket::OK);

Просмотреть файл

@ -37,7 +37,9 @@ public:
~nsHTTPConn();
int Open();
int ResumeOrGet(HTTPGetCB aCallback, char *aDestFile);
int Get(HTTPGetCB aCallback, char *aDestFile);
int Get(HTTPGetCB aCallback, char *aDestFile, int aResumePos);
int Close();
void SetProxyInfo(char *aProxiedURL, char *aProxyUser,
@ -54,12 +56,13 @@ public:
E_REQ_INCOMPLETE = -804,
E_B64_ENCODE = -805,
E_OPEN_FILE = -806,
E_SEEK_FILE = -807,
E_USER_CANCEL = -813
};
private:
int Request();
int Response(HTTPGetCB aCallback, char *aDestFile);
int Request(int aResumePos);
int Response(HTTPGetCB aCallback, char *aDestFile, int aResumePos);
void ParseContentLength(const char *aBuf, int *aLength);
int Base64Encode(const unsigned char *in_str, int in_len,
char *out_str, int out_len);

Просмотреть файл

@ -64,8 +64,9 @@ spew(char *funcName, int rv)
void
usage(char *prog)
{
fprintf(stderr, "usage: %s <URL> [ProxyServer ", prog);
fprintf(stderr, "ProxyPort [ProxyUserName ProxyPassword]\n");
fprintf(stderr, "usage: %s <URL>\n\t\t[<ProxyServer> ", prog);
fprintf(stderr, "<ProxyPort> [<ProxyUserName> <ProxyPassword>]]\n");
fprintf(stderr, "\t\t[-r<ResumePos> or -rg]\n");
#ifdef macintosh
int fin = getchar();
@ -77,10 +78,11 @@ main(int argc, char **argv)
{
char *proxyUser = 0, *proxyPswd = 0;
char proxyURL[kProxySrvrLen];
int rv = 0;
int rv = 0, resPos = 0;
time_t startTime, endTime;
double dlTime = 0; /* download time */
float dlRate = 0; /* download rate */
int bResumeOrGet = 0;
#ifdef macintosh
argc = ccommand(&argv);
@ -92,6 +94,25 @@ main(int argc, char **argv)
exit(1);
}
/* get resume pos if -r arg passed in */
for (int i = 1; i < argc; ++i)
{
/* resume or get */
if (strncmp(argv[i], "-rg", 3) == 0)
{
bResumeOrGet = 1;
}
/* resume from pos */
else if (strncmp(argv[i], "-r", 2) == 0)
{
resPos = atoi(argv[i] + 2);
printf("resPos = %d\n", resPos);
break;
}
}
/* has a proxy server been specified? */
if (argc >= 4)
{
@ -117,7 +138,14 @@ main(int argc, char **argv)
spew("nsHTTPConn::Open", rv);
startTime = time(NULL);
rv = conn->Get(ProgressCB, NULL); // use leaf from URL
if (bResumeOrGet)
{
rv = conn->ResumeOrGet(ProgressCB, NULL); // use leaf from URL
}
else
{
rv = conn->Get(ProgressCB, NULL, resPos); // use leaf from URL
}
endTime = time(NULL);
printf("\n"); // newline after progress completes
spew("nsHTTPConn::Get", rv);
@ -136,7 +164,14 @@ main(int argc, char **argv)
spew("nsHTTPConn::Open", rv);
startTime = time(NULL);
rv = conn->Get(ProgressCB, NULL);
if (bResumeOrGet)
{
rv = conn->ResumeOrGet(ProgressCB, NULL);
}
else
{
rv = conn->Get(ProgressCB, NULL, resPos);
}
endTime = time(NULL);
printf("\n"); // newline after progress completes
spew("nsHTTPConn::Get", rv);
@ -162,7 +197,16 @@ main(int argc, char **argv)
if (strrchr(path, '/') != (path + strlen(path)))
file = strrchr(path, '/') + 1; // set to leaf name
startTime = time(NULL);
rv = conn->Get(path, file, nsFTPConn::BINARY, 1, ProgressCB);
if (bResumeOrGet)
{
rv = conn->ResumeOrGet(path, file, nsFTPConn::BINARY, 1,
ProgressCB);
}
else
{
rv = conn->Get(path, file, nsFTPConn::BINARY, resPos, 1,
ProgressCB);
}
endTime = time(NULL);
printf("\n"); // newline after progress completes
spew("nsFTPConn::Get", rv);