18725, r=sdagley. FTP is now cancellable.

* added new state to FTP. data channel reading state.

* the FTP channel's SetConnectionQueue now handles a null arg and resets it's eventq if null is passed in.
This commit is contained in:
valeski%netscape.com 1999-11-13 00:31:36 +00:00
Родитель d2b0b19ca8
Коммит d16733f10b
3 изменённых файлов: 103 добавлений и 63 удалений

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

@ -272,7 +272,7 @@ nsFTPChannel::AsyncRead(PRUint32 startPosition, PRInt32 readCount,
mEventQueue, /* event queue for this thread */
mHandler,
this, ctxt, mEventSinkGetter);
mHandler = 0; // XXX this can go away when the channel is no longer being leaked.
mHandler = 0;
if (NS_FAILED(rv)) {
NS_RELEASE(protocolInterpreter);
return rv;
@ -394,21 +394,27 @@ nsFTPChannel::SetOwner(nsISupports * aOwner)
// nsIFTPChannel methods:
NS_IMETHODIMP
nsFTPChannel::SetConnectionQueue(nsIEventQueue *aEventQ) {
nsresult rv;
// create the proxy object so we can call into the FTP thread.
NS_WITH_SERVICE(nsIProxyObjectManager, proxyManager, kProxyObjectManagerCID, &rv);
if (NS_FAILED(rv)) return rv;
nsresult rv = NS_OK;
// change the thread request over to a proxy thread request.
rv = proxyManager->GetProxyObject(aEventQ,
NS_GET_IID(nsIRequest),
mThreadRequest,
PROXY_SYNC | PROXY_ALWAYS,
getter_AddRefs(mProxiedThreadRequest));
mThreadRequest = 0;
if (NS_FAILED(rv)) return rv;
if (aEventQ) {
// create the proxy object so we can call into the FTP thread.
NS_WITH_SERVICE(nsIProxyObjectManager, proxyManager, kProxyObjectManagerCID, &rv);
if (NS_FAILED(rv)) return rv;
return NS_OK;
// change the thread request over to a proxy thread request.
rv = proxyManager->GetProxyObject(aEventQ,
NS_GET_IID(nsIRequest),
mThreadRequest,
PROXY_SYNC | PROXY_ALWAYS,
getter_AddRefs(mProxiedThreadRequest));
mThreadRequest = 0;
} else {
// no event queue means the thread has effectively gone away.
mThreadRequest = 0;
mProxiedThreadRequest = 0;
}
return rv;
}
NS_IMETHODIMP
@ -436,6 +442,7 @@ nsFTPChannel::OnStopRequest(nsIChannel* channel, nsISupports* context,
nsresult aStatus,
const PRUnichar* aMsg) {
nsresult rv = NS_OK;
mProxiedThreadRequest = 0; // we don't want anyone trying to use this when the underlying thread has left.
if (mEventSink) {
nsAutoString statusMsg("FTP transaction complete.");
#ifndef BUG_16273_FIXED //TODO

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

@ -215,6 +215,59 @@ nsFtpConnectionThread::Process() {
}
// END: FTP_READ_BUF
case FTP_READ_DATA_BUF:
{
PRUint32 read = 0, readSoFar = 0;
while (readSoFar < NS_FTP_BUFFER_READ_SIZE) {
// suck in the data from the server
PRUint32 avail;
rv = mBufInStream->Available(&avail);
if (NS_FAILED(rv)) {
mInternalError = NS_ERROR_FAILURE;
mState = FTP_ERROR;
break;
}
rv = mBufOutStream->WriteFrom(mDInStream, NS_FTP_BUFFER_READ_SIZE-readSoFar, &read);
if (NS_FAILED(rv)) {
mInternalError = NS_ERROR_FAILURE;
mState = FTP_ERROR;
break;
}
readSoFar += read;
if (read == 0) {
// we've exhausted the stream, send any data we have left and get out of dodge.
rv = mListener->OnDataAvailable(mChannel, mContext, mBufInStream, avail, readSoFar);
if (NS_FAILED(rv)) {
mInternalError = NS_ERROR_FAILURE;
mState = FTP_ERROR;
break;
}
// we're done filling this end of the pipe. close it.
mBufOutStream->Close();
mState = FTP_READ_BUF;
mNextState = FTP_COMPLETE;
break; // this terminates the loop
}
if (readSoFar == NS_FTP_BUFFER_READ_SIZE) {
// we've filled our buffer, send the data off
rv = mListener->OnDataAvailable(mChannel, mContext, mBufInStream, avail, NS_FTP_BUFFER_READ_SIZE);
if (NS_FAILED(rv)) {
mInternalError = NS_ERROR_FAILURE;
mState = FTP_ERROR;
break;
}
mState = FTP_READ_DATA_BUF;
}
}
break;
}
// END: FTP_READ_DATA_BUF
case FTP_ERROR:
{
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("%x Process() - ERROR\n", mURL.get()));
@ -232,10 +285,13 @@ nsFtpConnectionThread::Process() {
case FTP_COMPLETE:
{
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("%x Process() - COMPLETE\n", mURL.get()));
// push through all of the pertinent state into the cache entry;
mConn->mCwd = mCwd;
rv = mConnCache->InsertConn(mCacheKey.GetBuffer(), mConn);
if (NS_FAILED(rv)) return rv;
if (NS_SUCCEEDED(mInternalError)) {
// we only want to cache the connection if things are ok.
// push through all of the pertinent state into the cache entry;
mConn->mCwd = mCwd;
rv = mConnCache->InsertConn(mCacheKey.GetBuffer(), mConn);
if (NS_FAILED(rv)) return rv;
}
rv = StopProcessing();
break;
@ -577,8 +633,6 @@ nsFtpConnectionThread::Process() {
if (FTP_ERROR == mState)
mInternalError = NS_ERROR_FAILURE;
mNextState = FTP_COMPLETE;
mDInStream->Close();
mDInStream = 0;
break;
}
// END: FTP_R_RETR
@ -1114,11 +1168,6 @@ nsFtpConnectionThread::S_size() {
// XXX should the actual file name be parsed out???
mFilename = path;
/*if (mServerType == FTP_VMS_TYPE) {
mState = FindGetState();
break;
}*/
nsCAutoString sizeBuf("SIZE ");
sizeBuf.Append(path);
sizeBuf.Append(FTP_CRLF);
@ -1341,46 +1390,10 @@ nsFtpConnectionThread::R_retr() {
mSentStart = PR_TRUE;
nsIBufferInputStream *bufInStrm = nsnull;
nsIBufferOutputStream *bufOutStrm = nsnull;
rv = NS_NewPipe(&bufInStrm, &bufOutStrm);
rv = NS_NewPipe(getter_AddRefs(mBufInStream), getter_AddRefs(mBufOutStream));
if (NS_FAILED(rv)) return FTP_ERROR;
nsIInputStream *inStream = nsnull;
rv = bufInStrm->QueryInterface(NS_GET_IID(nsIInputStream), (void**)&inStream);
if (NS_FAILED(rv)) return FTP_ERROR;
PRUint32 read = 0, readSoFar = 0;
while (readSoFar < NS_FTP_BUFFER_READ_SIZE) {
// suck in the data from the server
PRUint32 avail;
rv = inStream->Available(&avail);
if (NS_FAILED(rv)) return FTP_ERROR;
rv = bufOutStrm->WriteFrom(mDInStream, NS_FTP_BUFFER_READ_SIZE-readSoFar, &read);
if (NS_FAILED(rv)) return FTP_ERROR;
readSoFar += read;
if (read == 0) {
// we've exhausted the stream, send any data we have left and get out of dodge.
rv = mListener->OnDataAvailable(mChannel, mContext, inStream, avail, readSoFar);
if (NS_FAILED(rv)) return FTP_ERROR;
break; // this terminates the loop
}
if (readSoFar == NS_FTP_BUFFER_READ_SIZE) {
// we've filled our buffer, send the data off
readSoFar = 0;
rv = mListener->OnDataAvailable(mChannel, mContext, inStream, avail, NS_FTP_BUFFER_READ_SIZE);
if (NS_FAILED(rv)) return FTP_ERROR;
}
}
// we're done filling this end of the pipe. close it.
bufOutStrm->Close();
NS_RELEASE(inStream);
return FTP_READ_BUF;
return FTP_READ_DATA_BUF;
} else {
if (mServerType == FTP_VMS_TYPE) {
@ -1783,6 +1796,8 @@ nsFtpConnectionThread::Cancel(void)
rv = mDPipe->Cancel();
if (NS_FAILED(rv)) return rv;
}
mInternalError = NS_ERROR_FAILURE; // XXX should be an FTP code.
mState = FTP_COMPLETE;
return rv;
}
@ -1919,6 +1934,20 @@ nsFtpConnectionThread::StopProcessing() {
mCOutStream = 0;
mCInStream = 0;
NS_WITH_SERVICE(nsIProxyObjectManager, pIProxyObjectManager, kProxyObjectManagerCID, &rv);
if(NS_FAILED(rv)) return rv;
nsCOMPtr<nsIFTPChannel> ftpChannel;
rv = pIProxyObjectManager->GetProxyObject(mOutsideEventQueue,
NS_GET_IID(nsIFTPChannel),
mChannel,
PROXY_SYNC | PROXY_ALWAYS,
getter_AddRefs(ftpChannel));
if (NS_FAILED(rv)) return rv;
rv = ftpChannel->SetConnectionQueue(nsnull);
if (NS_FAILED(rv)) return rv;
// if we haven't sent an OnStartRequest() yet, fire one now. We don't want
// to blidly send an OnStop if we haven't "started" anything.
if (!mSentStart) {

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

@ -63,6 +63,7 @@ typedef enum _FTP_STATE {
//// Internal states
///////////////////////
FTP_READ_BUF,
FTP_READ_DATA_BUF,
FTP_ERROR,
FTP_COMPLETE,
@ -253,6 +254,9 @@ private:
nsXPIDLCString mURLSpec;
nsCOMPtr<nsIEventSinkGetter> mEventSinkGetter;
nsCOMPtr<nsIFTPChannel> mFTPChannel;
nsCOMPtr<nsIBufferInputStream> mBufInStream;
nsCOMPtr<nsIBufferOutputStream> mBufOutStream;
};
#define NS_FTP_BUFFER_READ_SIZE (8*1024)