diff --git a/mozilla/netwerk/protocol/ftp/public/nsPIFTPChannel.idl b/mozilla/netwerk/protocol/ftp/public/nsPIFTPChannel.idl index 105b8bfb940..e097c8c77d7 100644 --- a/mozilla/netwerk/protocol/ftp/public/nsPIFTPChannel.idl +++ b/mozilla/netwerk/protocol/ftp/public/nsPIFTPChannel.idl @@ -30,7 +30,6 @@ interface nsIEventQueue; [scriptable, uuid(64718e40-18c2-11d3-9337-00104ba0fd40)] interface nsPIFTPChannel : nsIChannel { - void SetConnectionQueue(in nsIEventQueue aEventQ); void SetContentLength(in long aLength); void SetContentType(in string aContentType); void Stopped(in nsresult aStatus, in wstring aMsg); diff --git a/mozilla/netwerk/protocol/ftp/src/Makefile.in b/mozilla/netwerk/protocol/ftp/src/Makefile.in index 1e7c1aaabc8..cd0787f92f0 100644 --- a/mozilla/netwerk/protocol/ftp/src/Makefile.in +++ b/mozilla/netwerk/protocol/ftp/src/Makefile.in @@ -35,6 +35,7 @@ CPPSRCS = \ nsFTPChannel.cpp \ nsFtpConnectionThread.cpp \ nsFtpModule.cpp \ + nsFTPListener.cpp \ $(NULL) EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS) diff --git a/mozilla/netwerk/protocol/ftp/src/makefile.win b/mozilla/netwerk/protocol/ftp/src/makefile.win index 007f13dde7e..96a51ee9ce5 100644 --- a/mozilla/netwerk/protocol/ftp/src/makefile.win +++ b/mozilla/netwerk/protocol/ftp/src/makefile.win @@ -36,6 +36,7 @@ CPP_OBJS = \ .\$(OBJDIR)\nsFTPChannel.obj \ .\$(OBJDIR)\nsFtpConnectionThread.obj \ .\$(OBJDIR)\nsFtpModule.obj \ + .\$(OBJDIR)\nsFTPListener.obj \ $(NULL) LLIBS= \ diff --git a/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.cpp b/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.cpp index 25dc4b115ef..7321242b6ac 100644 --- a/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.cpp +++ b/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.cpp @@ -23,28 +23,21 @@ // ftp implementation #include "nsFTPChannel.h" +#include "nsIStreamListener.h" #include "nscore.h" #include "prlog.h" -#include "nsCOMPtr.h" #include "nsIServiceManager.h" -#include "nsFtpConnectionThread.h" -#include "nsIEventQueueService.h" -#include "nsIProgressEventSink.h" -#include "nsIInterfaceRequestor.h" #include "nsIMIMEService.h" -#include "nsProxyObjectManager.h" #include "nsIPipe.h" -#include "nsAutoLock.h" +#include "nsNetUtil.h" -static NS_DEFINE_IID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID); static NS_DEFINE_CID(kMIMEServiceCID, NS_MIMESERVICE_CID); -static NS_DEFINE_CID(kEventQueueService, NS_EVENTQUEUESERVICE_CID); #if defined(PR_LOGGING) extern PRLogModuleInfo* gFTPLog; #endif /* PR_LOGGING */ -// There are actually two transport connections established for an +// There are two transport connections established for an // ftp connection. One is used for the command channel , and // the other for the data channel. The command channel is the first // connection made and is used to negotiate the second, data, channel. @@ -135,39 +128,26 @@ nsFTPChannel::Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult) // cross thread call. NS_IMETHODIMP -nsFTPChannel::IsPending(PRBool *result) -{ +nsFTPChannel::IsPending(PRBool *result) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP -nsFTPChannel::Cancel(void) -{ - nsresult rv = NS_OK; - if (mProxiedThreadRequest) - rv = mProxiedThreadRequest->Cancel(); - return rv; +nsFTPChannel::Cancel(void) { + NS_ASSERTION(mConnThread, "lost the connection thread."); + return mConnThread->Cancel(); } NS_IMETHODIMP -nsFTPChannel::Suspend(void) -{ - nsresult rv = NS_OK; - if (mProxiedThreadRequest) - rv = mProxiedThreadRequest->Suspend(); - return rv; +nsFTPChannel::Suspend(void) { + NS_ASSERTION(mConnThread, "lost the connection thread."); + return mConnThread->Suspend(); } NS_IMETHODIMP -nsFTPChannel::Resume(void) -{ - // we can't use the mProxiedThreadRequest to resume the thread - // because it needs the event pump to be running on the thread - // (which is blocking right now). Instead wake it up directly - // with a monitor notification. - NS_ASSERTION(mConnThread, "FTP: connection thread was dropped"); - nsAutoCMonitor mon(mConnThread); - return mon.Notify(); +nsFTPChannel::Resume(void) { + NS_ASSERTION(mConnThread, "lost the connection thread."); + return mConnThread->Resume(); } //////////////////////////////////////////////////////////////////////////////// @@ -189,9 +169,6 @@ nsFTPChannel::GetURI(nsIURI * *aURL) return NS_OK; } -#define NS_FTP_SEGMENT_SIZE (2*1024) -#define NS_FTP_BUFFER_SIZE (8*1024) - NS_IMETHODIMP nsFTPChannel::OpenInputStream(PRUint32 startPosition, PRInt32 readCount, nsIInputStream **_retval) @@ -206,15 +183,12 @@ nsFTPChannel::OpenInputStream(PRUint32 startPosition, PRInt32 readCount, // and the FTP thread get's the output stream end. // The FTP thread will write to the output stream end // when data become available to it. - nsCOMPtr bufOutStream; - nsCOMPtr bufInStream; - rv = NS_NewPipe(getter_AddRefs(bufInStream), getter_AddRefs(bufOutStream), - nsnull, NS_FTP_SEGMENT_SIZE, NS_FTP_BUFFER_SIZE); + nsCOMPtr bufOutStream; // we don't use this piece + nsCOMPtr listener; + rv = NS_NewSyncStreamListener(_retval, getter_AddRefs(bufOutStream), + getter_AddRefs(listener)); if (NS_FAILED(rv)) return rv; - *_retval = NS_STATIC_CAST(nsIInputStream*, bufInStream.get()); - NS_ADDREF(*_retval); - /////////////////////////// //// setup channel state mSourceOffset = startPosition; @@ -224,28 +198,23 @@ nsFTPChannel::OpenInputStream(PRUint32 startPosition, PRInt32 readCount, //// setup the channel thread NS_NEWXPCOM(mConnThread, nsFtpConnectionThread); if (!mConnThread) return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(mConnThread); // keep our own ref to the thread obj (we'll - // release it later in this same call. + NS_ADDREF(mConnThread); - rv = mConnThread->Init(mHandler, this, nsnull, - mBufferSegmentSize, mBufferMaxSize); + rv = mConnThread->Init(mHandler, this, mBufferSegmentSize, mBufferMaxSize); mHandler = 0; if (NS_FAILED(rv)) { NS_RELEASE(mConnThread); return rv; } - rv = mConnThread->SetOutputStream(bufOutStream); + rv = mConnThread->SetStreamListener(listener); if (NS_FAILED(rv)) { NS_RELEASE(mConnThread); return rv; } - mThreadRequest = do_QueryInterface((nsISupports*)(nsIRequest*)mConnThread); - rv = mPool->DispatchRequest((nsIRunnable*)mConnThread); - NS_RELEASE(mConnThread); // we're done w/ the raw thread obj if (NS_FAILED(rv)) return rv; mConnected = PR_TRUE; @@ -272,16 +241,10 @@ nsFTPChannel::AsyncOpen(nsIStreamObserver *observer, nsISupports* ctxt) //// setup the channel thread NS_NEWXPCOM(mConnThread, nsFtpConnectionThread); if (!mConnThread) return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(mConnThread); - // becuase we want to use the actual thread object as a monitor variable - // we need to hang on to it until the thread itself tells us it's invalid. - // See nsFTPChannel::Stopped(). - NS_ADDREF(mConnThread); // keep our own ref to the thread obj - mThreadRequest = do_QueryInterface((nsISupports*)(nsIRequest*)mConnThread); - - rv = mConnThread->Init(mHandler, this, ctxt, - mBufferSegmentSize, mBufferMaxSize); + rv = mConnThread->Init(mHandler, this, mBufferSegmentSize, mBufferMaxSize); mHandler = 0; if (NS_FAILED(rv)) { NS_RELEASE(mConnThread); @@ -294,7 +257,6 @@ nsFTPChannel::AsyncOpen(nsIStreamObserver *observer, nsISupports* ctxt) mConnected = PR_TRUE; mAsyncOpen = PR_TRUE; - // start the run return mPool->DispatchRequest((nsIRunnable*)mConnThread); } @@ -332,8 +294,7 @@ nsFTPChannel::AsyncRead(PRUint32 startPosition, PRInt32 readCount, rv = mConnThread->SetStreamListener(listener); if (NS_FAILED(rv)) return rv; - nsAutoCMonitor mon(mConnThread); - mon.Notify(); + mConnThread->Resume(); } else { if (mConnected) return NS_ERROR_ALREADY_CONNECTED; @@ -344,24 +305,21 @@ nsFTPChannel::AsyncRead(PRUint32 startPosition, PRInt32 readCount, if (!mConnThread) return NS_ERROR_OUT_OF_MEMORY; NS_ADDREF(mConnThread); - mThreadRequest = do_QueryInterface((nsISupports*)(nsIRequest*)mConnThread); - - rv = mConnThread->Init(mHandler, this, ctxt, - mBufferSegmentSize, mBufferMaxSize); + rv = mConnThread->Init(mHandler, this, mBufferSegmentSize, mBufferMaxSize); mHandler = 0; if (NS_FAILED(rv)) { NS_RELEASE(mConnThread); return rv; } - rv = mConnThread->SetStreamListener(listener); - if (NS_FAILED(rv)) return rv; + rv = mConnThread->SetStreamListener(listener, ctxt); + if (NS_FAILED(rv)) { + NS_RELEASE(mConnThread); + return rv; + } rv = mPool->DispatchRequest((nsIRunnable*)mConnThread); - NS_RELEASE(mConnThread); - if (NS_FAILED(rv)) return rv; - mConnected = PR_TRUE; } @@ -507,29 +465,6 @@ nsFTPChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallb return NS_OK; } -//////////////////////////////////////////////////////////////////////////////// -// nsPIFTPChannel methods: -NS_IMETHODIMP -nsFTPChannel::SetConnectionQueue(nsIEventQueue *aEventQ) { - nsresult rv = NS_OK; - - 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; - - // change the thread request over to a proxy thread request. - rv = proxyManager->GetProxyObject(aEventQ, - NS_GET_IID(nsIRequest), - mThreadRequest, - PROXY_ASYNC | PROXY_ALWAYS, - getter_AddRefs(mProxiedThreadRequest)); - } - mThreadRequest = 0; - - return rv; -} - NS_IMETHODIMP nsFTPChannel::SetContentLength(PRInt32 aLength) { mContentLength = aLength; @@ -547,9 +482,8 @@ nsFTPChannel::Stopped(nsresult aStatus, const PRUnichar *aMsg) { nsresult rv = NS_OK; // the underlying connection thread has gone away. mConnected = PR_FALSE; - mThreadRequest = 0; - mProxiedThreadRequest = 0; - NS_IF_RELEASE(mConnThread); + NS_ASSERTION(mConnThread, "lost the connection thread"); + NS_RELEASE(mConnThread); if (mLoadGroup) rv = mLoadGroup->RemoveChannel(this, nsnull, aStatus, aMsg); diff --git a/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.h b/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.h index 4de453ca4e8..95d700bc9a8 100644 --- a/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.h +++ b/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.h @@ -26,22 +26,16 @@ #define nsFTPChannel_h___ #include "nsPIFTPChannel.h" -#include "nsIStreamListener.h" #include "nsIURI.h" #include "nsString2.h" -#include "nsIEventQueue.h" #include "nsILoadGroup.h" #include "nsCOMPtr.h" -#include "nsHashtable.h" #include "nsIProtocolHandler.h" #include "nsIProgressEventSink.h" #include "nsIInterfaceRequestor.h" #include "nsIThreadPool.h" -#include "nsIRequest.h" -#include "nsAutoLock.h" #include "nsFtpConnectionThread.h" #include "netCore.h" -#include "nsIProgressEventSink.h" class nsFTPChannel : public nsPIFTPChannel, public nsIInterfaceRequestor, @@ -89,12 +83,10 @@ protected: PRUint32 mSourceOffset; PRInt32 mAmount; nsCOMPtr mLoadGroup; - nsAutoString mContentType; + nsCAutoString mContentType; PRInt32 mContentLength; nsCOMPtr mOwner; - nsCOMPtr mThreadRequest; - nsCOMPtr mProxiedThreadRequest; nsCOMPtr mHandler; nsCOMPtr mPool; // the thread pool we want to use to fire off connections. nsFtpConnectionThread *mConnThread; // the raw pointer to the thread object. diff --git a/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.cpp b/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.cpp index 67332478f8c..b7b16064e88 100644 --- a/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.cpp +++ b/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.cpp @@ -26,25 +26,21 @@ #include "nsIPipe.h" #include "nsIMIMEService.h" #include "nsIStreamConverterService.h" -#include "nsIIOService.h" #include "prprf.h" #include "prlog.h" +#include "prmon.h" #include "netCore.h" #include "ftpCore.h" #include "nsProxiedService.h" -#include "nsAutoLock.h" #include "nsCRT.h" #include "nsIInterfaceRequestor.h" +#include "nsFTPListener.h" #include "nsAppShellCIDs.h" // TODO remove later #include "nsIAppShellService.h" // TODO remove later #include "nsIWebShellWindow.h" // TODO remove later #include "nsINetPrompt.h" -#include "nsFtpProtocolHandler.h" -#include "nsPIFTPChannel.h" - -static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); static NS_DEFINE_CID(kStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID); static NS_DEFINE_CID(kMIMEServiceCID, NS_MIMESERVICE_CID); static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); @@ -53,60 +49,126 @@ static NS_DEFINE_CID(kAppShellServiceCID, NS_APPSHELL_SERVICE_CID); static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID); static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID); -static NS_DEFINE_CID(kFTPHandlerCID, NS_FTPPROTOCOLHANDLER_CID); #if defined(PR_LOGGING) extern PRLogModuleInfo* gFTPLog; #endif /* PR_LOGGING */ -NS_IMPL_ISUPPORTS2(nsFtpConnectionThread, nsIRunnable, nsIRequest); + +class nsFTPAsyncReadEvent { +public: + nsFTPAsyncReadEvent(nsIChannel *aChannel, + nsIStreamListener *aListener, + nsISupports *aContext); + virtual ~nsFTPAsyncReadEvent(); + + nsresult Fire(nsIEventQueue* aEventQ); + nsresult HandleEvent(); + +protected: + static void PR_CALLBACK HandlePLEvent(PLEvent* aEvent); + static void PR_CALLBACK DestroyPLEvent(PLEvent* aEvent); + + nsCOMPtr mChannel; + nsCOMPtr mListener; + nsCOMPtr mContext; + PLEvent *mEvent; +}; + +//////////////////////////////////////////////////////////////////////////////// + +nsFTPAsyncReadEvent::nsFTPAsyncReadEvent(nsIChannel *aChannel, + nsIStreamListener *aListener, + nsISupports *aContext) + : mChannel(aChannel), mListener(aListener), mContext(aContext), mEvent(nsnull) +{} + +nsFTPAsyncReadEvent::~nsFTPAsyncReadEvent() { + if (mEvent) { + delete mEvent; + mEvent = nsnull; + } +} + +nsresult +nsFTPAsyncReadEvent::HandleEvent() { + return mChannel->AsyncRead(0, -1, mContext, mListener); +} + +void PR_CALLBACK +nsFTPAsyncReadEvent::HandlePLEvent(PLEvent* aEvent) { + nsFTPAsyncReadEvent *ev = (nsFTPAsyncReadEvent*) PL_GetEventOwner(aEvent); + NS_ASSERTION(nsnull != ev,"null event."); + ev->HandleEvent(); +} + +void PR_CALLBACK +nsFTPAsyncReadEvent::DestroyPLEvent(PLEvent* aEvent) { + nsFTPAsyncReadEvent *ev = (nsFTPAsyncReadEvent*) PL_GetEventOwner(aEvent); + NS_ASSERTION(nsnull != ev,"null event."); + delete ev; +} + +nsresult +nsFTPAsyncReadEvent::Fire(nsIEventQueue* aEventQueue) { + NS_PRECONDITION(nsnull != aEventQueue, "nsIEventQueue for thread is null"); + NS_PRECONDITION(nsnull == mEvent, "Init plevent only once."); + mEvent = new PLEvent; + if (!mEvent) return NS_ERROR_OUT_OF_MEMORY; + + PL_InitEvent(mEvent, + this, + (PLHandleEventProc) nsFTPAsyncReadEvent::HandlePLEvent, + (PLDestroyEventProc) nsFTPAsyncReadEvent::DestroyPLEvent); + + PRStatus status = aEventQueue->PostEvent(mEvent); + return status == PR_SUCCESS ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMPL_ISUPPORTS3(nsFtpConnectionThread, nsIRunnable, nsIRequest, nsIStreamObserver); nsFtpConnectionThread::nsFtpConnectionThread() { NS_INIT_REFCNT(); - mSTS = nsnull; + // bool init + mConnected = mResetMode = mList = mRetryPass = mCachedConn = mSentStart = PR_FALSE; + mUsePasv = mBin = mKeepRunning = mAnonymous = PR_TRUE; + mAction = GET; - mUsePasv = PR_TRUE; mState = FTP_S_USER; mNextState = FTP_S_USER; - mBin = PR_TRUE; mLength = -1; - mConnected = PR_FALSE; - mResetMode = PR_FALSE; - mList = PR_FALSE; - mKeepRunning = PR_TRUE; - mContinueRead = PR_FALSE; - mAnonymous = PR_TRUE; - mRetryPass = PR_FALSE; - mCachedConn = PR_FALSE; - mInternalError = NS_OK; // start out on the up 'n up. - mSentStart = PR_FALSE; + + mInternalError = NS_OK; mConn = nsnull; mSuspendCount = 0; - mPort = 21; // default FTP port + mPort = 21; + + mLock = nsnull; + mMonitor = nsnull; } nsFtpConnectionThread::~nsFtpConnectionThread() { - // lose the socket transport - NS_IF_RELEASE(mSTS); PR_LOG(gFTPLog, PR_LOG_ALWAYS, ("~nsFtpConnectionThread() called")); + if (mLock) { + PR_DestroyLock(mLock); + mLock = nsnull; + } + + if (mMonitor) { + PR_DestroyMonitor(mMonitor); + mMonitor = nsnull; + } } nsresult nsFtpConnectionThread::Process() { - nsresult rv; + nsresult rv = NS_OK; + PRBool continueRead = PR_FALSE; PR_LOG(gFTPLog, PR_LOG_DEBUG, ("nsFtpConnectionThread::Process() started for %x (spec =%s)\n", mURL.get(), (const char *) mURLSpec)); while (mKeepRunning) { - - // churn the event pump - PLEvent *event; - rv = mFTPEventQueue->GetEvent(&event); - if (NS_FAILED(rv)) return rv; - rv = mFTPEventQueue->HandleEvent(event); - if (NS_FAILED(rv)) return rv; - switch(mState) { ////////////////////////////// @@ -135,26 +197,24 @@ nsFtpConnectionThread::Process() { PR_LOG(gFTPLog, PR_LOG_DEBUG, ("%x Process() - READ_BUF - read \"%s\" (%d bytes)", mURL.get(), buffer, read)); // get the response code out. - if (!mContinueRead) { + if (!continueRead) { PR_sscanf(buffer, "%d", &mResponseCode); mResponseCode = mResponseCode / 100; // truncate it } // see if we're handling a multi-line response. - if (mContinueRead || (buffer[3] == '-')) { + if (continueRead || (buffer[3] == '-')) { // yup, multi-line response, start appending char *tmpBuffer = buffer, *crlf = nsnull; PRBool lastLine = PR_FALSE; while ( (crlf = PL_strstr(tmpBuffer, CRLF)) ) { - if (crlf) { - char tmpChar = crlf[2]; - crlf[2] = '\0'; - // see if this is the last line - lastLine = tmpBuffer[3] != '-'; - mResponseMsg += tmpBuffer+4; // skip over the code and '-' - crlf[2] = tmpChar; - tmpBuffer = crlf+2; - } + char tmpChar = crlf[2]; + crlf[2] = '\0'; + // see if this is the last line + lastLine = tmpBuffer[3] != '-'; + mResponseMsg += tmpBuffer+4; // skip over the code and '-' + crlf[2] = tmpChar; + tmpBuffer = crlf+2; } if (*tmpBuffer) mResponseMsg += tmpBuffer+4; @@ -169,10 +229,10 @@ nsFtpConnectionThread::Process() { } else { mState = mNextState; } - mContinueRead = PR_FALSE; + continueRead = PR_FALSE; } else { // don't increment state, we need to read more. - mContinueRead = PR_TRUE; + continueRead = PR_TRUE; } break; } @@ -190,83 +250,6 @@ nsFtpConnectionThread::Process() { } // END: FTP_READ_BUF - case FTP_READ_DATA_BUF: - { - PRUint32 read = 0, readSoFar = 0; - - if (mCallerOutputStream) { - // we have an output stream, write data to it - // rather than sending OnDataAvailable() calls. - - while (readSoFar < NS_FTP_BUFFER_READ_SIZE) { - rv = mCallerOutputStream->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) { - // EOF - mCallerOutputStream->Close(); - - mState = FTP_READ_BUF; - mNextState = FTP_COMPLETE; - break; - } - } - } else { - NS_ASSERTION(mListener, "FTP: conn thread listener DNE"); - // no output stream. shuttle data over using the listener - while (readSoFar < NS_FTP_BUFFER_READ_SIZE) { - PRUint32 avail = 0; - rv = mBufInStream->Available(&avail); - if (NS_FAILED(rv)) return rv; - - // suck in the data from the server - 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; - } - } - } // end mCallerOutputStream - break; - } - // END: FTP_READ_DATA_BUF - case FTP_ERROR: { PR_LOG(gFTPLog, PR_LOG_DEBUG, ("%x Process() - ERROR\n", mURL.get())); @@ -297,7 +280,6 @@ nsFtpConnectionThread::Process() { } // END: FTP_COMPLETE - ////////////////////////////// //// CONNECTION SETUP STATES ////////////////////////////// @@ -572,15 +554,6 @@ nsFtpConnectionThread::Process() { PR_LOG(gFTPLog, PR_LOG_DEBUG, ("FAILED\n")); } else { PR_LOG(gFTPLog, PR_LOG_DEBUG, ("SUCCEEDED\n")); - // get the data channel ready - PR_LOG(gFTPLog, PR_LOG_DEBUG, ("%x Process() - S_LIST - Opening data stream ", mURL.get())); - rv = mDPipe->OpenInputStream(0, -1, getter_AddRefs(mDInStream)); - if (NS_FAILED(rv)) { - PR_LOG(gFTPLog, PR_LOG_DEBUG, ("FAILED\n")); - return rv; - } - PR_LOG(gFTPLog, PR_LOG_DEBUG, ("SUCCEEDED\n")); - mState = FTP_READ_BUF; mNextState = FTP_R_LIST; } @@ -591,9 +564,12 @@ nsFtpConnectionThread::Process() { case FTP_R_LIST: { mState = R_list(); - if (FTP_ERROR == mState) - mInternalError = NS_ERROR_FAILURE; - mNextState = FTP_COMPLETE; + if (FTP_ERROR == mState) { + mInternalError = rv; + mNextState = FTP_ERROR; + } else { + mNextState = FTP_COMPLETE; + } break; } // END: FTP_R_LIST @@ -608,15 +584,6 @@ nsFtpConnectionThread::Process() { PR_LOG(gFTPLog, PR_LOG_DEBUG, ("FAILED\n")); } else { PR_LOG(gFTPLog, PR_LOG_DEBUG, ("SUCCEEDED\n")); - // get the data channel ready - PR_LOG(gFTPLog, PR_LOG_DEBUG, ("%x Process() - S_RETR - Opening data stream ", mURL.get())); - rv = mDPipe->OpenInputStream(0, -1, getter_AddRefs(mDInStream)); - if (NS_FAILED(rv)) { - PR_LOG(gFTPLog, PR_LOG_DEBUG, ("FAILED\n")); - return rv; - } - PR_LOG(gFTPLog, PR_LOG_DEBUG, ("SUCCEEDED\n")); - mState = FTP_READ_BUF; mNextState = FTP_R_RETR; } @@ -658,8 +625,13 @@ nsFtpConnectionThread::Process() { case FTP_R_PASV: { mState = R_pasv(); + PLEvent *event = nsnull; + if ( NS_FAILED(mFTPEventQueue->WaitForEvent(&event)) + || NS_FAILED(mFTPEventQueue->HandleEvent(event))) return rv; + if (FTP_ERROR == mState) mInternalError = NS_ERROR_FTP_PASV; + mNextState = FTP_READ_BUF; break; } // END: FTP_R_PASV @@ -757,55 +729,26 @@ nsFtpConnectionThread::Process() { return NS_OK; } -nsresult -nsFtpConnectionThread::SetOutputStream(nsIBufferOutputStream* aOutputStream) { - if (mCallerOutputStream) return NS_ERROR_FAILURE; - mCallerOutputStream = aOutputStream; - return NS_OK; -} - nsresult nsFtpConnectionThread::SetStreamObserver(nsIStreamObserver* aObserver, nsISupports *aContext) { - nsresult rv; - static PRBool streamObserverSet = PR_FALSE; - if (streamObserverSet) return NS_ERROR_FAILURE; + nsresult rv = NS_OK; + if (mConnected) return NS_ERROR_ALREADY_CONNECTED; + mObserverContext = aContext; NS_WITH_SERVICE(nsIProxyObjectManager, pIProxyObjectManager, kProxyObjectManagerCID, &rv); if(NS_FAILED(rv)) return rv; - rv = pIProxyObjectManager->GetProxyObject(nsnull, /* use the main thread's eventQ */ + return pIProxyObjectManager->GetProxyObject(NS_UI_THREAD_EVENTQ, NS_GET_IID(nsIStreamObserver), aObserver, PROXY_ASYNC | PROXY_ALWAYS, getter_AddRefs(mObserver)); - mObserverContext = aContext; - streamObserverSet = PR_TRUE; - return rv; } nsresult -nsFtpConnectionThread::SetStreamListener(nsIStreamListener* aListener) { - nsresult rv; - // stream listeners can be reset at any time. - mListener = 0; - mSyncListener = 0; - - NS_WITH_SERVICE(nsIProxyObjectManager, pIProxyObjectManager, kProxyObjectManagerCID, &rv); - if(NS_FAILED(rv)) return rv; - - rv = pIProxyObjectManager->GetProxyObject(nsnull, - NS_GET_IID(nsIStreamListener), - aListener, - PROXY_ASYNC | PROXY_ALWAYS, - getter_AddRefs(mListener)); - if (NS_FAILED(rv)) return rv; - - rv = pIProxyObjectManager->GetProxyObject(nsnull, - NS_GET_IID(nsIStreamListener), - aListener, - PROXY_SYNC | PROXY_ALWAYS, - getter_AddRefs(mSyncListener)); - if (NS_FAILED(rv)) return rv; - +nsFtpConnectionThread::SetStreamListener(nsIStreamListener* aListener, nsISupports *aContext) { + nsresult rv = NS_OK; + mListener = aListener; + mListenerContext = aContext; return NS_OK; } @@ -823,20 +766,20 @@ nsFtpConnectionThread::S_user() { } else { if (!mUsername.Length()) { - NS_WITH_SERVICE(nsIAppShellService, appshellservice, kAppShellServiceCID, &rv); - if (NS_FAILED(rv)) return rv; + NS_WITH_SERVICE(nsIAppShellService, appshellservice, kAppShellServiceCID, &rv); + if (NS_FAILED(rv)) return rv; - nsCOMPtr webshellwindow; - appshellservice->GetHiddenWindow(getter_AddRefs( webshellwindow ) ); - nsCOMPtr prompter( do_QueryInterface( webshellwindow ) ); + nsCOMPtr webshellwindow; + appshellservice->GetHiddenWindow(getter_AddRefs( webshellwindow ) ); + nsCOMPtr prompter( do_QueryInterface( webshellwindow ) ); - NS_WITH_SERVICE(nsIProxyObjectManager, pIProxyObjectManager, kProxyObjectManagerCID, &rv); - if(NS_FAILED(rv)) { - return rv; - } - nsINetPrompt* proxyprompter = NULL; - rv = pIProxyObjectManager->GetProxyObject - (NS_UI_THREAD_EVENTQ, nsINetPrompt::GetIID(), prompter, PROXY_SYNC, (void**)&proxyprompter); + NS_WITH_SERVICE(nsIProxyObjectManager, pIProxyObjectManager, kProxyObjectManagerCID, &rv); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr proxyprompter; + rv = pIProxyObjectManager->GetProxyObject(NS_UI_THREAD_EVENTQ, + NS_GET_IID(nsINetPrompt), prompter, + PROXY_SYNC, getter_AddRefs(proxyprompter)); PRUnichar *user = nsnull, *passwd = nsnull; PRBool retval; static nsAutoString message; @@ -849,7 +792,6 @@ nsFtpConnectionThread::S_user() { } rv = proxyprompter->PromptUsernameAndPassword(host, NULL, message.GetUnicode(), &user, &passwd, &retval); - proxyprompter->Release(); // Must be done as not managed for you. // if the user canceled or didn't supply a username we want to fail if (!retval || (user && !*user) ) return NS_ERROR_FAILURE; @@ -900,20 +842,20 @@ nsFtpConnectionThread::S_pass() { } else { if (!mPassword.Length() || mRetryPass) { // ignore any password we have, it's not working - NS_WITH_SERVICE(nsIAppShellService, appshellservice, kAppShellServiceCID, &rv); - if (NS_FAILED(rv)) return rv; + NS_WITH_SERVICE(nsIAppShellService, appshellservice, kAppShellServiceCID, &rv); + if (NS_FAILED(rv)) return rv; - nsCOMPtr webshellwindow; - appshellservice->GetHiddenWindow(getter_AddRefs( webshellwindow ) ); - nsCOMPtr prompter( do_QueryInterface( webshellwindow ) ); + nsCOMPtr webshellwindow; + appshellservice->GetHiddenWindow(getter_AddRefs( webshellwindow ) ); + nsCOMPtr prompter( do_QueryInterface( webshellwindow ) ); - NS_WITH_SERVICE(nsIProxyObjectManager, pIProxyObjectManager, kProxyObjectManagerCID, &rv); - if(NS_FAILED(rv)) { - return rv; - } - nsINetPrompt* proxyprompter = NULL; - rv = pIProxyObjectManager->GetProxyObject - (NS_UI_THREAD_EVENTQ, nsINetPrompt::GetIID(), prompter, PROXY_SYNC, (void**)&proxyprompter); + NS_WITH_SERVICE(nsIProxyObjectManager, pIProxyObjectManager, kProxyObjectManagerCID, &rv); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr proxyprompter; + rv = pIProxyObjectManager->GetProxyObject(NS_UI_THREAD_EVENTQ, + NS_GET_IID(nsINetPrompt), prompter, + PROXY_SYNC, getter_AddRefs(proxyprompter)); PRUnichar *passwd = nsnull; PRBool retval; static nsAutoString message; @@ -938,7 +880,6 @@ nsFtpConnectionThread::S_pass() { } rv = proxyprompter->PromptPassword(userAtHostC, NULL, message.GetUnicode(), &passwd, &retval); nsCRT::free(userAtHostC); - proxyprompter->Release(); // Must be done as not managed for you. // we want to fail if the user canceled or didn't enter a password. if (!retval || (passwd && !*passwd) ) @@ -1321,6 +1262,7 @@ nsFtpConnectionThread::R_mdtm() { nsresult nsFtpConnectionThread::S_list() { + nsresult rv; char *buffer; PRUint32 bytes; if (mList) @@ -1330,19 +1272,9 @@ nsFtpConnectionThread::S_list() { PR_LOG(gFTPLog, PR_LOG_DEBUG, ("%x Writing \"%s\"\n", mURL.get(), buffer)); - return mCOutStream->Write(buffer, PL_strlen(buffer), &bytes); -} + rv = mCOutStream->Write(buffer, PL_strlen(buffer), &bytes); + if (NS_FAILED(rv)) return rv; -FTP_STATE -nsFtpConnectionThread::R_list() { - nsresult rv; - - if ((mResponseCode == 4) - || - (mResponseCode == 5)) { - // unable to open the data connection. - return FTP_ERROR; - } // setup a listener to push the data into. This listener sits inbetween the // unconverted data of fromType, and the final listener in the chain (in this case @@ -1350,89 +1282,43 @@ nsFtpConnectionThread::R_list() { nsCOMPtr converterListener; NS_WITH_SERVICE(nsIStreamConverterService, StreamConvService, kStreamConverterServiceCID, &rv); - if (NS_FAILED(rv)) { - return FTP_ERROR; - } + if (NS_FAILED(rv)) return rv; nsAutoString fromStr("text/ftp-dir-"); SetDirMIMEType(fromStr); - - // all FTP directory listings are converted to http-index nsAutoString toStr("application/http-index-format"); - if (mCallerOutputStream) { - nsCOMPtr convertedStream; - rv = StreamConvService->Convert(mDInStream, - fromStr.GetUnicode(), - toStr.GetUnicode(), - mURL, - getter_AddRefs(convertedStream)); - if (NS_FAILED(rv)) return FTP_ERROR; + rv = StreamConvService->AsyncConvertData(fromStr.GetUnicode(), toStr.GetUnicode(), + mListener, mURL, getter_AddRefs(converterListener)); + if (NS_FAILED(rv)) return rv; + + nsFTPListener *FTPListener = new nsFTPListener(converterListener, mChannel); + if (!FTPListener) return rv; - mDInStream->Close(); - mDInStream = 0; + nsFTPAsyncReadEvent *event = new nsFTPAsyncReadEvent(mDPipe, + FTPListener, + mListenerContext); + if (!event) return NS_ERROR_OUT_OF_MEMORY; - mDInStream = convertedStream; - return FTP_READ_DATA_BUF; - } else { - rv = StreamConvService->AsyncConvertData(fromStr.GetUnicode(), - toStr.GetUnicode(), - mSyncListener, - mURL, getter_AddRefs(converterListener)); - if (NS_FAILED(rv)) { - return FTP_ERROR; - } + return event->Fire(mUIEventQ); +} - rv = converterListener->OnStartRequest(mChannel, mContext); - if (NS_FAILED(rv)) return FTP_ERROR; - - mSentStart = PR_TRUE; - - // The only way out of this loop is if the stream read - // fails or we read the end of the stream. - while (1) { - PRUint32 read; - char *listBuf = (char*)nsAllocator::Alloc(NS_FTP_BUFFER_READ_SIZE + 1); - if (!listBuf) return FTP_ERROR; - - rv = mDInStream->Read(listBuf, NS_FTP_BUFFER_READ_SIZE, &read); - - if (NS_FAILED(rv)) { - PR_LOG(gFTPLog, PR_LOG_DEBUG, ("%x R_list() data pipe read failed w/ rv = %d\n", mURL.get(), rv)); - nsAllocator::Free(listBuf); - return FTP_ERROR; - } else if (read < 1) { - // EOF - PR_LOG(gFTPLog, PR_LOG_DEBUG, ("%x R_list() data pipe read hit EOF\n", mURL.get())); - nsAllocator::Free(listBuf); - return FTP_READ_BUF; - } - listBuf[read] = '\0'; - - PR_LOG(gFTPLog, PR_LOG_DEBUG, ("%x R_list() data pipe read %d bytes:\n%s\n", mURL.get(), read, listBuf)); - - nsCOMPtr stringStreamSup; - rv = NS_NewCharInputStream(getter_AddRefs(stringStreamSup), listBuf); - if (NS_FAILED(rv)) return FTP_ERROR; - - nsCOMPtr listStream = do_QueryInterface(stringStreamSup, &rv); - - rv = converterListener->OnDataAvailable(mChannel, mContext, listStream, 0, read); - if (NS_FAILED(rv)) return FTP_ERROR; - } +FTP_STATE +nsFtpConnectionThread::R_list() { + nsresult rv = NS_OK; + if ((mResponseCode == 4) + || + (mResponseCode == 5)) { + // unable to open the data connection. + return FTP_ERROR; } - - // NOTE: that we're not firing an OnStopRequest() to the converterListener (the - // stream converter). It (at least this implementation of it) doesn't care - // about stops. FTP_COMPLETE will send the stop. - return FTP_READ_BUF; } nsresult nsFtpConnectionThread::S_retr() { - nsresult rv; + nsresult rv = NS_OK; nsXPIDLCString path; PRUint32 bytes; rv = mURL->GetPath(getter_Copies(path)); @@ -1451,34 +1337,24 @@ nsFtpConnectionThread::S_retr() { PR_LOG(gFTPLog, PR_LOG_DEBUG, ("%x Writing \"%s\"\n", mURL.get(), retrStr.GetBuffer())); rv = mCOutStream->Write(retrStr.GetBuffer(), retrStr.Length(), &bytes); - return rv; -} -#define NS_FTP_SEGMENT_SIZE (2*1024) -#define NS_FTP_BUFFER_SIZE (8*1024) + nsFTPListener *FTPListener = new nsFTPListener(mListener, mChannel); + if (!FTPListener) return NS_ERROR_OUT_OF_MEMORY; + + nsFTPAsyncReadEvent *event = new nsFTPAsyncReadEvent(mDPipe, + FTPListener, + mListenerContext); + if (!event) return NS_ERROR_OUT_OF_MEMORY; + + return event->Fire(mUIEventQ); +} FTP_STATE nsFtpConnectionThread::R_retr() { - nsresult rv; - // The only way we can get here is if we knew we were dealing with - // a file and not a dir listing. This state assumes we're retrieving - // a file! + nsresult rv = NS_OK; if (mResponseCode == 1) { // success. - - // we may not have a listener if we were OpenInputStream()ed. - if (mListener) { - rv = mListener->OnStartRequest(mChannel, mContext); - if (NS_FAILED(rv)) return FTP_ERROR; - mSentStart = PR_TRUE; - } - - rv = NS_NewPipe(getter_AddRefs(mBufInStream), getter_AddRefs(mBufOutStream), - nsnull, NS_FTP_SEGMENT_SIZE, NS_FTP_BUFFER_SIZE); - if (NS_FAILED(rv)) return FTP_ERROR; - - return FTP_READ_DATA_BUF; - + return FTP_READ_BUF; } else { if (mServerType == FTP_VMS_TYPE) { return FTP_ERROR; @@ -1488,7 +1364,6 @@ nsFtpConnectionThread::R_retr() { } } - nsresult nsFtpConnectionThread::S_pasv() { char *buffer = "PASV" CRLF; @@ -1572,20 +1447,16 @@ nsFtpConnectionThread::R_pasv() { getter_AddRefs(mDPipe)); // the data channel if (NS_FAILED(rv)) return FTP_ERROR; + // The FTP connection thread will receive transport leve + // AsyncOpen notifications. + rv = mDPipe->AsyncOpen(this, nsnull); + if (NS_FAILED(rv)) return FTP_ERROR; + // hook ourself up as a proxy for progress notifications nsCOMPtr progressProxy(do_QueryInterface(mChannel)); rv = mDPipe->SetNotificationCallbacks(progressProxy); if (NS_FAILED(rv)) return FTP_ERROR; - - if (mAction == GET) { - // Setup the data channel for file reception - } else { - // get the output stream so we can write to the server - rv = mDPipe->OpenOutputStream(0, getter_AddRefs(mDOutStream)); - if (NS_FAILED(rv)) return FTP_ERROR; - } - // we're connected figure out what type of transfer we're doing (ascii or binary) nsXPIDLCString type; rv = mFTPChannel->GetContentType(getter_Copies(type)); @@ -1595,8 +1466,6 @@ nsFtpConnectionThread::R_pasv() { else typeStr = type; - mContentType = typeStr; - PRInt32 textType = typeStr.Find("text"); if (textType == 0) // only send ascii for text type files @@ -1613,7 +1482,7 @@ nsFtpConnectionThread::S_del_file() { nsXPIDLCString filename; PRUint32 bytes; rv = mURL->GetPath(getter_Copies(filename)); // XXX we should probably check to - // XXX make sure we have an actual filename. + // XXX make sure we have an actual filename. if (NS_FAILED(rv)) return rv; nsCAutoString delStr("DELE "); @@ -1691,7 +1560,8 @@ nsFtpConnectionThread::R_mkdir() { // END: STATE METHODS /////////////////////////////////// - +#define FTP_COMMAND_CHANNEL_SEG_SIZE 64 +#define FTP_COMMAND_CHANNEL_MAX_SIZE 512 //////////////////////////////////////////////////////////////////////////////// // nsIRunnable method: @@ -1709,26 +1579,12 @@ nsFtpConnectionThread::Run() { rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(mFTPEventQueue)); if (NS_FAILED(rv)) return rv; - // we've got to send the event queue for this sucker over to the - // channel's thread so he can post event back to us. - NS_WITH_SERVICE(nsIProxyObjectManager, pIProxyObjectManager, kProxyObjectManagerCID, &rv); - if(NS_FAILED(rv)) return rv; - - nsCOMPtr ftpChannel; - rv = pIProxyObjectManager->GetProxyObject(nsnull, - NS_GET_IID(nsPIFTPChannel), - mChannel, - PROXY_SYNC | PROXY_ALWAYS, - getter_AddRefs(ftpChannel)); + rv = eventQService->GetThreadEventQueue(NS_UI_THREAD, getter_AddRefs(mUIEventQ)); if (NS_FAILED(rv)) return rv; - rv = ftpChannel->SetConnectionQueue(mFTPEventQueue); - if (NS_FAILED(rv)) return rv; - - rv = nsServiceManager::GetService(kSocketTransportServiceCID, NS_GET_IID(nsISocketTransportService), - (nsISupports **)&mSTS); + getter_AddRefs(mSTS)); if(NS_FAILED(rv)) return rv; ///////////////////////// @@ -1757,7 +1613,8 @@ nsFtpConnectionThread::Run() { // build our own rv = mSTS->CreateTransport(host, mPort, host, - mBufferSegmentSize, mBufferMaxSize, + FTP_COMMAND_CHANNEL_SEG_SIZE, + FTP_COMMAND_CHANNEL_MAX_SIZE, getter_AddRefs(mCPipe)); // the command channel if (NS_FAILED(rv)) return rv; @@ -1778,64 +1635,10 @@ nsFtpConnectionThread::Run() { /////////////////////////////// if (!mCachedConn) { - // digest any server greeting. - char greetBuf[NS_FTP_BUFFER_READ_SIZE]; - for (PRInt32 i=0; i < NS_FTP_BUFFER_READ_SIZE; i++) - greetBuf[i] = '\0'; - PRUint32 read; - rv = mCInStream->Read(greetBuf, NS_FTP_BUFFER_READ_SIZE, &read); - if (NS_FAILED(rv)) { - PR_LOG(gFTPLog, PR_LOG_DEBUG, ("%x nsFTPConnTrd::Run() greeting read failed with rv = %d\n", mURL.get(), rv)); - return rv; - } - - if (read > 0) { - // we got something. - // look for a response code - switch (greetBuf[0]) { - case '2': - PR_sscanf(greetBuf, "%d", &mResponseCode); - mResponseCode = mResponseCode / 100; // truncate it - - // we're receiving some data - // see if it's multiline - if (greetBuf[3] == '-') { - // yup, multi-line. be sure to digest the rest of it later. - char *tmpBuffer = greetBuf, *crlf = nsnull; - PRBool lastLine = PR_FALSE; - while ( (crlf = PL_strstr(tmpBuffer, CRLF)) ) { - if (crlf) { - char tmpChar = crlf[2]; - crlf[2] = '\0'; - // see if this is the last line - lastLine = tmpBuffer[3] != '-'; - mResponseMsg += tmpBuffer+4; // skip over the code and '-' - crlf[2] = tmpChar; - tmpBuffer = crlf+2; - } - } - if (*tmpBuffer) - mResponseMsg += tmpBuffer+4; - - // see if this was the last line - if (lastLine || (*tmpBuffer && (tmpBuffer[3] != '-')) ) { - // yup. last line, let's move on. - mContinueRead = PR_FALSE; - mState = mNextState; - } else { - //we need to read more. - mContinueRead = PR_TRUE; - mState = FTP_READ_BUF; - } - } - break; - default: - break; - } - } + rv = DigestServerGreeting(); + if (NS_FAILED(rv)) return rv; } else { - // we're already connected to this server. - // skip login. + // we're already connected to this server, skip login. mState = FTP_S_PASV; } @@ -1843,7 +1646,6 @@ nsFtpConnectionThread::Run() { rv = Process(); mListener = 0; - mSyncListener = 0; mChannel = 0; mConnCache = 0; @@ -1858,6 +1660,8 @@ nsFtpConnectionThread::IsPending(PRBool *result) { nsresult rv = NS_OK; *result = PR_FALSE; + nsAutoLock aLock(mLock); + if (mCPipe) { rv = mCPipe->IsPending(result); if (NS_FAILED(rv)) return rv; @@ -1873,6 +1677,8 @@ NS_IMETHODIMP nsFtpConnectionThread::Cancel(void) { nsresult rv = NS_OK; + nsAutoLock aLock(mLock); + if (mCPipe) { rv = mCPipe->Cancel(); if (NS_FAILED(rv)) return rv; @@ -1881,7 +1687,7 @@ nsFtpConnectionThread::Cancel(void) rv = mDPipe->Cancel(); if (NS_FAILED(rv)) return rv; } - mInternalError = NS_ERROR_FAILURE; // XXX should be an FTP code. + mInternalError = NS_ERROR_FAILURE; mState = FTP_COMPLETE; return rv; } @@ -1890,6 +1696,12 @@ NS_IMETHODIMP nsFtpConnectionThread::Suspend(void) { nsresult rv = NS_OK; + nsAutoLock aLock(mLock); + + // suspending the underlying socket transport will + // cause the FTP state machine to "suspend" when it + // tries to use the transport. May not be granular + // enough. if (mSuspendCount < 1) { mSuspendCount++; if (mCPipe) { @@ -1900,10 +1712,6 @@ nsFtpConnectionThread::Suspend(void) rv = mDPipe->Suspend(); if (NS_FAILED(rv)) return rv; } - nsAutoCMonitor mon(this); - mon.Wait(); - // If we're notifiec, let everythign resume. - rv = Resume(); } return rv; @@ -1913,6 +1721,11 @@ NS_IMETHODIMP nsFtpConnectionThread::Resume(void) { nsresult rv = NS_ERROR_FAILURE; + nsAutoLock aLock(mLock); + + // resuming the underlying socket transports will + // cause the FTP state machine to unblock and + // go on about it's business. if (mSuspendCount) { // only a suspended thread can be resumed if (mCPipe) { @@ -1926,27 +1739,44 @@ nsFtpConnectionThread::Resume(void) rv = NS_OK; } mSuspendCount--; - return rv; } +// nsIStreamObserver methods +NS_IMETHODIMP +nsFtpConnectionThread::OnStartRequest(nsIChannel *aChannel, nsISupports *aContext) { + mState = FTP_S_MODE; // bump to the next state. + return NS_OK; +} + +NS_IMETHODIMP +nsFtpConnectionThread::OnStopRequest(nsIChannel *aChannel, nsISupports *aContext, + nsresult aStatus, const PRUnichar *aMsg) { + return NS_OK; +} nsresult nsFtpConnectionThread::Init(nsIProtocolHandler* aHandler, nsIChannel* aChannel, - nsISupports* aContext, PRUint32 bufferSegmentSize, PRUint32 bufferMaxSize) { - nsresult rv; + nsresult rv = NS_OK; + + if (mConnected) return NS_ERROR_ALREADY_CONNECTED; mBufferSegmentSize = bufferSegmentSize; mBufferMaxSize = bufferMaxSize; + mLock = PR_NewLock(); + if (!mLock) return NS_ERROR_OUT_OF_MEMORY; + + mMonitor = PR_NewMonitor(); + if (!mMonitor) return NS_ERROR_OUT_OF_MEMORY; + // parameter validation NS_ASSERTION(aChannel, "FTP: thread needs a channel"); // setup internal member variables mChannel = aChannel; // a straight com ptr to the channel - mContext = aContext; // this is the original caller's context rv = aChannel->GetURI(getter_AddRefs(mURL)); if (NS_FAILED(rv)) return rv; @@ -1990,7 +1820,7 @@ nsFtpConnectionThread::Init(nsIProtocolHandler* aHandler, // This proxied channel is used to set channel related // state on the *real* channel back in the main thread. - rv = pIProxyObjectManager->GetProxyObject(nsnull, + rv = pIProxyObjectManager->GetProxyObject(NS_UI_THREAD_EVENTQ, NS_GET_IID(nsPIFTPChannel), aChannel, PROXY_SYNC | PROXY_ALWAYS, @@ -1999,7 +1829,7 @@ nsFtpConnectionThread::Init(nsIProtocolHandler* aHandler, // get a proxied ptr to the FTP protocol handler service so we can control // the connection cache from here. - rv = pIProxyObjectManager->GetProxyObject(nsnull, + rv = pIProxyObjectManager->GetProxyObject(NS_UI_THREAD_EVENTQ, NS_GET_IID(nsIConnectionCache), aHandler, PROXY_SYNC | PROXY_ALWAYS, @@ -2009,12 +1839,59 @@ nsFtpConnectionThread::Init(nsIProtocolHandler* aHandler, nsresult nsFtpConnectionThread::SetAction(FTP_ACTION aAction) { - if (mConnected) - return NS_ERROR_ALREADY_CONNECTED; + if (mConnected) return NS_ERROR_ALREADY_CONNECTED; mAction = aAction; return NS_OK; } +nsresult +nsFtpConnectionThread::DigestServerGreeting() { + nsresult rv = NS_OK; + char greetBuf[NS_FTP_BUFFER_READ_SIZE+1]; + PRUint32 read = -1; + mResponseCode = 0; + PRBool multiline = PR_FALSE, lastline = PR_FALSE; + + while (1) { + rv = mCInStream->Read(greetBuf, NS_FTP_BUFFER_READ_SIZE, &read); + if (NS_FAILED(rv)) { + PR_LOG(gFTPLog, PR_LOG_DEBUG, ("%x FTP:Digest() greeting read failed with rv = %d\n", mURL.get(), rv)); + return rv; + } + + if (read < 1) break; + greetBuf[read] = '\0'; + + // we got something. look for a response code + if (!mResponseCode) { + PR_sscanf(greetBuf, "%d", &mResponseCode); + mResponseCode = mResponseCode / 100; // truncate it + } + + // first determine whether or not we're dealing with a + // multiline response. + //multiline = greetBuf[3] == '-'; + + // handle all the lines we Read() + char *buf = greetBuf, *lineEnd = nsnull; + while ( (lineEnd = PL_strstr(buf, CRLF)) ) { + char tmpChar = lineEnd[2]; + lineEnd[2] = '\0'; + mResponseMsg += buf+4; + lastline = buf[3] != '-'; // look for last line indicator + lineEnd[2] = tmpChar; + buf = lineEnd+2; // move to the next line + } + + if (lineEnd && lineEnd[4]) + mResponseMsg += lineEnd+4; + + if (lastline) break; + } + + return rv; +} + nsresult nsFtpConnectionThread::StopProcessing() { @@ -2035,24 +1912,10 @@ nsFtpConnectionThread::StopProcessing() { if (NS_FAILED(rv)) return rv; } - rv = mFTPChannel->Stopped(mInternalError, errorMsg); if (NS_FAILED(rv)) return rv; - // if we have a listener, end the transaction. - if (mListener) { - // 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) { - rv = mListener->OnStartRequest(mChannel, mContext); - if (NS_FAILED(rv)) return rv; - } - - rv = mListener->OnStopRequest(mChannel, mContext, mInternalError, errorMsg); - if (NS_FAILED(rv)) return rv; - } - - // if we have an observer, end hte transaction + // if we have an observer, end the transaction if (mObserver) { rv = mObserver->OnStopRequest(mChannel, mObserverContext, mInternalError, errorMsg); } @@ -2143,7 +2006,6 @@ nsFtpConnectionThread::FindGetState(void) { if (mServerType == FTP_VMS_TYPE) { // check for directory if (!path[0] || (path[0] == '/' && !path[1]) ) { - mDirectory = PR_TRUE; result = FTP_S_LIST; } else if (!PL_strchr(path, '/')) { @@ -2153,7 +2015,6 @@ nsFtpConnectionThread::FindGetState(void) { result = FTP_S_CWD; } } else { - // XXX I've removed the check for "aleady tried RETR" if (path[PL_strlen(path) -1] == '/') { result = FTP_S_CWD; } else { @@ -2250,4 +2111,3 @@ nsFtpConnectionThread::SetDirMIMEType(nsString& aString) { aString.Append("generic"); } } - diff --git a/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.h b/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.h index 2ed42442742..55427c3dc70 100644 --- a/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.h +++ b/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.h @@ -25,15 +25,14 @@ #include "nsIThread.h" #include "nsIRunnable.h" -#include "nsIRequest.h" #include "nsISocketTransportService.h" #include "nsIServiceManager.h" #include "nsIStreamListener.h" #include "nsIURI.h" #include "prtime.h" +#include "prmon.h" #include "nsString2.h" #include "nsIEventQueue.h" -#include "nsHashtable.h" #include "nsPIFTPChannel.h" #include "nsIConnectionCache.h" #include "nsConnectionCacheObj.h" @@ -42,6 +41,7 @@ #include "nsXPIDLString.h" #include "nsIBufferInputStream.h" #include "nsIBufferOutputStream.h" +#include "nsAutoLock.h" // ftp server types #define FTP_GENERIC_TYPE 0 @@ -60,217 +60,167 @@ typedef enum _FTP_STATE { /////////////////////// //// Internal states -/////////////////////// FTP_READ_BUF, - FTP_READ_DATA_BUF, FTP_ERROR, FTP_COMPLETE, /////////////////////// //// Command channel connection setup states -/////////////////////// - FTP_S_USER, // send username - FTP_R_USER, - FTP_S_PASS, // send password - FTP_R_PASS, - FTP_S_SYST, // send system (interrogates server) - FTP_R_SYST, - FTP_S_ACCT, // send account - FTP_R_ACCT, - FTP_S_MACB, - FTP_R_MACB, - FTP_S_PWD , // send parent working directory (pwd) - FTP_R_PWD , - FTP_S_DEL_FILE, // send delete file - FTP_R_DEL_FILE, - FTP_S_DEL_DIR , // send delete directory - FTP_R_DEL_DIR , - FTP_S_MKDIR, // send mkdir - FTP_R_MKDIR, - FTP_S_MODE, // send ASCII or BINARY - FTP_R_MODE, - FTP_S_CWD, // send change working directory - FTP_R_CWD, - FTP_S_SIZE, // send size - FTP_R_SIZE, - FTP_S_PUT, // send STOR to upload the file - FTP_R_PUT, - FTP_S_RETR, // send retrieve to download the file - FTP_R_RETR, - FTP_S_MDTM, // send MDTM to get time information - FTP_R_MDTM, - FTP_S_LIST, // send LIST or NLST (server dependent) to get a dir listing - FTP_R_LIST, - FTP_S_TYPE, // send TYPE to indicate what type of file will be transfered - FTP_R_TYPE, + FTP_S_USER, FTP_R_USER, + FTP_S_PASS, FTP_R_PASS, + FTP_S_SYST, FTP_R_SYST, + FTP_S_ACCT, FTP_R_ACCT, + FTP_S_MACB, FTP_R_MACB, + FTP_S_PWD , FTP_R_PWD , + FTP_S_DEL_FILE, FTP_R_DEL_FILE, + FTP_S_DEL_DIR , FTP_R_DEL_DIR , + FTP_S_MKDIR, FTP_R_MKDIR, + FTP_S_MODE, FTP_R_MODE, + FTP_S_CWD, FTP_R_CWD, + FTP_S_SIZE, FTP_R_SIZE, + FTP_S_PUT, FTP_R_PUT, + FTP_S_RETR, FTP_R_RETR, + FTP_S_MDTM, FTP_R_MDTM, + FTP_S_LIST, FTP_R_LIST, + FTP_S_TYPE, FTP_R_TYPE, /////////////////////// //// Data channel connection setup states -/////////////////////// - FTP_S_PASV, // send passsive - FTP_R_PASV + FTP_S_PASV, FTP_R_PASV } FTP_STATE; // higher level ftp actions -typedef enum _FTP_ACTION { - GET, - PUT, - MKDIR, - DEL -} FTP_ACTION; +typedef enum _FTP_ACTION { GET, PUT, MKDIR, DEL} FTP_ACTION; class nsFtpConnectionThread : public nsIRunnable, - public nsIRequest { + public nsIRequest, + public nsIStreamObserver { public: NS_DECL_ISUPPORTS NS_DECL_NSIRUNNABLE NS_DECL_NSIREQUEST + NS_DECL_NSISTREAMOBSERVER nsFtpConnectionThread(); virtual ~nsFtpConnectionThread(); nsresult Init(nsIProtocolHandler *aHandler, nsIChannel *aChannel, - nsISupports *aContext, PRUint32 bufferSegmentSize, PRUint32 bufferMaxSize); - nsresult Process(); - - // use this to have data written to an output stream (OpenInputStream) - nsresult SetOutputStream(nsIBufferOutputStream *aOutputStream); - // use this to set an observer. (as in the asyncopen case) nsresult SetStreamObserver(nsIStreamObserver *aObserver, nsISupports *aContext); // use this to set a listener to receive data related On*() notifications - nsresult SetStreamListener(nsIStreamListener *aListener); + nsresult SetStreamListener(nsIStreamListener *aListener, nsISupports *aContext=nsnull); // user level setup nsresult SetAction(FTP_ACTION aAction); + private: + /////////////////////////////////// + // BEGIN: STATE METHODS + nsresult S_user(); FTP_STATE R_user(); + nsresult S_pass(); FTP_STATE R_pass(); + nsresult S_syst(); FTP_STATE R_syst(); + nsresult S_acct(); FTP_STATE R_acct(); - /////////////////////////////////// - // STATE METHODS - /////////////////////////////////// - nsresult S_user(); - FTP_STATE R_user(); - nsresult S_pass(); - FTP_STATE R_pass(); - nsresult S_syst(); - FTP_STATE R_syst(); - nsresult S_acct(); - FTP_STATE R_acct(); - nsresult S_macb(); - FTP_STATE R_macb(); - nsresult S_pwd(); - FTP_STATE R_pwd(); - nsresult S_mode(); - FTP_STATE R_mode(); - nsresult S_cwd(); - FTP_STATE R_cwd(); - nsresult S_size(); - FTP_STATE R_size(); - nsresult S_mdtm(); - FTP_STATE R_mdtm(); - nsresult S_list(); - FTP_STATE R_list(); - nsresult S_retr(); - FTP_STATE R_retr(); + nsresult S_macb(); FTP_STATE R_macb(); + nsresult S_pwd(); FTP_STATE R_pwd(); + nsresult S_mode(); FTP_STATE R_mode(); + nsresult S_cwd(); FTP_STATE R_cwd(); - nsresult S_pasv(); - FTP_STATE R_pasv(); - nsresult S_del_file(); - FTP_STATE R_del_file(); - nsresult S_del_dir(); - FTP_STATE R_del_dir(); - nsresult S_mkdir(); - FTP_STATE R_mkdir(); - /////////////////////////////////// + nsresult S_size(); FTP_STATE R_size(); + nsresult S_mdtm(); FTP_STATE R_mdtm(); + nsresult S_list(); FTP_STATE R_list(); + + nsresult S_retr(); FTP_STATE R_retr(); + nsresult S_pasv(); FTP_STATE R_pasv(); + nsresult S_del_file(); FTP_STATE R_del_file(); + nsresult S_del_dir(); FTP_STATE R_del_dir(); + + nsresult S_mkdir(); FTP_STATE R_mkdir(); // END: STATE METHODS /////////////////////////////////// - nsresult StopProcessing(); - void SetSystInternals(void); - FTP_STATE FindActionState(void); - FTP_STATE FindGetState(void); - nsresult MapResultCodeToString(nsresult aResultCode, PRUnichar* *aOutMsg); - void SetDirMIMEType(nsString& aString); + // internal methods + nsresult StopProcessing(); + void SetSystInternals(void); + FTP_STATE FindActionState(void); + FTP_STATE FindGetState(void); + nsresult MapResultCodeToString(nsresult aResultCode, PRUnichar* *aOutMsg); + void SetDirMIMEType(nsString& aString); + nsresult DigestServerGreeting(); + nsresult Process(); + /////////////////////////////////// // Private members - nsCOMPtr mFTPEventQueue; // the eventq for this thread. - nsCOMPtr mURL; - PRInt32 mPort; // the port to connect to - + // ****** state machine vars FTP_STATE mState; // the current state FTP_STATE mNextState; // the next state - FTP_ACTION mAction; // the higher level action (GET/PUT) - - nsISocketTransportService *mSTS; // the socket transport service; - - nsCOMPtr mCPipe; // the command channel transport - nsCOMPtr mDPipe; // the data channel transport - - nsCOMPtr mCOutStream; // command channel output - nsCOMPtr mCInStream; // command channel input - - nsCOMPtr mDOutStream; // data channel output - nsCOMPtr mDInStream; // data channel input - - PRInt32 mResponseCode; // the last command response code. + PRBool mKeepRunning; // thread event loop boolean + PRInt32 mResponseCode; // the last command response code nsCAutoString mResponseMsg; // the last command response text - nsString2 mUsername; - nsString2 mPassword; - nsString2 mFilename; // url filename (if any) - PRInt32 mLength; // length of the file - PRTime mLastModified; // last modified time for file + nsCOMPtr mFTPEventQueue; // the eventq for this thread -// these members should be hung off of a specific transport connection - PRInt32 mServerType; - PRBool mPasv; - PRBool mList; // use LIST instead of NLST - nsCAutoString mCwd; // Our current working dir. - nsCAutoString mCwdAttempt; // the dir we're trying to get into. -// end "these ...." + // ****** channel/transport/stream vars + nsCOMPtr mSTS; // the socket transport service + nsCOMPtr mCPipe; // the command channel transport + nsCOMPtr mDPipe; // the data channel transport + nsCOMPtr mCOutStream; // command channel output + nsCOMPtr mCInStream; // command channel input - nsCAutoString mCacheKey; // the key into the cache hash. + // ****** consumer vars + nsCOMPtr mListener; // the consumer of our read events + nsCOMPtr mListenerContext; // the context we pass through our read events + nsCOMPtr mObserver; // the consumer of our open events + nsCOMPtr mObserverContext; // the context we pass through our open events + nsCOMPtr mChannel; // our owning FTP channel we pass through our events - PRBool mConnected; - PRBool mUsePasv; // use a passive data connection. - PRBool mDirectory; // this url is a directory - PRBool mBin; // transfer mode (ascii or binary) - PRBool mContinueRead; // continue digesting a multi-line reponse - PRBool mResetMode; // have we reset the mode to ascii - PRBool mAnonymous; // try connecting anonymous (default) - PRBool mRetryPass; // retrying the password - PRBool mCachedConn; // is this connection from the cache - PRBool mSentStart; // have we sent an OnStartRequest() notification - PRUint8 mSuspendCount; - nsresult mInternalError; // represents internal state errors + // ****** connection cache vars + PRInt32 mServerType; // What kind of server are we talking to + PRBool mPasv; // Should we use PASV for data channel + PRBool mList; // Use LIST instead of NLST + nsCAutoString mCwd; // Our current working dir. + nsCAutoString mCwdAttempt; // The dir we're trying to get into. + nsCAutoString mCacheKey; // the key into the cache hash. + PRBool mCachedConn; // is this connection from the cache + nsCOMPtr mConnCache;// the nsISupports proxy ptr to our connection cache + nsConnectionCacheObj *mConn; // The cached connection. - nsCOMPtr mListener; // the listener we want to call - // during our event firing. - nsCOMPtr mSyncListener; // a syncronous version of our listener - nsCOMPtr mChannel; - nsCOMPtr mContext; - nsCOMPtr mConnCache; // the nsISupports proxy ptr to the FTP proto handler - nsConnectionCacheObj* mConn; // The cached connection. - PRBool mKeepRunning; // thread event loop boolean + // ****** protocol interpretation related state vars + nsAutoString mUsername; // username + nsAutoString mPassword; // password + FTP_ACTION mAction; // the higher level action (GET/PUT) + PRBool mUsePasv; // use a passive data connection. + PRBool mBin; // transfer mode (ascii or binary) + PRBool mResetMode; // have we reset the mode to ascii + PRBool mAnonymous; // try connecting anonymous (default) + PRBool mRetryPass; // retrying the password + nsresult mInternalError; // represents internal state errors - nsString2 mContentType; // the content type of the data we're dealing w/. - nsXPIDLCString mURLSpec; - nsCOMPtr mFTPChannel; + // ****** URI vars + nsCOMPtr mURL; // the uri we're connecting to + nsXPIDLCString mURLSpec; // raw spec of the url + PRInt32 mPort; // the port to connect to + nsAutoString mFilename; // url filename (if any) + PRInt32 mLength; // length of the file + PRTime mLastModified;// last modified time for file - nsCOMPtr mBufInStream; - nsCOMPtr mBufOutStream; - nsCOMPtr mCallerOutputStream; - - nsCOMPtr mObserver; - nsCOMPtr mObserverContext; - PRUint32 mBufferSegmentSize; - PRUint32 mBufferMaxSize; + // ****** other vars + PRBool mConnected; // are we connected. + PRBool mSentStart; // have we sent an OnStartRequest() notification + PRUint8 mSuspendCount;// number of times we've been suspended. + nsCOMPtr mFTPChannel;// used to synchronize w/ our owning channel. + PRUint32 mBufferSegmentSize; + PRUint32 mBufferMaxSize; + PRLock *mLock; + PRMonitor *mMonitor; + nsCOMPtrmUIEventQ; + PLEvent *mAsyncReadEvent; }; #define NS_FTP_BUFFER_READ_SIZE (8*1024) diff --git a/mozilla/netwerk/protocol/ftp/src/nsFtpModule.cpp b/mozilla/netwerk/protocol/ftp/src/nsFtpModule.cpp index 6c40aed43aa..ccd02efb755 100644 --- a/mozilla/netwerk/protocol/ftp/src/nsFtpModule.cpp +++ b/mozilla/netwerk/protocol/ftp/src/nsFtpModule.cpp @@ -19,226 +19,16 @@ * * Contributor(s): */ -#include "nsCOMPtr.h" -#include "nsIModule.h" + #include "nsIGenericFactory.h" -#include "nsIComponentManager.h" -#include "nsIServiceManager.h" #include "nsFtpProtocolHandler.h" -#include "nscore.h" -static NS_DEFINE_CID(kFtpProtocolHandlerCID, NS_FTPPROTOCOLHANDLER_CID); - -/////////////////////////////////////////////////////////////////////////////// - -class nsFTPModule : public nsIModule -{ -public: - nsFTPModule(); - virtual ~nsFTPModule(); - - NS_DECL_ISUPPORTS - - NS_DECL_NSIMODULE - -protected: - nsresult Initialize(); - - void Shutdown(); - - PRBool mInitialized; - nsCOMPtr mFactory; +static nsModuleComponentInfo gResComponents[] = { + { "The FTP Protocol Handler", + NS_FTPPROTOCOLHANDLER_CID, + NS_NETWORK_PROTOCOL_PROGID_PREFIX "ftp", + nsFtpProtocolHandler::Create + } }; -static NS_DEFINE_IID(kIModuleIID, NS_IMODULE_IID); - -nsFTPModule::nsFTPModule() - : mInitialized(PR_FALSE) -{ - NS_INIT_ISUPPORTS(); -} - -nsFTPModule::~nsFTPModule() -{ - Shutdown(); -} - -NS_IMPL_ISUPPORTS(nsFTPModule, kIModuleIID) - -// Perform our one-time intialization for this module -nsresult -nsFTPModule::Initialize() -{ - if (mInitialized) { - return NS_OK; - } - mInitialized = PR_TRUE; - return NS_OK; -} - -// Shutdown this module, releasing all of the module resources -void -nsFTPModule::Shutdown() -{ - // Release the factory object - mFactory = nsnull; -} - -// Create a factory object for creating instances of aClass. -NS_IMETHODIMP -nsFTPModule::GetClassObject(nsIComponentManager *aCompMgr, - const nsCID& aClass, - const nsIID& aIID, - void** r_classObj) -{ - nsresult rv; - - // Defensive programming: Initialize *r_classObj in case of error below - if (!r_classObj) { - return NS_ERROR_INVALID_POINTER; - } - *r_classObj = NULL; - - // Do one-time-only initialization if necessary - if (!mInitialized) { - rv = Initialize(); - if (NS_FAILED(rv)) { - // Initialization failed! yikes! - return rv; - } - } - - // Choose the appropriate factory, based on the desired instance - // class type (aClass). - nsCOMPtr fact; - if (aClass.Equals(kFtpProtocolHandlerCID)) { - if (!mFactory) { - rv = NS_NewGenericFactory(getter_AddRefs(mFactory), - nsFtpProtocolHandler::Create); - } - fact = mFactory; - } - else { - rv = NS_ERROR_FACTORY_NOT_REGISTERED; -#ifdef DEBUG - char* cs = aClass.ToString(); - printf("+++ nsFTPModule: unable to create factory for %s\n", cs); - nsCRT::free(cs); -#endif - } - - if (fact) { - rv = fact->QueryInterface(aIID, r_classObj); - } - - return rv; -} - -//---------------------------------------- - -struct Components { - const char* mDescription; - const nsID* mCID; - const char* mProgID; -}; - -// The list of components we register -static Components gComponents[] = { - { "FTP Protocol Handler", &kFtpProtocolHandlerCID, - NS_NETWORK_PROTOCOL_PROGID_PREFIX "ftp", }, -}; -#define NUM_COMPONENTS (sizeof(gComponents) / sizeof(gComponents[0])) - -NS_IMETHODIMP -nsFTPModule::RegisterSelf(nsIComponentManager *aCompMgr, - nsIFileSpec* aPath, - const char* registryLocation, - const char* componentType) -{ - nsresult rv = NS_OK; - -#ifdef DEBUG - printf("*** Registering ftp: components\n"); -#endif - - Components* cp = gComponents; - Components* end = cp + NUM_COMPONENTS; - while (cp < end) { - rv = aCompMgr->RegisterComponentSpec(*cp->mCID, cp->mDescription, - cp->mProgID, aPath, PR_TRUE, - PR_TRUE); - if (NS_FAILED(rv)) { -#ifdef DEBUG - printf("nsFTPModule: unable to register %s component => %x\n", - cp->mDescription, rv); -#endif - break; - } - cp++; - } - - return rv; -} - -NS_IMETHODIMP -nsFTPModule::UnregisterSelf(nsIComponentManager* aCompMgr, - nsIFileSpec* aPath, - const char* registryLocation) -{ -#ifdef DEBUG - printf("*** Unregistering ftp: components\n"); -#endif - Components* cp = gComponents; - Components* end = cp + NUM_COMPONENTS; - while (cp < end) { - nsresult rv = aCompMgr->UnregisterComponentSpec(*cp->mCID, aPath); - if (NS_FAILED(rv)) { -#ifdef DEBUG - printf("nsFTPModule: unable to unregister %s component => %x\n", - cp->mDescription, rv); -#endif - } - cp++; - } - - return NS_OK; -} - -NS_IMETHODIMP -nsFTPModule::CanUnload(nsIComponentManager *aCompMgr, PRBool *okToUnload) -{ - if (!okToUnload) { - return NS_ERROR_INVALID_POINTER; - } - *okToUnload = PR_FALSE; - return NS_ERROR_FAILURE; -} - -//---------------------------------------------------------------------- - -static nsFTPModule *gModule = NULL; - -extern "C" NS_EXPORT nsresult NSGetModule(nsIComponentManager *servMgr, - nsIFileSpec* location, - nsIModule** return_cobj) -{ - nsresult rv = NS_OK; - - NS_ASSERTION(return_cobj, "Null argument"); - NS_ASSERTION(gModule == NULL, "nsFTPModule: Module already created."); - - // Create and initialize the module instance - nsFTPModule *m = new nsFTPModule(); - if (!m) { - return NS_ERROR_OUT_OF_MEMORY; - } - - // Increase refcnt and store away nsIModule interface to m in return_cobj - rv = m->QueryInterface(NS_GET_IID(nsIModule), (void**)return_cobj); - if (NS_FAILED(rv)) { - delete m; - m = nsnull; - } - gModule = m; // WARNING: Weak Reference - return rv; -} +NS_IMPL_NSGETMODULE("ftp", gResComponents) \ No newline at end of file diff --git a/mozilla/netwerk/protocol/ftp/src/nsFtpProtocolHandler.cpp b/mozilla/netwerk/protocol/ftp/src/nsFtpProtocolHandler.cpp index accae426160..873e733f373 100644 --- a/mozilla/netwerk/protocol/ftp/src/nsFtpProtocolHandler.cpp +++ b/mozilla/netwerk/protocol/ftp/src/nsFtpProtocolHandler.cpp @@ -20,15 +20,15 @@ * Contributor(s): */ -#include "nspr.h" -#include "nsFTPChannel.h" #include "nsFtpProtocolHandler.h" +#include "nsFTPChannel.h" #include "nsIURL.h" #include "nsCRT.h" #include "nsIComponentManager.h" #include "nsIInterfaceRequestor.h" #include "nsIProgressEventSink.h" #include "nsConnectionCacheObj.h" +#include "prlog.h" #if defined(PR_LOGGING) // @@ -58,16 +58,7 @@ nsFtpProtocolHandler::~nsFtpProtocolHandler() { PR_LOG(gFTPLog, PR_LOG_ALWAYS, ("~nsFtpProtocolHandler() called")); } -NS_IMPL_ADDREF(nsFtpProtocolHandler) -NS_IMPL_RELEASE(nsFtpProtocolHandler) - -NS_INTERFACE_MAP_BEGIN(nsFtpProtocolHandler) - NS_INTERFACE_MAP_ENTRY(nsIProtocolHandler) - NS_INTERFACE_MAP_ENTRY(nsIConnectionCache) - NS_INTERFACE_MAP_ENTRY(nsIObserver) - NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) - NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIProtocolHandler) -NS_INTERFACE_MAP_END +NS_IMPL_ISUPPORTS3(nsFtpProtocolHandler, nsIProtocolHandler, nsIConnectionCache, nsIObserver) NS_METHOD nsFtpProtocolHandler::Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult) @@ -209,7 +200,6 @@ nsFtpProtocolHandler::InsertConn(const char *aKey, nsConnectionCacheObj *aConn) // cleans up a connection list entry PRBool CleanupConnEntry(nsHashKey *aKey, void *aData, void *closure) { - // XXX do we need to explicitly close the streams? delete (nsConnectionCacheObj*)aData; return PR_TRUE; } diff --git a/mozilla/netwerk/protocol/ftp/src/nsFtpProtocolHandler.h b/mozilla/netwerk/protocol/ftp/src/nsFtpProtocolHandler.h index d3eccd16f09..cb91c28d0c7 100644 --- a/mozilla/netwerk/protocol/ftp/src/nsFtpProtocolHandler.h +++ b/mozilla/netwerk/protocol/ftp/src/nsFtpProtocolHandler.h @@ -26,13 +26,10 @@ #include "nsIServiceManager.h" #include "nsIProtocolHandler.h" #include "nsHashtable.h" -#include "nsVoidArray.h" #include "nsIConnectionCache.h" #include "nsConnectionCacheObj.h" #include "nsIThreadPool.h" #include "nsIObserverService.h" -#include "nsIObserver.h" -#include "nsWeakReference.h" // {25029490-F132-11d2-9588-00805F369F95} #define NS_FTPPROTOCOLHANDLER_CID \ @@ -40,19 +37,12 @@ class nsFtpProtocolHandler : public nsIProtocolHandler, public nsIConnectionCache, - public nsIObserver, - public nsSupportsWeakReference + public nsIObserver { public: NS_DECL_ISUPPORTS - - // nsIProtocolHandler methods: NS_DECL_NSIPROTOCOLHANDLER - - // nsIConnectionCache methods NS_DECL_NSICONNECTIONCACHE - - // nsIObserver methods NS_DECL_NSIOBSERVER // nsFtpProtocolHandler methods: @@ -60,17 +50,15 @@ public: virtual ~nsFtpProtocolHandler(); // Define a Create method to be used with a factory: - static NS_METHOD - Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult); + static NS_METHOD Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult); nsresult Init(); protected: - nsISupports* mEventSinkGetter; - nsHashtable* mRootConnectionList; // hash of FTP connections - nsCOMPtr mPool; // thread pool for FTP connections + nsHashtable* mRootConnectionList; // hash of FTP connections + nsCOMPtr mPool; // thread pool for FTP connections }; -#define NS_FTP_CONNECTION_COUNT 6 +#define NS_FTP_CONNECTION_COUNT 4 #define NS_FTP_CONNECTION_STACK_SIZE (64 * 1024) #endif /* nsFtpProtocolHandler_h___ */